I am trying to convince people that right now we should try to think about how we can build our application effectively. Instead of building everything from scratch we should look for possibilities of composition application from different elements. This means that you should write smaller amount of code and there is also smaller chance for making an error.

In case of Azure Functions natural choice for email service provider is SendGrid.

SendGrid Configuration

Let’s start from beginning and create such service in Azure Portal:

Of course, we need to provide all needed information. Please note that free plan allows sending 25’000 emails per month. After entering all data we can click Create:

After a while you should be able to see created service in your resource group. Please open this service and click Manage button. In case you do not see this SendGrid service please refresh Resource group list.

After clicking this button you should be redirected to SendGrid page. First of all you need to confirm your identity. After that we need to generate API key. This key will be used in our function. Please open Settings, then API Keys and click Create API Key. You need to select level of security – for demo purpose I will select Full access – and provide name for created key. After successful creation you should be able to see and copy your key:

This key will be needed in our function that will send emails.

Email sending from Azure Functions

Function created as a script

We are already in the middle of our journey. Now we should switch to Azure Functions. I hope that you know how you should create Azure Function. I will start from Http Trigger function because I would like to show you step by step what you should configure. There is also Scheduled mail template that will do everything for us.

After function creation we should open Integrate, add new output parameter and select SendGrid:

And then we should configure service. Most of parameters are very clear. There are two tricky one:

  • SendGrid API Key App Setting – please note that here we should enter key from App Setting that contains SendGrid API Key and NOT SendGrid API key. Most people make mistake here entering SendGrid API key. When you do not have key stored in App Setting please use new button.
  • Use function return value – with this option we can select if we like to pass mail as function argument (not selected) or as return value of function. I will use it as method argument and leave it empty.

After clicking save configuration will be saved in function.json file:

On integration screen we have one very interesting option – Documentation. You need to select only interesting element and you will see great documentation:

We can find there code that is needed for our function:

#r "SendGrid"

using System;
using SendGrid.Helpers.Mail;
using Microsoft.Azure.WebJobs.Host;

public static Mail Run(Order order, TraceWriter log)
{
  log.Info($"C# Queue trigger function processed order: {order.OrderId}");

  Mail message = new Mail()
  {
    Subject = $"Thanks for your order (#{order.OrderId})!"
  };

  Content content = new Content
  {
    Type = "text/plain",
    Value = $"{order.CustomerName}, your order ({order.OrderId}) is being processed!"
  };

  message.AddContent(content);

  return message;
}

public class Order
{
  public string OrderId { get; set; }
  public string CustomerName { get; set; }
  public string CustomerEmail { get; set; }
}

As you can see it is a bit different than our use case:

  • function is triggered by message in queue,
  • mail is created as return object.

Let’s try to adjust it to our needs – I will create function that will send email with provided text. Code should look like this:

#r "SendGrid"

using System;
using SendGrid.Helpers.Mail;
using System.Net;

public static HttpResponseMessage Run(HttpRequestMessage req, out Mail message)
{
  // parse query parameter
  string messageText = req.GetQueryNameValuePairs()
    .FirstOrDefault(q => string.Compare(q.Key, "message", true) == 0)
    .Value;

  message = new Mail();
  Content content = new Content
  {
    Type = "text/plain",
    Value = messageText
  };
  message.AddContent(content);

  return req.CreateResponse(HttpStatusCode.Accepted);
}

Please remember that you can test this function by message only by query parameter. I removed part responsible for getting those data from request body. After running this function you should get email to provided email address.

Of course you can adjust parameters of email (to, from, subject) as you wish by extending this code.

Function created as code file

We have also second option – we can use attributes to configure SendGrid integration. The steps are pretty the same. Only the code looks a bit different:

[FunctionName("SendThankYouEmailMessage")]
public static void Run(
  [QueueTrigger("tosendemail", Connection = "registration2storage_STORAGE")] Customer customer,
  [SendGrid(
    To = "{Email}",
    Subject = "Thank you!",
    Text = "Hi {Name}, Thank you for registering!!!!",
    From = "[email protected]"
  )]
  out Mail message)
  {
    message = new Mail();
}

Please note that in this case we can consume values that come in object from queue directly in SendGrid attribute.