I'm trying to use mailkit to send emails via a gmail account. I keep getting the 5.7.8 BadCredentials error.
My Oauth2 credentials in google specify a project name of "EmailTesting" for a desktop app - however I'm not specifying this string anywhere in my code. Is this a problem? The credentials.json file specified in the code is directly downloaded from the oauth2 credentials page.
UPDATE: Now using SaslMechanismOAuthBearer method since GMAIL indicates OAuthBearer. Also showing smtp.log at end.
My code is as follows:
public async Task Test4()
{
UserCredential creds;
using (var stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
{
creds = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.FromStream(stream).Secrets,
new[] { GmailService.Scope.GmailSend },
"donotreply@INSERT_DOMAIN_HERE",
CancellationToken.None);
if (creds.Token.IsExpired(SystemClock.Default))
{
await creds.RefreshTokenAsync(CancellationToken.None);
}
}
MailKit.Net.Smtp.SmtpClient client;
client = new MailKit.Net.Smtp.SmtpClient();
client.Connect("smtp.gmail.com", 465, MailKit.Security.SecureSocketOptions.SslOnConnect);
client.Authenticate(new SaslMechanismOAuthBearer(creds.UserId, creds.Token.AccessToken));
var builder = new MimeKit.BodyBuilder();
builder.TextBody = "This is the body of the email";
MimeMessage mail = new MimeKit.MimeMessage();
mail.From.Add(MailboxAddress.Parse("donotreply@INSERT_DOMAIN_HERE"));
mail.To.Add(MailboxAddress.Parse("erict@INSERT_DOMAIN_HERE"));
mail.Subject = "this is the subject";
mail.Body = builder.ToMessageBody();
await client.SendAsync(mail);
client.Disconnect(true);
client.Dispose();
mail.Dispose();
}
The first day I ran this, it redirected to a web page so that donotreply@INSERT_DOMAIN_HERE could give permission for the app to send emails. However, after that and since then, it would throw a 5.7.8 Username and Password not accepted error. All day yesterday the google 5.7.8 learn more link suggested I need to add a recovery phone - even though I had done that more than 24h ago, and verified. As of this morning, google does not add that suggestion anymore, but still throws a 5.7.8 error. Here is a log output:
S: 220 smtp.gmail.com ESMTP r12-20020a05621410cc00b0066d132b1c8bsm4912733qvs.102 - gsmtp
C: EHLO New-Laptop
S: 250-smtp.gmail.com at your service, [<IP-ADDRESS OF MY MACHINE>]
S: 250-SIZE 35882577
S: 250-8BITMIME
S: 250-STARTTLS
S: 250-ENHANCEDSTATUSCODES
S: 250-PIPELINING
S: 250-CHUNKING
S: 250 SMTPUTF8
C: STARTTLS
S: 220 2.0.0 Ready to start TLS
C: EHLO New-Laptop
S: 250-smtp.gmail.com at your service, [<IP-ADDRESS OF MY MACHINE>]
S: 250-SIZE 35882577
S: 250-8BITMIME
S: 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
S: 250-ENHANCEDSTATUSCODES
S: 250-PIPELINING
S: 250-CHUNKING
S: 250 SMTPUTF8
C: AUTH OAUTHBEARER ********
S: 334 eyJzdGF0dXMiOiJpbnZhbGlkX3JlcXVlc3QiLCJzY29wZSI6Imh0dHBzOi8vbWFpbC5nb29nbGUuY29tLyJ9
C: ********
S: 535-5.7.8 Username and Password not accepted. Learn more at...
First you need to use the "https://mail.google.com/" to use the SMTP server second AuthenticateAsync should be using SaslMechanismOAuth2
using Google.Apis.Auth.OAuth2;
using Google.Apis.Util.Store;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
var to = "[email protected]";
// TODO: figure out how to get the users email back from the smtp server without having to request the profile scope.
var from = "[email protected]";
var path = @"C:\Development\FreeLance\GoogleSamples\Credentials\Credentials.json";
var scopes = new[] { "https://mail.google.com/" }; // You can only use this scope to connect to the smtp server.
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromFile(path).Secrets,
scopes,
"GmailSmtpUser",
CancellationToken.None,
new FileDataStore(Directory.GetCurrentDirectory(), true)).Result;
var message = new EmailMessage()
{
From = from,
To = to,
MessageText = "This is a test message using https://developers.google.com/gmail/imap/xoauth2-protocol",
Subject = "Testing GmailSMTP with XOauth2"
};
try
{
using (var client = new SmtpClient())
{
client.Connect("smtp.gmail.com", 465, true);
var oauth2 = new SaslMechanismOAuth2 (message.From, credential.Token.AccessToken);
await client.AuthenticateAsync (oauth2, CancellationToken.None);
client.Send(message.GetMessage());
client.Disconnect(true);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
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("From a user", From));
message.To.Add(new MailboxAddress("To a user", To));
message.Subject = Subject;
message.Body = new TextPart("plain") { Text = body };
return message;
}
}