SMTP和OAuth 2

use*_*287 13 .net c# smtp sasl oauth-2.0

.NET是否支持通过OAuth协议进行SMTP身份验证?基本上,我希望能够使用OAuth访问令牌发送有关用户行为的电子邮件.但是,我在.NET框架中找不到对此的支持.

Google 在其他环境中提供了一些示例,但不提供.NET.

jst*_*ast 16

System.Net.Mail不支持OAuth或OAuth2.但是,只要您拥有用户的OAuth访问令牌,您就可以使用MailKit(注意:仅支持OAuth2)SmtpClient来发送邮件(MailKit没有可以获取OAuth令牌的代码,但如果您有,则可以使用它它).

您需要做的第一件事是按照Google的说明获取应用程序的OAuth 2.0凭据.

完成此操作后,获取访问令牌的最简单方法是使用Google的Google.Apis.Auth库:

var certificate = new X509Certificate2 (@"C:\path\to\certificate.p12", "password", X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential (new ServiceAccountCredential
    .Initializer ("your-developer-id@developer.gserviceaccount.com") {
    // Note: other scopes can be found here: https://developers.google.com/gmail/api/auth/scopes
    Scopes = new[] { "https://mail.google.com/" },
    User = "username@gmail.com"
}.FromCertificate (certificate));

bool result = await credential.RequestAccessTokenAsync (CancellationToken.None);

// Note: result will be true if the access token was received successfully
Run Code Online (Sandbox Code Playgroud)

现在你有了一个访问令牌(credential.Token.AccessToken),你可以将它与MailKit一起使用,就像它是密码一样:

using (var client = new SmtpClient ()) {
    client.Connect ("smtp.gmail.com", 587, SecureSocketOptions.StartTls);

    // use the access token
    var oauth2 = new SaslMechanismOAuth2 ("username@gmail.com", credential.Token.AccessToken);
    client.Authenticate (oauth2);

    client.Send (message);

    client.Disconnect (true);
}
Run Code Online (Sandbox Code Playgroud)

  • 如何获得 Google 信任的 X509 证书? (4认同)
  • 先生,这个图书馆节省了我的一天,工作就像一个魅力!感谢分享. (2认同)
  • 谢谢@jstedfast。代码是正确的。如果其他人正在尝试此操作并收到身份验证失败错误,我的问题是 OAuth 中的“范围”。我只想发送邮件,所以我使用了“https://www.googleapis.com/auth/gmail.compose”,但是使用 MailKit 进行身份验证需要您将其更改为“https://mail.google.com/ "(完整的 Gmail 特权)。 (2认同)

Ogg*_*las 8

我通过使用Office 365 / Exchange OnlineMicrosoft.Identity.Client使其正常工作。MailKit.Net.Smtp.SmtpClient应用注册需要API权限SMTP.Send

var options = new PublicClientApplicationOptions
{
    ClientId = "00000000-0000-0000-0000-000000000000",
    TenantId = " 00000000-0000-0000-0000-000000000000",
    RedirectUri = "http://localhost"
};

var publicClientApplication = PublicClientApplicationBuilder
    .CreateWithApplicationOptions(options)
    .Build();

var scopes = new string[] {
    "email",
    "offline_access",
    "https://outlook.office.com/SMTP.Send" // Only needed for SMTP
};

var authToken = await publicClientApplication.AcquireTokenInteractive(scopes).ExecuteAsync();

//Test refresh token
var newAuthToken = await publicClientApplication.AcquireTokenSilent(scopes, authToken.Account).ExecuteAsync(cancellationToken);

var oauth2 = new SaslMechanismOAuth2(authToken.Account.Username, authToken.AccessToken);

using (var client = new SmtpClient())
{
    await client.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
    await client.AuthenticateAsync(oauth2);

    var message = new MimeMessage();
    message.From.Add(MailboxAddress.Parse(authToken.Account.Username));
    message.To.Add(MailboxAddress.Parse("toEmail"));
    message.Subject = "Test";
    message.Body = new TextPart("plain") { Text = @"Oscar Testar" };

    await client.SendAsync(message, cancellationToken);

    await client.DisconnectAsync(true);
}
Run Code Online (Sandbox Code Playgroud)

基于这个例子:

https://github.com/jstedfast/MailKit/blob/master/ExchangeOAuth2.md

  • 您可以,但它仍然需要公共凭证流,即使只是间歇性的。私人解决方案是可行的,但它是后端的一个主要难题。整个情况一团糟,我对设计这个令人厌恶的东西的人没有高兴的想法或高度尊重 (2认同)