I am building an email automation application to login to a mailbox, extract text and sort the emails etc. I am trying to use the MailKit library but running into some issues logging into the inbox which is a Microsoft 365 tenant.
I have worked through the registration of the app within Microsoft Infra that is listed in the documentation for Microsoft.Indentity.Client
I am using the following code from MailKit’s GitHub.
var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create("xxxx")
.WithAuthority($"https://login.microsoftonline.com/{"xxxxx"}/v2.0")
.WithClientSecret("xxxx")
.Build();
var scopes = new string[] {
"https://ps.outlook.com/.default"
};
var authToken = await confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync();
var oauth2 = new SaslMechanismOAuth2(username, authToken.AccessToken);
using (var client = new ImapClient())
{
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);
await client.AuthenticateAsync(oauth2);
await client.DisconnectAsync(true);
}
I am now getting back an Access Token with the assigned scope from this line
var authToken = await confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync();
But when it is processed by MailKit, this object shows that it is not authenticated
var oauth2
and this line throws an Authentication Failed Error.
await client.AuthenticateAsync(oauth2);
I have used the code sample that pops up a Microsoft login to authenticate and everything works fine, so the mailbox setup seems to be ok with imap, but I cannot figure out what could be wrong.
Can anyone point me in the right direction as to how I can breakdown the AuthToken object to look for issues, or to get more information from the authentication failure?
here is the code that does work, albeit with a popup microsoft authenticator.
var options = new PublicClientApplicationOptions
{
ClientId = "xxxxx",
TenantId = "xxxxx",
RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient"
};
var publicClientApplication = PublicClientApplicationBuilder
.CreateWithApplicationOptions(options)
.Build();
var scopes = new string[] {
"email",
"offline_access",
"https://outlook.office.com/IMAP.AccessAsUser.All", // Only needed for IMAP
};
var authToken = await publicClientApplication.AcquireTokenInteractive(scopes).ExecuteAsync();
var oauth2 = new SaslMechanismOAuth2(authToken.Account.Username, authToken.AccessToken);
using (var client = new ImapClient())
{
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);
await client.AuthenticateAsync(oauth2);
await client.DisconnectAsync(true);
}
This however is not an option since this program will basically run as a scheduled task on a server somewhere.
Hope I have explained it well enough.
Thanks,
pfreeman is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.