SmtpClient с Gmail - PullRequest
       17

SmtpClient с Gmail

31 голосов
/ 21 марта 2012

Я разрабатываю почтовый клиент для школьного проекта. Мне удалось отправить электронную почту, используя SmtpClient в C #. Это прекрасно работает с любым сервером, но не работает с 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("myemail@mydomain.com");

    // Set sender
    // In this case the same as the username
    message.From = new MailAddress("username@gmail.com");

    // 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 

У кого-нибудь есть идея, почему я могу получить эту ошибку?

Ответы [ 6 ]

23 голосов
/ 21 марта 2012

SMTP-сервер Gmail требует от вас проверки подлинности вашего запроса с помощью действительной комбинации электронной почты и пароля GmailВам также нужно включить SSL.Не имея возможности увидеть дамп всех передаваемых переменных в лучшем предположении, которое я могу сделать, это то, что ваши учетные данные недействительны, убедитесь, что вы используете действительную GMAIL электронную почту / пароль.

Возможно, вы захотите прочитать здесь для рабочего примера.

РЕДАКТИРОВАТЬ: Хорошо, вот кое-что, что я написал и протестировал именно тогда, и оно отлично работает для меня:

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 здесь

22 голосов
/ 21 марта 2012

Попробуйте запустить это:

mozroots --import --ask-remove

в вашей системе (только в bash или из командной строки Mono, если это в Windows).И затем снова запустите код.

РЕДАКТИРОВАТЬ:

Я забыл, что вы также должны запустить

certmgr -ssl smtps://smtp.gmail.com:465

(и ответить на вопросы да)Это работает для меня на Mono 2.10.8, Linux (на вашем примере).

4 голосов
/ 21 марта 2012

Я думаю, вам нужно проверить сертификат сервера, который используется для установления 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

3 голосов
/ 24 марта 2017

Вам необходимо включить двухэтапную верификацию в своей учетной записи gmail и создать пароль приложения (https://support.google.com/accounts/answer/185833?hl=en).. После замены пароля новым паролем приложения, он должен работать.

Credentials = new System.Net.NetworkCredential("your email address", "your app password");
3 голосов
/ 21 марта 2012

Этот код отлично работает для меня, попробуйте вставить его в LinqPad, отредактируйте почтовые адреса и пароль и сообщите нам, что вы видите:

var client = new System.Net.Mail.SmtpClient("smtp.gmail.com", 587);
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("me@gmail.com", "xxxxxxx");

try
{
    // Create instance of message
    System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();

    // Add receiver
    message.To.Add("me@gmail.com");

    // Set sender
    // In this case the same as the username
    message.From = new System.Net.Mail.MailAddress("me@gmail.com");

    // 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);
}
1 голос
/ 18 июня 2013

Я начал получать это с 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;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...