如何使用 MailMessage 通过 SendGrid 发送邮件?

How do I to use MailMessage to send mail using SendGrid?

我正在尝试使用 SendGrid 发送邮件,但我不能。它总是抛出一个我无法修复的异常。

我该如何解决这个问题?

发送邮件

public static Boolean isSend(IList<String> emailTo, String mensagem, String assunto, String emailFrom, String emailFromName){        
        try{            
            MailMessage mail = new MailMessage();
            mail.BodyEncoding = System.Text.Encoding.UTF8;
            mail.SubjectEncoding = System.Text.Encoding.UTF8;
            //to
            foreach (String e in emailTo) {
                mail.To.Add(e);
            }             
            mail.From = new MailAddress(emailFrom);
            mail.Subject = assunto;            
            mail.Body = mensagem;
            mail.IsBodyHtml = true;
            SmtpClient smtp = new SmtpClient();
            smtp.Host = CustomEmail.SENDGRID_SMTP_SERVER;
            smtp.Port = CustomEmail.SENDGRID_PORT_587;            
            smtp.Credentials = new System.Net.NetworkCredential(CustomEmail.SENDGRID_API_KEY_USERNAME, CustomEmail.SENDGRID_API_KEY_PASSWORD);
            smtp.UseDefaultCredentials = false;
            smtp.EnableSsl = false;
            smtp.Timeout = 20000;
            smtp.Send(mail);
            return true;
        }catch (SmtpException e){
            Debug.WriteLine(e.Message);
            return false;
        }        
    }

自定义邮件

//SendGrid Configs   
    public const String SENDGRID_SMTP_SERVER = "smtp.sendgrid.net";
    public const int SENDGRID_PORT_587 = 587;
    public const String SENDGRID_API_KEY_USERNAME = "apikey"; //myself
    public const String SENDGRID_API_KEY_PASSWORD = "SG.xx-xxxxxxxxxxxxxxxxxxxxxxxxx-E";

异常

Exception thrown: 'System.Net.Mail.SmtpException' in System.dll
Server Answer: Unauthenticated senders not allowed

要使用 SendGrid 发送电子邮件,有 v3 API. The NuGet name is SendGrid and the link is here

此库不适用于 System.Net.Mail.MailMessage,它使用 SendGrid.Helpers.Mail.SendGridMessage

此库使用 API 密钥进行授权。您可以在登录 SendGrid 网络应用程序时创建一个,然后导航至电子邮件 API -> 集成指南 -> Web API -> C#。

var client = new SendGridClient(apiKey);
var msg = MailHelper.CreateSingleTemplateEmail(from, new EmailAddress(to), templateId, dynamicTemplateData);

try
{
    var response = client.SendEmailAsync(msg).Result;
    if (response.StatusCode != HttpStatusCode.OK
        && response.StatusCode != HttpStatusCode.Accepted)
    {
        var errorMessage = response.Body.ReadAsStringAsync().Result;
        throw new Exception($"Failed to send mail to {to}, status code {response.StatusCode}, {errorMessage}");
    }
}
catch (WebException exc)
{
    throw new WebException(new StreamReader(exc.Response.GetResponseStream()).ReadToEnd(), exc);
}

我认为你的问题源于没有在构造函数中用服务器实例化 SMTP 客户端。此外,您应该将 smtpclient 包装在 using 语句中,以便正确处理它,或者在完成后调用 dispose。

试试这个:

    public static Boolean isSend(IList<String> emailTo, String mensagem, String assunto, String emailFrom, String emailFromName)
    {
        try
        {
            MailMessage mail = new MailMessage();
            mail.BodyEncoding = System.Text.Encoding.UTF8;
            mail.SubjectEncoding = System.Text.Encoding.UTF8;
            //to
            foreach (String e in emailTo)
            {
                mail.To.Add(e);
            }
            mail.From = new MailAddress(emailFrom);
            mail.Subject = assunto;
            mail.Body = mensagem;
            mail.IsBodyHtml = true;
            using(SmtpClient smtp = new SmtpClient(CustomEmail.SENDGRID_SMTP_SERVER)){
                smtp.Port = CustomEmail.SENDGRID_PORT_587;
                smtp.Credentials = new System.Net.NetworkCredential(CustomEmail.SENDGRID_API_KEY_USERNAME, CustomEmail.SENDGRID_API_KEY_PASSWORD);
                smtp.UseDefaultCredentials = false;
                smtp.EnableSsl = false;
                smtp.Timeout = 20000;
                smtp.Send(mail)
            }
        }
        catch (SmtpException e)
        {
            Debug.WriteLine(e.Message);
            return false;
        }
    }

如果这不起作用,您可以尝试删除 smtp 客户端的端口、enablessl 和 usedefaultcredentials 参数。我一直使用 sendgrid 并且不使用这些选项。

为了更具体地回答您最初的问题和异常原因,SendGrid SMTP 服务器可能不是在寻找您帐户的用户名和密码,而是在寻找您的 API 密钥。该错误似乎表明您的身份验证不成功。

https://sendgrid.com/docs/for-developers/sending-email/v3-csharp-code-example/

To integrate with SendGrids SMTP API:

  • Create an API Key with at least "Mail" permissions.
  • Set the server host in your email client or application to smtp.sendgrid.net.
    • This setting is sometimes referred to as the external SMTP server or the SMTP relay.
  • Set your username to apikey.
  • Set your password to the API key generated in step 1.
  • Set the port to 587.

使用 SendGrid C# 库也将简化此过程:

https://sendgrid.com/docs/for-developers/sending-email/v3-csharp-code-example/

// using SendGrid's C# Library
// https://github.com/sendgrid/sendgrid-csharp
using SendGrid;
using SendGrid.Helpers.Mail;
using System;
using System.Threading.Tasks;

namespace Example
{
    internal class Example
    {
        private static void Main()
        {
            Execute().Wait();
        }

        static async Task Execute()
        {
            var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY");
            var client = new SendGridClient(apiKey);
            var from = new EmailAddress("test@example.com", "Example User");
            var subject = "Sending with SendGrid is Fun";
            var to = new EmailAddress("test@example.com", "Example User");
            var plainTextContent = "and easy to do anywhere, even with C#";
            var htmlContent = "<strong>and easy to do anywhere, even with C#</strong>";
            var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
            var response = await client.SendEmailAsync(msg);
        }
    }
}