SmtpClient с Gmail
Я разрабатываю почтовый клиент для школьного проекта. Мне удалось отправить электронные письма с помощью SmtpClient
в С#. Это отлично работает с любым сервером, но не работает с Gmail. Я считаю, это из-за того, что Google использует TLS. Я попытался установить EnableSsl
на true
на SmtpClient
, но это не имеет значения.
Это код, который я использую, чтобы создать SmtpClient
и отправить электронное письмо.
this.client = new SmtpClient("smtp.gmail.com", 587);
this.client.EnableSsl = true;
this.client.UseDefaultCredentials = false;
this.client.Credentials = new NetworkCredential("username", "password");
try
{
// Create instance of message
MailMessage message = new MailMessage();
// Add receiver
message.To.Add("[email protected]");
// Set sender
// In this case the same as the username
message.From = new MailAddress("[email protected]");
// Set subject
message.Subject = "Test";
// Set body of message
message.Body = "En test besked";
// Send the message
this.client.Send(message);
// Clean up
message = null;
}
catch (Exception e)
{
Console.WriteLine("Could not send e-mail. Exception caught: " + e);
}
Это ошибка, которую я получаю, когда пытаюсь отправить электронное письмо.
Could not send e-mail. Exception caught: System.Net.Mail.SmtpException: Message could not be sent. ---> System.IO.IOException: The authentication or decryption has failed. ---> System.InvalidOperationException: SSL authentication error: RemoteCertificateNotAvailable, RemoteCertificateChainErrors
at System.Net.Mail.SmtpClient.<callback>m__4 (System.Object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, SslPolicyErrors sslPolicyErrors) [0x00000] in <filename unknown>:0
at System.Net.Security.SslStream+<BeginAuthenticateAsClient>c__AnonStorey7.<>m__A (System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Int32[] certErrors) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslClientStream.OnRemoteCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] errors) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslStreamBase.RaiseRemoteCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] errors) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslClientStream.RaiseServerCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] certificateErrors) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.validateCertificates (Mono.Security.X509.X509CertificateCollection certificates) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.ProcessAsTls1 () [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.Handshake.HandshakeMessage.Process () [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) Mono.Security.Protocol.Tls.Handshake.HandshakeMessage:Process ()
at Mono.Security.Protocol.Tls.ClientRecordProtocol.ProcessHandshakeMessage (Mono.Security.Protocol.Tls.TlsStream handMsg) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at System.Net.Mail.SmtpClient.Send (System.Net.Mail.MailMessage message) [0x00000] in <filename unknown>:0
at P2Mailclient.SMTPClient.send (P2Mailclient.Email email) [0x00089] in /path/to/my/project/SMTPClient.cs:57
У кого-нибудь есть идея, почему я могу получить эту ошибку?
Ответы
Ответ 1
Попробуйте выполнить следующее:
mozroots --import --ask-remove
в вашей системе (только в bash или из командной строки Mono, если она находится в Windows). Затем запустите код еще раз.
EDIT:
Я забыл, что вы также должны бежать
certmgr -ssl smtps://smtp.gmail.com:465
(и ответьте "да" на вопросы). Это работает для меня на Mono 2.10.8, Linux (с вашим примером).
Ответ 2
Для SMTP-сервера Gmail требуется аутентификация вашего запроса с помощью действительной комбинации электронной почты/пароля gmail. Вам также нужен SSL. Не имея возможности увидеть, как дамп всех ваших переменных передается наилучшим образом, я могу сделать, что ваши учетные данные недействительны, убедитесь, что вы используете допустимую комбинацию электронной почты/пароля GMAIL.
Вы можете прочитать здесь для рабочего примера.
EDIT: Хорошо, вот что-то я написал и протестировал именно тогда, и это сработало отлично для меня:
public static bool SendGmail(string subject, string content, string[] recipients, string from) {
if (recipients == null || recipients.Length == 0)
throw new ArgumentException("recipients");
var gmailClient = new System.Net.Mail.SmtpClient {
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
UseDefaultCredentials = false,
Credentials = new System.Net.NetworkCredential("******", "*****")
};
using (var msg = new System.Net.Mail.MailMessage(from, recipients[0], subject, content)) {
for (int i = 1; i < recipients.Length; i++)
msg.To.Add(recipients[i]);
try {
gmailClient.Send(msg);
return true;
}
catch (Exception) {
// TODO: Handle the exception
return false;
}
}
}
Если вам нужна дополнительная информация, там есть аналогичная статья SO здесь
Ответ 3
Я думаю, вам нужно проверить сертификат сервера, который используется для установления SSL-соединений.....
Используйте следующий код для отправки почты с подтверждением сертификата сервера.
this.client = new SmtpClient(_account.SmtpHost, _account.SmtpPort);
this.client.EnableSsl = _account.SmtpUseSSL;
this.client.Credentials = new NetworkCredential(_account.Username, _account.Password);
try
{
// Create instance of message
MailMessage message = new MailMessage();
// Add receivers
for (int i = 0; i < email.Receivers.Count; i++)
message.To.Add(email.Receivers[i]);
// Set sender
message.From = new MailAddress(email.Sender);
// Set subject
message.Subject = email.Subject;
// Send e-mail in HTML
message.IsBodyHtml = email.IsBodyHtml;
// Set body of message
message.Body = email.Message;
//validate the certificate
ServicePointManager.ServerCertificateValidationCallback =
delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ return true; };
// Send the message
this.client.Send(message);
// Clean up
message = null;
}
catch (Exception e)
{
Console.WriteLine("Could not send e-mail. Exception caught: " + e);
}
Импортировать пространство имен System.Security.Cryptography.X509Certificates
для использования ServicePointManager
Ответ 4
Этот код отлично подходит для меня, попробуйте вставить его в LinqPad, отредактируйте почтовые адреса и пароль и сообщите нам, что вы видите:
var client = new System.Net.Mail.SmtpClient("smtp.gmail.com", 587);
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("[email protected]", "xxxxxxx");
try
{
// Create instance of message
System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
// Add receiver
message.To.Add("[email protected]");
// Set sender
// In this case the same as the username
message.From = new System.Net.Mail.MailAddress("[email protected]");
// Set subject
message.Subject = "Test";
// Set body of message
message.Body = "En test besked";
// Send the message
client.Send(message);
// Clean up
message = null;
}
catch (Exception e)
{
Console.WriteLine("Could not send e-mail. Exception caught: " + e);
}
Ответ 5
Вам нужно включить двухэтапную аутентификацию в своей учетной записи gmail и создать пароль приложения (https://support.google.com/accounts/answer/185833?hl=en). После замены пароля новым паролем приложения он должен работать.
Credentials = new System.Net.NetworkCredential("your email address", "your app password");
Ответ 6
Я начал получать это с GMail в мае 2013 года после работы в течение 6 месяцев. Проект Mono Использование достоверных корней с уважением предоставил руководство по работе. Я выбрал вариант # 1:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Слишком разрушительно, что электронная почта для моей службы перестает работать без предупреждения.
Обновление 26 августа 2016 года: пользователь Chico предложил следующую полную реализацию обратного вызова ServerCertificateValidationCallback. Я не тестировал.
ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
bool isOk = true;
// If there are errors in the certificate chain, look at each error to determine the cause.
if (sslPolicyErrors != SslPolicyErrors.None) {
for (int i=0; i<chain.ChainStatus.Length; i++) {
if (chain.ChainStatus [i].Status != X509ChainStatusFlags.RevocationStatusUnknown) {
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan (0, 1, 0);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
bool chainIsValid = chain.Build ((X509Certificate2)certificate);
if (!chainIsValid) {
isOk = false;
}
}
}
}
return isOk;
}