Чтобы лучше защитить своих пользователей, почтовые провайдеры GMail и другие рекомендуют обновлять все наши приложения до OAuth 2.0.
Я прав, что это означает, что System.Net.Mail
больше не работает, и нам нужно использовать другую библиотеку, например MailKit
?
В общем, я пытаюсь понять, как отправить электронное письмо без разрешения "Доступ для менее безопасных приложений"?
Потому что у меня System.Net.Mail.SmtpException: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required.
Выполняется smtpClient.Send(message);
.
Если единственный способ решить эту проблему - использовать MailKit
, я думаю, что этот вопрос будет хорошим практическим пошаговым руководством по переключению от System.Net.Mail
до использования MailKit
и Google.Apis.Auth.OAuth2
. Я не знаю, может быть, общее решение будет использовать DotNetOpenAuth
?
У меня есть следующий класс в моем приложении, который соответствует отправке письма на любой адрес (gmail, yandex и другие):
public class EmailSender
{
public void SendEmail(SmtpServerSettings serverSettings, SendEmailRequest emailRequest)
{
// Usually I have 587 port, SmtpServerName = smtp.gmail.com
_logger.Trace("Sending message with subject '{0}' using SMTP server {1}:{2}",
emailRequest.Subject,
serverSettings.SmtpServerName,
serverSettings.SmtpPort);
try
{
using (var smtpClient = new SmtpClient(serverSettings.SmtpServerName, (int)serverSettings.SmtpPort))
{
smtpClient.EnableSsl = serverSettings.SmtpUseSsl; // true
if (!string.IsNullOrEmpty(serverSettings.UserName) || !string.IsNullOrEmpty(serverSettings.EncryptedPassword))
{
smtpClient.Credentials = new NetworkCredential(serverSettings.UserName, serverSettings.EncryptedPassword);
}
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpClient.Timeout = (int)serverSettings.SmtpTimeout.TotalMilliseconds;
using (var message = new MailMessage())
{
message.From = new MailAddress(serverSettings.FromAddress);
emailRequest.To.ForEach(message.To.Add);
emailRequest.CC.ForEach(message.CC.Add);
emailRequest.Bcc.ForEach(message.Bcc.Add);
message.Subject = emailRequest.Subject.Replace('\r', ' ').Replace('\n', ' ');
message.Body = emailRequest.Body;
message.BodyEncoding = Encoding.UTF8;
message.IsBodyHtml = false;
smtpClient.Send(message);
}
}
_logger.Trace("Sent message with subject '{0}' using SMTP server {1}:{2}",
emailRequest.Subject,
serverSettings.SmtpServerName,
serverSettings.SmtpPort);
}
catch (SmtpFailedRecipientsException e)
{
var failedRecipients = e.InnerExceptions.Select(x => x.FailedRecipient);
LogAndReThrowWithValidMessage(e, EmailsLocalization.EmailDeliveryFailed, failedRecipients);
}
}
}
Он отлично работает до новых политик безопасности Google.
Я знаю, что System.Net.Mail
не поддерживает OAuth2
. Я решил использовать MailKit's
SmtpClient
для отправки сообщений.
После расследования я понимаю, что мой исходный код не так сильно изменяется, потому что API MailKit's
выглядит очень похоже (с System.Net.Mail
).
За исключением одной детали: мне нужен токен доступа пользователя OAuth (MailKit не имеет кода, который будет извлекать токен OAuth, но он может использовать его, если он у меня есть).
Итак, в будущем у меня будет следующая строка:
smtpClient.Authenticate (usersLoginName, usersOAuthToken);
У меня есть идея добавить GoogleCredentials
в качестве нового параметра к методу SendEmail
:
public void SendEmail(SmtpServerSettings serverSettings, SendEmailRequest emailRequest,
GoogleCredentials credentials)
{
var certificate = new X509Certificate2(credentials.CertificateFilePath,
credentials.PrivateKey,
X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(credentials.ServiceAccountEmail)
{
Scopes = new[] { "https://mail.google.com/" },
User = serverSettings.UserName
}.FromCertificate(certificate));
....
//my previous code but with MailKit API
}
Как получить usersOAuthToken
?
Это лучший способ использования Google.Apis.Auth.OAuth2
?
Код, который я написал выше, предназначен только для GMail и НЕ РАБОТАЕТ для yandex.ru или других почтовых провайдеров. Для работы с другими мне, вероятно, понадобится использовать другие библиотеки OAuth2. Но я не хочу иметь много механизмов аутентификации в моем коде для многих возможных почтовых провайдеров. Я хотел бы иметь ОДИН ОБЩИЙ РЕШЕНИЕ для каждого почтового провайдера. И одна библиотека, которая может отправлять электронную почту (например,.net smtpclient)