web-dev-qa-db-fra.com

SmtpClient avec Gmail

Je développe un client de messagerie pour un projet d'école. J'ai réussi à envoyer des courriels en utilisant la variable SmtpClient en C #. Cela fonctionne parfaitement avec n'importe quel serveur, mais pas avec Gmail. Je crois que c'est à cause de l'utilisation de TLS par Google. J'ai essayé de régler EnableSsl à true sur SmtpClient mais cela ne change rien.

C’est le code que j’utilise pour créer la variable SmtpClient et envoyer un courrier électronique.

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

C'est l'erreur que je reçois lorsque j'essaie d'envoyer un courrier électronique.

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 

Quelqu'un at-il une idée de la raison pour laquelle je risque d’obtenir cette erreur?

30
simonbs

Essayez de lancer ceci:

mozroots --import --ask-remove

dans votre système (uniquement en bash ou à partir de l'invite de commande mono s'il est sous Windows) Et puis exécutez le code à nouveau.

MODIFIER:

J'ai oublié que tu devrais aussi courir

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

(et répondez oui aux questions). Cela fonctionne pour moi sur Mono 2.10.8, Linux (avec votre exemple).

22
konrad.kruczynski

Le serveur SMTP de Gmail nécessite que vous authentifiiez votre demande avec une combinaison valide d'adresse e-mail/mot de passe Gmail. Vous devez également activer SSL. Sans être en mesure de voir toutes vos variables passées dans la meilleure hypothèse que je puisse faire, c’est que vos informations d’identité ne sont pas valides. Assurez-vous d’utiliser un code valide. GMAIL combinaison email/mot de passe.

Vous voudrez peut-être lire ici pour un exemple de travail.

EDIT: Ok, voici quelque chose que j'ai écrit et testé à ce moment-là et qui a bien fonctionné pour moi:

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

Si vous avez besoin de plus d’informations, voici un article similaire SO ici

23
Jason Larke

Je pense que vous devez valider le certificat de serveur utilisé pour établir les connexions SSL .....

Utilisez le code suivant pour envoyer un courrier électronique avec un certificat de serveur de validation .....

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

Importer l'espace de noms System.Security.Cryptography.X509Certificates à utiliser ServicePointManager

4
user1082916

Ce code fonctionne très bien pour moi. Essayez de le coller dans LinqPad, modifiez les adresses e-mail et le mot de passe et dites-nous ce que vous voyez:

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);
}
3
rasmusvhansen

Vous devez activer la vérification en deux étapes dans votre compte gmail et créer un mot de passe pour l'application ( https://support.google.com/accounts/answer/185833?hl=fr ). Une fois que vous avez remplacé votre mot de passe par le nouveau mot de passe de l'application, cela devrait fonctionner.

Credentials = new System.Net.NetworkCredential("your email address", "your app password");
3
Poet

J'ai commencé à recevoir cela avec GMail en mai 2013 après avoir travaillé pendant 6 mois. Le projet Mono Using Trusted Roots Respect Respect document fournit des indications sur la manière de contourner le problème. J'ai choisi l'option n ° 1:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Il est trop perturbant de voir un courrier électronique pour mon service cesser de fonctionner sans avertissement.

Mise à jour du 26 août 2016: l'utilisateur Chico a suggéré la mise en œuvre complète suivante du rappel ServerCertificateValidationCallback. Je n'ai pas testé.

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;

}
1
t9mike