Search code examples
outlookazure-active-directoryoffice365mailkitsmtp-auth

Outlook SMTP Oauth Send - Authentication Unsuccessful


I have been trying to implement email functionality in a legacy app using the Legacy Mail API to add OAuth support after getting a token through the Device Code Flow starting with the Microsoft Sample Project.

Along that route I have added SMTP.Send and many other API permissions to find the missing piece. (Including { "User.Read", "User.ReadBasic.All", "SMTP.Send", "offline_access", "Mail.Send" } in fear of missing one)

I have been testing with the MailKit library to build a proof of concept.

So far I have the following Code Snippet that fails after trying to authenticate.

public void SendSmtpMessageAsync(string id, string accessToken)
{
    var message = new MimeMessage();
    message.From.Add(new MailboxAddress("From Name", "From [email protected]"));
    message.To.Add(new MailboxAddress("To Name", "To [email protected]"));
    message.Subject = "How you doin'?";

    message.Body = new TextPart("plain")
    {
        Text = @"Test Email Content"
    };

    using (var client = new SmtpClient(new ProtocolLogger(Console.OpenStandardOutput())))
    {
        try
        {
            client.Connect("smtp.office365.com", 587, SecureSocketOptions.StartTls);

            var oauth2 = new SaslMechanismOAuth2(id, accessToken);

            var temp = client.AuthenticationMechanisms;
            client.Authenticate(oauth2);

            client.Send(message);
            client.Disconnect(true);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }
}


MailKit Log

I have enabled logging and gotten a log that shows the client connecting than sending the token to authenticate but the authentication failing.

Connected to smtp://smtp.office365.com:587/?starttls=always
S: 220 MW3PR05CA0003.outlook.office365.com Microsoft ESMTP MAIL Service ready at Mon, 25 May 2020 21:31:07 +0000
C: EHLO [192.168.0.7]
S: 250-MW3PR05CA0003.outlook.office365.com Hello [<<My IP>>]
S: 250-SIZE 157286400
S: 250-PIPELINING
S: 250-DSN
S: 250-ENHANCEDSTATUSCODES
S: 250-STARTTLS
S: 250-8BITMIME
S: 250-BINARYMIME
S: 250-CHUNKING
S: 250 SMTPUTF8
C: STARTTLS
S: 220 2.0.0 SMTP server ready
C: EHLO [192.168.0.7]
S: 250-MW3PR05CA0003.outlook.office365.com Hello [<<My IP>>]
S: 250-SIZE 157286400
S: 250-PIPELINING
S: 250-DSN
S: 250-ENHANCEDSTATUSCODES
S: 250-AUTH LOGIN XOAUTH2
S: 250-8BITMIME
S: 250-BINARYMIME
S: 250-CHUNKING
S: 250 SMTPUTF8
C: AUTH XOAUTH2 <<Token omitted but I have confirmed that it is Base64 encoded and 
in the format of base64("user=" + userName + "^Aauth=Bearer " + accessToken + "^A^A")>>
S: 535 5.7.3 Authentication unsuccessful [MW3PR05CA0003.namprd05.prod.outlook.com]
MailKit.Security.AuthenticationException: 535: 5.7.3 Authentication unsuccessful 
[MW3PR05CA0003.namprd05.prod.outlook.com]

Any direction or resources would be appreciated since most existing posts are from pre-2020 when Legacy SMTP support was added. Additionally, if you see any misunderstanding let me know so I can do some additional reading.


Solution

  • After lots of searching and trying to talk to Microsoft I was pointed in the direction of this answer of a different post. (I had adding a POP3 call that was in the same format as the SMTP call in the OP.) The answer said to include the scope https://outlook.office.com/POP.AccessAsUser.All so after replacing the POP.AccessAsUser.All I had before the SMTP and POP3 calls worked using modern authentication.


    Additionally, now that I know the answer I see it is documented in Microsoft's Docs Authenticate an IMAP, POP or SMTP connection using OAuth verifying that this is the proper solution.

    Make sure to specify the full scopes, including Outlook resource URLs, when authorizing your application and requesting an access token.

    | Protocol  | Permission scope string
    |-----------|-------------------------------------
    | IMAP      | https://outlook.office.com/IMAP.AccessAsUser.All
    | POP       | https://outlook.office.com/POP.AccessAsUser.All
    | SMTP AUTH | https://outlook.office.com/SMTP.Send
    

    Hope this helps anyone else facing this same issue