Using SendGrid with Azure Functions to Send Email

I’ve been working on a solution for a customer that utilizes SharePoint Online lists and libraries, PowerApps, Logic Apps, and Azure Functions. The solution works something like this: Project documents are stored and updated in a SharePoint Library by office staff. The shop floor needs to access the documents and know at a glance when documents have been updated. The PowerApp displays a count of the most recently updated documents by project and document type, and also displays the documents. A SharePoint List is used to store the counts of the most recently updated documents. The Logic App and Azure Function work together to update the SharePoint List with the counts from the SharePoint Library.

As part of the solution, we wanted a way to be notified if the Azure Function threw an error. This is where SendGrid comes in. SendGrid is a third-party email delivery service. Azure Functions support an output binding for SendGrid, which makes it very easy to integrate into your solution.Here is a grand overview of how my solution (just the Azure Function and SendGrid piece) will work – If my Azure Function throws an error, it will send the error message to Azure Queue Storage. The error message will be stored in Azure Queue Storage until another Azure Function (2) comes and picks it up. Azure Function (2) will use SendGrid to send an email containing the error message. Easy-peasy. You can use SendGrid to send emails for all kinds of reasons – when a customer places an order, you can send a confirmation email with the details of the order; when someone clicks a button on your site to request information, you can send an email with the requested information; the options are endless.

Just a couple notes for clarity:

  1. My Function App is using Runtime V1, because I am calling the SharePoint Online Client-Side Object Model (CSOM) in my Azure Function and V2 doesn’t play well with CSOM
  2. My Function is an HTTP Trigger function
  3. I am developing in the local Azure Environment using C#

In addition, you will need a few things to make this all work:

  1. Appropriate permissions to create resources in the Azure Portal
    1. You will need a Resource Group, a Function App, and a Function
      1. If you go with Runtime V2, which is the default, check the Microsoft docs about SendGrid bindings – you may need to register the extension
    2. Download and Install Microsoft Azure Storage Explorer. You will need this to work with Azure Queue Storage, which is where you will send your error message to be picked up by another Azure Function that will send the SendGrid email (this will all make sense in a bit, just bear with me).
    3. Create a SendGrid Account (Don’t worry – it is free for the first 25,000 emails per month, and I will walk you through creating this account a little later).

Ok, let’s get started. Once I have written the code for my Azure Function, I need to create an Output Binding for Queue Storage (remember – this is where we are going to send and store our error message for the second function to pick up to send in the SendGrid email). When I do this, Azure will add the necessary code to my function’s function.json file.

Create Output Binding for Queue Storage in Function 1

In the Azure Portal, while in my function:

QueueStorageIntegrate

  • Click on “Integrate” in the left menu under the Function Name (Step 1 in image above)
  • Under Outputs, click on “+ New Output” (Step 2 in image above)

QueueStorage

  • Click on “Azure Queue Storage” (see image above)
  • Enter a Message Parameter Name – I used myQueueItems
  • Enter a Queue Name – I used myqueue-items
  • Select account connection (or create a new one) – I used AzureWebJobsStorage
  • Click “Save” – The new output is now listed under Outputs
  • Expand Documentation
    • Copy the Account Name and Account Key to use to connect to the Storage Account
  • Click GO to create the second Azure Function that will be triggered by this Queue Storage Output
    • Select Queue trigger – C# and give my New Function a name
      • Queue Name and Storage Account Connection are auto-filled from what was selected when the output was created
    • Click Create

QueueStorageFunction

This is the function that is created (see image above). We’ll add more code to this in a later step.

Connect to Azure Queue Storage

  • Run the Microsoft Azure Storage Explorer that you downloaded earlier or download and install it now, then run it.

Connect Storage

  • Click on the plug icon in the left menu (step 1 in image above)
  • Select “Use a storage account name and key” (step 2 in image above)
  • Click “Next”
  • Click “Connect”
  • Enter the Account Name and Account Key copied during the creation of the Queue Output Binding
  • Click “Next”
  • In the Storage Accounts Menu, expand the storage account associated with the Azure Function
  • Right-click “Queues”
  • Click “Create Queues”, type “myqueue-items” (or the queue name you created), press “Enter”

Test the Queue Triggered Function

At this point, the Queue Storage and the Queue Triggered Function are connected. Testing the function is easy.

In Azure Portal:

  • Open Queue Triggered Function
  • Expand Logs
  • Make sure log streaming isn’t paused
  • Leave Azure Portal open

In Storage Explorer:

  • Click on “myqueue-items”
  • Click on Add Message
  • Type a message in Message Text
  • Click OK
  • Wait for a few seconds

Return to Azure Portal:

  • Check function log and verify that the Message Text has been read from the queue

Return to Storage Explorer:

  • Click Refresh and verify that the message has been processed and is no longer in queue

Add Code in Function 1 to Communicate with Storage Queue

In my HTTP Triggered Function, I use a try-catch statement to handle errors. In the catch block, I add the code: myQueueItems.Add(errorMessage) after I create the string variable errorMessage that contains the error. See below:

</pre>
catch(Exception ex) { string errorMessage = ex.Message + “/n” + ex.StackTrace; //Send the error message to Storage Queue myQueueItems.Add(errorMessage); return req.CreateResponse(HttpStatusCode.BadRequest,”ERROR: “ + errorMessage); } 

myQueueItems was the message parameter name that was used when creating the Output Binding for Azure Storage.

Create SendGrid Account

In the Azure Portal, click the green plus sign to create a new resource.

  • Search for “SendGrid”, and select it
  • Click on “Create”
  • Enter a name for the SendGrid Account – name it anything you want.
  • Create a password, and confirm it
  • Select the subscription used for this project
  • Click on “Use Existing” resource group, and select the resource group used for this project
  • Click on Pricing Tier and select the F1 Free tier – this allows 25,000 emails/month
  • Click on Contact Information and fill it the blanks
  • Click on Legal Terms and accept them
  • Click on Create

Once the account is created, a Deployment Succeeded pop-up will be shown, and the SendGrid account will be listed in All resources. Open the SendGrid Account and click “Manage”. This will open the SendGrid dashboard and initiate the email verification process. Until the email is verified, only 100 emails/day can be sent.

Get the SendGrid API Key

In the SendGrid dashboard (get here by clicking on “Manage” in your SendGrid Account in the Azure Portal),

  • Click on “Setting” in the left navigation, then click on “API Keys”

API KEY

  • Click on “Create API Key” in the top right corner

API KEY2

  • Enter a name for the key
  • Select “Full Access” permissions
  • Click “Create & View”

API KEY3

  • IMPORTANT! Copy and save the API Key, this is the only time you will see it

Create Output Binding for SendGrid in Function 2

The first few steps here are the same as Creating Output Binding for Queue Storage in Function 1 above.

  • Click on “SendGrid” instead of Azure Queue Storage
  • Click on “Select”
  • Expand documentation, there are details about each requested value, and JavaScript and C# code samples for the function
  • Enter a name for Message parameter name – I used “message”
  • SendGrid API Key App Setting
    • Click new
    • Enter a name in key – I used SendGridKey
    • Paste the API Key from the last step in value
    • Click “Create”
  • The To, From, Subject and Text are optional
    • If not provided here, they can be added in code
    • I entered the To and From address, because mine would always be the same
  • Click “Save”

Update Code in Function 2 to send email using SendGrid

Make sure to reference the SendGrid assembly with a “#r” statement, and the SendGrid.Helpers.Mail namespace and the Microsoft.Azure.WebJobs.Host namespace with “using” statements. My email is very simple. It includes a subject and a single line of content stating that there was an error, which passes the errorMessage (the error and StackTrace) from Function 1.

  • Create a new Mail object
  • Use the Content class to set the content of the message (this can be either HTML or plain text)
  • Specify the Subject

It is also possible to set the sender, receiver(s), attachments, footers and tracking in the code. Many of these settings can also be handled in the binding, which you can find in the function.json file (My to and from email addresses are in the binding, which is why they aren’t in the code below.)


#r “SendGrid”

using System;

using SendGrid.Helpers.Mail;

using Microsoft.Azure.WebJobs.Host;

public static void Run(string myQueueItem, TraceWriter log, out Mail message)

{

log.Info($”SendErrorEmail function processed: {myQueueItem}”);

message = new Mail();

Content content = new Content(“text/plain”, $”PublishDocumentToKioskApp has thrown the following error: {myQueueItem}!”);

message.AddContent(content);

message.Subject = $”ShopFloorKioskApp Error”;

}

That’s it. You should have an Azure Function that sends its error message to Azure Queue Storage, and another Azure Function that picks up that message and sends it in an email using SendGrid.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s