FernandoPaiva
FernandoPaiva

Reputation: 4460

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

I'm trying to send mail using SendGrid but I can't. It always throws an exception that I can't fix.

How do I to fix this issue ?

SendMail

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

CustomMail

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

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

Upvotes: 0

Views: 3583

Answers (3)

Martin Staufcik
Martin Staufcik

Reputation: 9490

For sending emails with SendGrid there is v3 API. The NuGet name is SendGrid and the link is here.

This library does not work with System.Net.Mail.MailMessage, it uses SendGrid.Helpers.Mail.SendGridMessage.

This library uses an API key for authorization. You can create one when you log into SendGrid web app, and navigate to Email API -> Integration Guide -> 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);
}

Upvotes: 1

Adam
Adam

Reputation: 3847

To more specifically answer your original question and the cause of your exception, the SendGrid SMTP server probably isn't looking for your account's username and password, but rather your API key. The error seems to indicate your authentication is not successful.

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.

Using the SendGrid C# library will also simplify this process:

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("[email protected]", "Example User");
            var subject = "Sending with SendGrid is Fun";
            var to = new EmailAddress("[email protected]", "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);
        }
    }
}

Upvotes: 1

Neil L.
Neil L.

Reputation: 154

I think your problem stems from not instantiating the SMTP client with the server in the constructor. Also you should wrap your smtpclient in a using statement so it disposes of it properly, or call dispose once you're finished.

Try this:

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

If that doesn't work you could try removing the port, enablessl and usedefaultcredentials parameters for the smtp client. I use sendgrid all the time and don't use those options.

Upvotes: 0

Related Questions