Using SendGrid binding from PowerShell in Azure Functions

Published by Marco Obinu on

Azure functions in PowerShell

As an ITPro, I approached Azure Functions in PowerShell as an alternative to Azure Automation, to have an additional way to implement serverless automation. I found them interesting in terms of integration with other services, like Logic Apps and Azure Monitor Alerts.
Azure Functions offer various bindings, to get input or produce output data in different formats, making the platform highly integrable. However, since PowerShell support is still in preview, documentation is quite incomplete. It notably lacks in examples: you can find a lot of them in other languages, which are not so easy to convert in PowerShell.
That said, I had to implement mail notification in some functions, and I decided to use SendGrid for this scope.
You can easily send messages to SendGrid from you PoSH by using Send-MailMessage, but there’s a SendGrid output binding perfect for this scope. As usual, its doc page lacks in PoSH examples, so I decided to invest some time in making it work.

Creating a SendGrid free plan

First of all, you need to create a SendGrid account with the free plan.
From Azure Portal, search for SendGrid Account and add one of them by compiling the following blades:

SendGrid on Azure - personal contacts

SendGrid on Azure – choose a plan

SendGrid on Azure - personal contacts

SendGrid on Azure – personal contacts

SendGrid on Azure - confirm contacts

SendGrid on Azure – confirm contacts

Genete an API key and configure the Function App

Once created, you need to browse the SendGrid portal and create a new API key that will be used by the Function App:

Open SendGrid management portal

Open SendGrid management portal

From there, you have to create a new API key, assigning it a name. For demo purposes, you can choose a full access API key:

Go to API key management page

Go to API key management page

Generate a new API key

Generate a new API key

Assign a name and choose a permission level

Assign a name and assign a permission level

Copy the generated key

Copy the generated key

Now you have the API key you can insert in the appSettings of the Function App; you can use the following AZ CLI command to update the default:

az functionapp config appsettings set -n FunctionAppName -g ResourceGroupName \
    --settings "AzureWebJobsSendGridApiKey=Insert your key here"

As a more secure alternative, you can also store the key inside an Azure Key Vault, and then referenciate it in App Settings. You can find an example in my GitHub repo.

Use SendGrid binding in your function

To proceed over, you need to integrate the SendGrid binding in your function.

Let’s start by adding the following extension block in host.json:

"extensions": {
  "sendGrid": {
      "from": "Azure Functions <samples@functions.com>"
  }
}

Then, you need to modify your function.json by adding a new output binding:

{
  "type": "sendGrid",
  "direction": "out",
  "name": "message",
  "apiKey": "AzureWebJobsSendGridApiKey"
}

In this way, the function app retrieves the ApiKey from the corresponding appSetting parameter, while the function manages other required fields, like sender, recipient, and subject, at runtime.

Now, you have to prepare something that Push-OutputBinding cmdlet can handle to send a message to SendGrid. I read different examples in the official doc page and found an example of how to send messages from Azure Automation runbooks, so I understood I need to compile the following JSON to communicate with SendGrid:

{
  "subject": "Mail test",
  "content": [
    {
      "type": "text/plain",
      "value": "input"
    }
  ],
  "personalizations": [
    {
      "to": [
        {
          "email": "sender@contoso.com"
        }
      ]
    }
  ],
  "from": {
    "email": "AzFunctionDemo@omegamadlab.com"
  }
}

You can achieve the above result by using an appropriate structure of array and hash tables.

Then, sending this code to SendGrid is as simple as converting it to JSON (be aware of the depth parameter, needed to preserve the original structure) and use the Push-OutputBinding cmdlet:

$mail = @{
    "personalizations" = @(
        @{
            "to" = @(
                @{
                    "email" = $emailAddress 
                }
            )
        }
    )
    "from" = @{ 
        "email" = "AzFunctionDemo@omegamadlab.test" 
    }        
    "subject" = "Mail test"
    "content" = @(
        @{
            "type" = "text/plain"
            "value" = "input"
        }
    )
}

Push-OutputBinding -Name message -Value (ConvertTo-Json -InputObject $mail -Depth 4)  

All done! Not so difficult, indeed. You can eventually chance content type to text/html to send a visual report; you can find additional examples in my GitHub repo.

 

 


Marco Obinu

Curious by nature, talkative geek who can speak in front of a public or a camera, in love with technology, especially SQL Server. I want to understand how things work and to solve problems by myself during work as in my many hobbies.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: