Gmail SMTP 的 MailKit 和 OAuth2 - 5.7.8 BadCredentials 错误

问题描述 投票:0回答:1

我正在尝试使用 mailkit 通过 gmail 帐户发送电子邮件。我不断收到 5.7.8 BadCredentials 错误。

我在谷歌中的 Oauth2 凭据为桌面应用程序指定了“EmailTesting”的项目名称 - 但是我没有在代码中的任何位置指定此字符串。这是一个问题吗?代码中指定的credentials.json文件是直接从oauth2凭证页面下载的。

更新: 现在使用 SaslMechanismOAuthBearer 方法,因为 GMAIL 指示 OAuthBearer。最后还显示 smtp.log。

我的代码如下:

    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();
    }

我运行此程序的第一天,它重定向到一个网页,以便 donotreply@INSERT_DOMAIN_HERE 可以授予应用程序发送电子邮件的权限。 但是,此后以及此后,它将抛出 5.7.8 用户名和密码不接受错误。 昨天一整天,谷歌 5.7.8 了解更多链接建议我需要添加恢复手机 - 尽管我已经在 24 小时前完成了该操作,并且已验证。截至今天早上,谷歌不再添加该建议,但仍然抛出 5.7.8 错误。 这是日志输出:

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...
c# smtp google-oauth google-api-dotnet-client mailkit
1个回答
0
投票

首先您需要使用“https://mail.google.com/”来使用SMTP服务器 第二个 AuthenticateAsync 应该使用 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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.