Search code examples
c#oauthsmtpgmailmailkit

Authenticate to Gmail smtp using Xoauth2. Results in Username and Password not accepted


Due to the recent removal of less secure apps and not wanting to go along the route of an apps password. I have been trying to enable Xoauth2 with the smtp server as a more secure sustainable method of authorization for my users.

I have created a simple console appication to test this.

  1. Uses mailkit
  2. connects to googles smtp server
  3. uses xoauth2.
  4. Created installed application on google cloud console.

Authorization appears to work i am getting an access token back. The issue seams to be that the smtp server will not accept it, or possibly how I am applying it.

using Google.Apis.Auth.OAuth2;
using Google.Apis.Util.Store;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;


var path = @"C:\YouTube\dev\credentials.json";
var scopes = new[] { "email" };
var userName = "test2";

var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromFile(path).Secrets,
    scopes,
    userName,
    CancellationToken.None,
    new FileDataStore(Directory.GetCurrentDirectory(), true)).Result;

credential.GetAccessTokenForRequestAsync();

var message = new EmailMessage()
{
    From = "xxx@gmail.com",
    To = "xxx@gmail.com",
    MessageText = "test",
    Subject = "test"
};

try
{
    using (var client = new SmtpClient())
    {
        client.Connect("smtp.gmail.com", 465, true);
        
        var oauth2 = new SaslMechanismOAuth2 ("xxx@gmail.com", credential.Token.AccessToken);
        await client.AuthenticateAsync (oauth2, CancellationToken.None);
        
        client.Send(message.GetMessage());
        client.Disconnect(true);
    }

   
}
catch (Exception ex)
{
    int i = 1;  // throws MailKit.Security.AuthenticationException here
}


public class EmailMessage
{
    public string To { get; set; }
    public string From { get; set; }
    public string Subject { get; set; }
    public string MessageText { get; set; }

    public MimeMessage GetMessage()
    {
        var body = MessageText;
        var message = new MimeMessage();
        message.From.Add(new MailboxAddress("test", From));
        message.To.Add(new MailboxAddress("test", To));
        message.Subject = Subject;
        message.Body = new TextPart("plain") { Text = body };
        return message;
    }
}

The full error message is as follows.

MailKit.Security.AuthenticationException: 535: 5.7.8 Username and Password not accepted. Learn more at 5.7.8 https://support.google.com/mail/?p=BadCredentials da26-20020a056402177a00b004315050d7dfsm6610655edb.81 - gsmtp at MailKit.Net.Smtp.SmtpClient.AuthenticateAsync(SaslMechanism mechanism, Boolean doAsync, CancellationToken cancellationToken) at Program.$(String[] args) in C:\YouTube\dev\Gmail\Code\SMTPTesting\SmtpTest\SmtpTestXoauth2\Program.cs:line 38


Solution

  • It seams that after struggling with this for a while.

    The standard email scope was incorrect. XOauth2 with the smtp server has two scopes only used for it

    the last one apparently only works for workspace.

    fix

    The only thing i needed to change in the code was

    var scopes = new[] { "email" };
    

    to

    var scopes = new[] { "https://mail.google.com/" };
    

    More info can be found here Oauth2 scopes