C# 使用 Gmail 的 SmtpClient

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9801224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 08:55:14  来源:igfitidea点击:

SmtpClient with Gmail

c#monogmailmonodevelopsmtpclient

提问by simonbs

I'm developing a mail client for a school project. I have managed to send e-mails using the SmtpClientin C#. This works perfectly with any server but it doesn't work with Gmail. I believe it's because of Google using TLS. I have tried setting EnableSslto trueon the SmtpClientbut this doesn't make a difference.

我正在为学校项目开发邮件客户端。我已经设法使用SmtpClientC#发送电子邮件。这适用于任何服务器,但不适用于 Gmail。我相信这是因为 Google 使用了 TLS。我试过设置EnableSsltrueonSmtpClient但这没有区别。

This is the code I am using to create the SmtpClientand send an e-mail.

这是我用来创建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);
}

This is the error I am getting when I try to send an e-mail.

这是我尝试发送电子邮件时遇到的错误。

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 

Does anyone have an idea why I might be getting this error?

有谁知道为什么我可能会收到此错误?

采纳答案by konrad.kruczynski

Try running this:

尝试运行这个:

mozroots --import --ask-remove

in your system (just in bash or from Mono Command Prompt if it is on Windows). And then run the code again.

在您的系统中(仅在 bash 中或从 Mono Command Prompt 如果它在 Windows 上)。然后再次运行代码。

EDIT:

编辑:

I forgot you also should run

我忘了你也应该跑

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

(and answer yes on questions). This works for me on Mono 2.10.8, Linux (with your example).

(并在问题上回答是)。这适用于我在 Mono 2.10.8、Linux(以你的例子)。

回答by Jason Larke

Gmail's SMTP server requires you to authenticate your request with a valid gmail email/password combination. You do need SSL enabled as well. Without actually being able to see a dump of all your variables being passed in the best guess I can make is that your Credentials are invalid, make sure you're using a valid GMAILemail/password combination.

Gmail 的 SMTP 服务器要求您使用有效的 Gmail 电子邮件/密码组合来验证您的请求。您也需要启用 SSL。实际上无法看到所有变量的转储,我可以做出的最佳猜测是您的凭据无效,请确保您使用的是有效的GMAIL电子邮件/密码组合。

You might want to read herefor a working example.

你可能想在这里阅读一个工作示例。

EDIT: Okay here's something I wrote and tested just then and it worked fine for me:

编辑:好的,这是我当时编写和测试的内容,对我来说效果很好:

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

If you need any more info there's a similar SO article here

如果您需要任何更多的信息有一个相似的,所以文章在这里

回答by rasmusvhansen

This code works fine for me, try pasting this into LinqPad, edit the mail addresses and password and tell us what you see:

这段代码对我来说很好用,尝试将其粘贴到 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);
}

回答by rasmusvhansen

I think, you need to validate the server certificate that is used to establish the SSL connections.....

我认为,您需要验证用于建立 SSL 连接的服务器证书.....

Use following code to send mail with validating server certificate.....

使用以下代码发送带有验证服务器证书的邮件.....

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

Import System.Security.Cryptography.X509Certificatesnamespace to use ServicePointManager

导入System.Security.Cryptography.X509Certificates命名空间使用ServicePointManager

回答by t9mike

I started getting this with GMail in May 2013 after working for 6 momths. The Mono project's Using Trusted Roots Respectfullydocument provided guidance on work around. I chose option #1:

在工作了 6 个月后,我于 2013 年 5 月开始使用 GMail 获取此信息。Mono 项目的使用受信任的根尊重文档提供了解决方法的指导。我选择了选项#1:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

It is too disruptive to have e-mail for my service stop working without warning.

让我的服务的电子邮件在没有警告的情况下停止工作太具有破坏性。

Update Aug 26 2016: user Chico suggested the following complete implementation of the ServerCertificateValidationCallback callback. I have not tested.

2016 年 8 月 26 日更新:用户 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;

}

回答by Poet

You need to enable 2-Step Verification in your gmail account and create an app password (https://support.google.com/accounts/answer/185833?hl=en). Once you replace your password with the new app password, it should work.

您需要在您的 Gmail 帐户中启用两步验证并创建应用密码 ( https://support.google.com/accounts/answer/185833?hl=en)。用新的应用程序密码替换密码后,它应该可以工作。

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