it-swarm.com.de

SmtpClient mit Google Mail

Ich entwickle einen Mail-Client für ein Schulprojekt. Es ist mir gelungen, E-Mails mit SmtpClient in C # zu senden. Dies funktioniert perfekt mit jedem Server, aber nicht mit Google Mail. Ich glaube es liegt daran, dass Google TLS verwendet. Ich habe versucht, EnableSsl auf true für SmtpClient zu setzen, aber das macht keinen Unterschied.

Dies ist der Code, den ich verwende, um SmtpClient zu erstellen und eine E-Mail zu senden.

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

Dies ist der Fehler, den ich erhalte, wenn ich versuche, eine E-Mail zu senden.

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 

Hat jemand eine Idee, warum ich diesen Fehler bekomme?

30
simonbs

Versuchen Sie, dies auszuführen:

mozroots --import --ask-remove

in Ihrem System (nur in bash oder von der Mono-Eingabeaufforderung, wenn es unter Windows läuft). Führen Sie dann den Code erneut aus.

BEARBEITEN:

Ich habe vergessen, dass du auch rennen solltest

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

(und antworten Sie mit Ja.) Dies funktioniert für mich unter Mono 2.10.8, Linux (mit Ihrem Beispiel).

22

Für den SMTP-Server von Google Mail müssen Sie Ihre Anfrage mit einer gültigen Kombination aus Google Mail-E-Mail und Passwort authentifizieren. Sie benötigen auch SSL, das aktiviert ist. Wenn Sie nicht in der Lage sind, einen Speicherauszug aller Ihrer Variablen zu sehen, die in der besten Annahme sind, dass Ihre Anmeldeinformationen ungültig sind, stellen Sie sicher, dass Sie eine gültige verwenden GMAIL E-Mail/Passwort-Kombination.

Sie können here für ein Arbeitsbeispiel lesen.

EDIT: Okay, hier habe ich etwas geschrieben und getestet, und es hat gut funktioniert für mich:

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

Wenn Sie weitere Informationen benötigen, gibt es einen ähnlichen SO Artikel hier .

23
Jason Larke

Ich denke, Sie müssen das Serverzertifikat überprüfen, das zum Herstellen der SSL-Verbindungen verwendet wird.

Verwenden Sie den folgenden Code, um E-Mails mit einem Serverzertifikat zu senden.

            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-Namespace importieren, um ServicePointManager zu verwenden

4
user1082916

Dieser Code funktioniert gut für mich. Versuchen Sie, dies in LinqPad einzufügen, bearbeiten Sie die E-Mail-Adressen und das Passwort und teilen Sie uns mit, was Sie sehen:

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

Sie müssen die Bestätigung in zwei Schritten in Ihrem Google Mail-Konto aktivieren und ein App-Kennwort erstellen ( https://support.google.com/accounts/answer/185833?hl=de ). Wenn Sie Ihr Kennwort durch das neue App-Kennwort ersetzt haben, sollte es funktionieren.

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

Ich habe im Mai 2013 mit GMail angefangen, nachdem ich 6 Monate gearbeitet hatte. Das Mono-Projekt Vertrauenswürdige Wurzeln verwenden - Dokument gab Hinweise zur Umgehung. Ich habe Option 1 gewählt:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Es ist zu störend, wenn E-Mails für meinen Dienst ohne Warnung nicht mehr funktionieren.

Update 26. August 2016: Benutzer Chico schlug die folgende vollständige Implementierung des ServerCertificateValidationCallback-Callbacks vor. Ich habe es nicht getestet.

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