0
votes

Trying to connect to Hotmail using OAuth via Mailkit Imap.

I have tried to fetch emails with Microsoft's Graph API, it works, I can connect to Hotmails, fetching emails. So this proves that my configuration on Azure is fine.

When using Mailkit, here is the code:

    private async Task ConnectAndAuthenticateAsync()
    {
        SaslMechanismOAuth2 oauth2 = null;

        try
        {
            if (imapClient.IsConnected == false || imapClient.IsAuthenticated == false)
            {
                oauth2 = await GetOutlookCredentials();
                // outlook.office365.com imap-mail.outlook.com
                //imapClient.AuthenticationMechanisms.Clear();
                await imapClient.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);
                await imapClient.AuthenticateAsync(oauth2);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw ex;
        }

    }

   public async Task<SaslMechanismOAuth2> GetOutlookCredentials()
    {
        var response = new List<string>();

        var consoleCallback = new LogCallback((logLevel, message, bol) =>
        {
            response.Add(message);
            Console.WriteLine(message);
        });

        string authorityFormat = "https://login.microsoftonline.com/{0}/v2.0";
        string tenantId = "common";
        string redirectUri = "https://localhost:44394/";

        var scopes = new string[] { "https://outlook.office365.com/.default" };

        IConfidentialClientApplication app;
        var clientId = "xxxxx";

        app = ConfidentialClientApplicationBuilder.Create(clientId)
            .WithClientSecret("xxxxxx")
            .WithTenantId(tenantId)
            .WithRedirectUri(redirectUri)
            .WithLogging(consoleCallback)
            .Build();
        AuthenticationResult result = null;
        try
        {
            result = await app?.AcquireTokenForClient(scopes)?.ExecuteAsync();
        }
        catch (Exception ex)
        {
            response.Add($"{Environment.NewLine}==>{ex.Message}");
        }

        SaslMechanismOAuth2 oauth = new SaslMechanismOAuth2(clientId, result.AccessToken);
        return oauth;
    }

Here is the Mailkit log:

Connected to imaps://imap-mail.outlook.com:993/
S: * OK The Microsoft Exchange IMAP4 service is ready. [TQBFAEEAUABSADAAMQBDAEEAMAAwADkANgAuAGEAdQBzAHAAcgBkADAAMQAuAHAAcgBvAGQALgBvAHUAdABsAG8AbwBrAC4AYwBvAG0A]
C: A00000000 CAPABILITY S: * CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+ 
S: A00000000 OK CAPABILITY completed.
C: A00000001 AUTHENTICATE XOAUTH2 dXNlcj0yODg4YmIxZi1jOTI1LTRjNzQtYjlhMi02ZmY4MDA4NzQ4MTIBYXV0aD1CZWFyZXIgZXlKMGVYQWlPaUpLVjFRaUxDSnViMjVqWlNJNkluVmtla1JQTXpreGRtTm1jSEpCYlZJd2NWTnZlbFYzZUZsa2IyZHNZbk5DT0RORloxVlhPRU5rUTFFaUxDSmhiR2NpT2lKU1V6STFOaUlzSW5nMWRDSTZJbGxOUlV4SVZEQm5kbUl3YlhodlUwUnZXV1p2YldweFptcFpWU0lzSW10cFpDSTZJbGxOUlV4SVZEQm5kbUl3YlhodlUwUnZXV1p2YldweFptcFpWU0o5LmV5SmhkV1FpT2lKb2RIUndjem92TDI5MWRHeHZiMnN1YjJabWFXTmxNelkxTG1OdmJTSXNJbWx6Y3lJNkltaDBkSEJ6T2k4dmMzUnpMbmRwYm1SdmQzTXVibVYwTDJZNFkyUmxaak14TFdFek1XVXROR0kwWVMwNU0yVTBMVFZtTlRjeFpUa3hNalUxWVM4aUxDSnBZWFFpT2pFMU9EWXhOakF6Tmprc0ltNWlaaUk2TVRVNE5qRTJNRE0yT1N3aVpYaHdJam94TlRnMk1UWTBNalk1TENKaGFXOGlPaUkwTW1SbldVeHFURXR1Y0VjMWRuWnpNVzlRV0dGdU1XNDNkbWcxUWtGQlBTSXNJbUZ3Y0Y5a2FYTndiR0Y1Ym1GdFpTSTZJbEJoY0dGNVpXVWlMQ0poY0hCcFpDSTZJakk0T0RoaVlqRm1MV001TWpVdE5HTTNOQzFpT1dFeUxUWm1aamd3TURnM05EZ3hNaUlzSW1Gd2NHbGtZV055SWpvaU1TSXNJbWxrY0NJNkltaDBkSEJ6T2k4dmMzUnpMbmRwYm1SdmQzTXVibVYwTDJZNFkyUmxaak14TFdFek1XVXROR0kwWVMwNU0yVTBMVFZtTlRjeFpUa3hNalUxWVM4aUxDSnphV1FpT2lJM1pUWXdaR1psWXkxbE5qbGpMVFJoTnpndFlUWTVNQzB6T0dWa01qaGtZakZtTmpraUxDSjBhV1FpT2lKbU9HTmtaV1l6TVMxaE16RmxMVFJpTkdFdE9UTmxOQzAxWmpVM01XVTVNVEkxTldFaUxDSjFkR2tpT2lJNGNDMW9aVmhyWWxaRlR6VkxPV3RFU25rd05rRkJJaXdpZG1WeUlqb2lNUzR3SW4wLllOY3RMWVA0LV9NWkxfMWpwalJQSUU5bzlQV3NDSUtoZTM4UnFYSXVVS0ZBaVJLTXJLTXhfakFQQWhpZkNibnBJdl94Ylk1YkpLcmJTV1JVTFRFZHhNb0tBMUlVZmFpNURzb25qQXlwTGtuS3JoVTFvOHV1MUV3UDlGeW5xZHVNb2lKamJ1SndXY09tWUlUQmp0MXR1bW5SVmptRFUyYTdxbUZMMDljNTBzNG1SbHpTWjJXSjRYYUVfQVFIUG9GOTJhMjY3SjM4SU95ZnpYYlh6WWJlX1JKaGNtT0I5R25lQnRvRFY0WFRWTjhhMjBBTmhIRnc1bVVSMi1qQzVHa1U3N3dsNU1zS1B3ODIwMGlBbHZoVGh2RGY0T2lKWlVIMFl4TUd5YmFadGZVNDcyRHdYcWp4WFdBWlg5TERJRDdYS3NBWU1pWHlhWDRiaWpZTlJuQ2h3ZwEB
S: A00000001 NO AUTHENTICATE failed.

Worthy to mention that :

await imapClient.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);

is successful, it's the next line of code that throwing the error

await imapClient.AuthenticateAsync(oauth2);


Update 1

overview

Update 2

I found a document saying :Office365 Oauth doesn't support SMTP/IMAP4, only EWS is supported.

enter image description here

Does this mean we will not be able to use OAuth for Hotmail via IMap4?

Update 3

enter image description here

I found that there are 2 different sets of Mail.Read, one from Graph, one from Exchange, plus the EWS.AccessAsUser.All from Exchange, as I am following the tutorial from https://www.emailarchitect.net/eagetmail/sdk/?ct=object_oauth_live

I am now totally lost, don't know which set I should be using.

2

2 Answers

0
votes

Don't use clientId as the user name. That's not the user name.

0
votes

The requested token does not contain any information about the mailbox. Although you request the token correctly, this token cannot be used to access the IMAP mailbox. You would need to add the email address or username of the mailbox to the token as well. But according to the documentation at https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-net-client-assertions there is no corresponding claim that can be added to the token.

To access a Google mailbox using an OAuth2 token for a service account, you have to provide the email address for the mailbox in the "sub" claim. This is not possible with your approach. AcquireTokenForClient requires "iss" (client-id) and "sub" to match.