Love them or hate them, email notifications are a topic nearly every project needs to solve. Having to trigger them from Azure has come up multiple times in the last week which prompted me to ask, how many ways can we trigger notifications?  Is there an easy serverless way to do this from Azure?  

Azure offers a very straightforward way to create a serverless flow based app using Azure Logic Apps.  We'll create a Logic App and leverage 4 different ways to trigger notifications: Office365, SMTP to Email providers, SendGrid, and lastly API Gateway.

The first step is to login to the Azure Portal and create a Logic App.

Creating Logic App

You can create a Logic App in the Portal:

We will use an HTTP request

We can use a sample payload to generate the schema:

Next put in a payload.  We'll need a to for the email address:

which will generate the request schema, for instance:

{
    "type": "object",
    "properties": {
        "to": {
            "type": "string"
        }
    }
}

Send Grid

First create a sendgrid account if you don't already have one:

Then create a Single Sender Verification:

After we verify, we’ll want to create an API key:https://app.sendgrid.com/settings/api_keys

In the logic apps designer, after “When an HTTP request is received” click "+New Step".

Next, add SendGrid and choose Send Email (v4):

Use the API key you generated above:

For a quick demo, we will setup just a hello world. But we will pull in the to as passed via HTTP:

When done, click save:

Testing:

First, get the POST URL from the first step:

https://prod-02.centralus.logic.azure.com:443/workflows/2e39fb753e5b4354920b3958a04a8e6e/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=RAJX94DZYiYc19ilNe76C8MQZXWrvJSxQ6ftT75-3f4

This does include the key so you’ll want to protect it. We can use something like PostMan, but i tend to just use plain old curl:

$ curl --header "Content-Type: application/json" --request POST --data '{"to":"isaac.johnson@gmail.com"}' 'https://prod-02.centralus.logic.azure.com:443/workflows/2e39fb753e5b4354920b3958a04a8e6e/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=RAJX94DZYiYc19ilNe76C8MQZXWrvJSxQ6ftT75-3f4'

Note: my first tests failed because for some reason i wrote freshbrewed.com (not me):

It was blocked, as one might expect.

Let’s change that to my freshbrewed.science email address and try again.

Using Office365

If you have Office365, you can use that connector which also allows you to look up details from Azure Active Directory.  This is what one of my Logic Apps looks like today in such environment:

You’ll notice i can use O365 to pull information about a users role, such as Given Name and Surname and add that to the email message for a more polished notification.

You can even pull details from O365 graph.

Using AWS SQS/SNS

Create an SNS topic. For a demo, I’ll create “NotifyMe” in us-east-1 and add myself as a subscriber:

We can Publish message to test

{"source":"la-draft-clipboard","value":[{"tokenKey":"A7548FB3-0520-474F-92B4-DB91BBD1C472","type":"literal","tokenExpression":"https://sns.us-east-2.amazonaws.com/?Action=Publish"},{"tokenKey":"CE3E4460-B0FF-4382-B4D1-9064CF9515A3","type":"new_line","tokenExpression":"\n"},{"tokenKey":"F67D9BD6-F48F-4CAE-9E12-9C588066A0B2","type":"literal","tokenExpression":"&TopicArn=arn%3Aaws%3Asns%3Aus-east-1%3A095928337644%3ANotifyMe&Subject=MyLogicApp&Message=Hello%20World%21&Version-2010-03-31"}]}

We could now go through creating a messaging queue (SQS) that could trigger SNS:

But more often, someone else has done the work.  Simply create a new Lambda and choose "Browse serverless".  Search for "generic-webhook-to-sns" and launch.

Once launched, you will have a reachable API Gateway endpoint to enque to SQS that has a lambda to trigger SNS.  To receive messages, you'll need to create a subscription to the created topic.

Create subscription to topic:

Confirm the email to subscribe (like any maillist).

We can test with:

$ curl --header "Content-Type: application/json" --request POST --data '{"to":"isaac.johnson@gmail.com"}' https://hjnb66q7wh.execute-api.us-east-1.amazonaws.com

Back to the Logic App, add an HTTP step and use POST to pass the same values to the API Gateway trigger:

Now when we invoke our Logic Function:

$ curl --header "Content-Type: application/json" --request POST --data '{"to":"isaac.johnson@gmail.com"}' 'https://prod-02.centralus.logic.azure.com:443/workflows/2e39fb753e5b4354920b3958a04a8e6e/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=RAJX94DZYiYc19ilNe76C8MQZXWrvJSxQ6ftT75-3f4'

We should get an email from SendGrid AND from SNS:

proof it was triggered via Logic APp call

If I cared to really use AWS SNS, i would update the lambda to parse out the details and create a nicer body:

SMTP with Gmail, Yahoo and Others

First, you’ll need to allow insecure apps. By Default, Gmail will block curl and you’ll see “invalid logins”:

When it works, the curl locally should send emails:

$ echo hi > test.txt && curl -u youruser@gmail.com:yourpassword -n --ssl-reqd --mail-from "youruser@gmail.com" --mail-rcpt "youruser@gmail.com" --url smtps://smtp.gmail.com:465 -T test.txt

Next add parameters for our fields

And then add our values.  Like before, we can use “to” from our passed in values:

Now when we test our logic app:

builder@DESKTOP-2SQ9NQM:~$ curl --header "Content-Type: application/json" --request POST --data '{"to":"isaac.johnson@gmail.com"}' 'https://prod-02.centralus.logic.azure.com:443/workflows/2e39fb753e5b4354920b3958a04a8e6e/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=RAJX94DZYiYc19ilNe76C8MQZXWrvJSxQ6ftT75-3f4'

It fails.. Sadly it seems even with insecure apps it wont work.

I don't recommend leaving this on.

Error

  "message": "The SMTP server 'smtp.gmail.com' requires a secure connection or the client was not authenticated. Ensure you are using SSL connection and check your account's security settings (if you have enabled 2-step verification, try to use App password, otherwise, turn on access for less secure apps).\r\nclientRequestId: d9efe5bc-c03a-4322-8593-65c191717dd8",

Yahoo:

But no settings seemed to work for Yahoo either:

Moving to my domain SMTP server worked just fine, however:

Note: Logic Apps SMPT is not designed for specifying port 465 and will gen an error if you try it. Use 587.

Cleanup

Make sure to remove the deployment from CloudFormation in AWS if you tested that path.

You can regenerate the access key (the &sig part of the URL) from Settings/Access Keys in the Logic App:

Summary

In addressing the need for a serverless method to trigger notifications out of Azure we looked into Azure Logic Apps.  We explored four common routes: SMTP, O365, SendGrid and using AWS API Gateway, SQS, Lambda and SNS.  In truth, the last of those could operate independent of the Azure Logic App.

Azure Logic Apps offer a quick and easy way to create templated notifications emails as well as leverage the Microsoft Graph to get user details from Office 365 (Exchange).