azure4 Min Read

Azure Functions - How to trigger an email on any change in storage container blob

Gorav Singal

July 17, 2020

TL;DR

Create an Azure Function with BlobTrigger binding pointed at your container, add a SendGrid output binding, and you get email alerts on every file change — no polling required.

Azure Functions - How to trigger an email on any change in storage container blob

Introduction

In Azure, assuming you are having a storage container. And, you want to get an alert email if there are anything changes in that container. You want the email on any file event, whether its a new file, modified file, or deleted file.

Showing storage containers list:

Azure Storage Containers

I will be targetting container name: gtest Showing files inside container: gtest:

Azure Storage Containers files

See solution for this problem in full automation with Azure ARM template and code deployment automation

Creating Azure Function

  • Go to your resource group
  • Click on Add
  • Search and look for Function App
  • Click on create
  • Fill the form, your subscription.
    • Under Publish, choose Code
    • Runtime stack: Node.js, version 12.0
    • Choose your region
    • Storage Account: Choose your existing storage account OR create a new one
    • Operating System: Windows
    • Plantype: Serverless
    • Enable Application Insights: Yes

Azure Function

Azure Function create

Create actual Function

  • Goto your function app. On the left side, you will see an option: Functions.
  • Click on it.
  • Now click on Add
  • You will get a list of templates. These are ready-made templates for multiple purposes.
  • Choose: Blob trigger: Javascript. You can choose another language.
  • Give a name to your function
  • In Path, put your storage container name followed by a placeholder {name}

Example below:

Azure Function blob trigger

Edit Code

After creating a function, you get some basic pre-written code. Click on Code + Test, and just put something to console to test whether your code setup is good.

Azure Function code

module.exports = function (context, myBlob) {
    context.log("JavaScript blob");
    context.log(JSON.stringify(context));
    context.log(JSON.stringify(myBlob));
};

Now, click on Integration on the left side. This will give a graphical view of your function. Its input and output. It will look something like below:

Azure Function integration

Create an account with Sendgrid

First, create an account on sendgrid.com to obtain an API-key. This is a free account, to begin with. You also need to authenticate the sender email with SendGrid, with whom you want to send the email. Once you get the api key, test it with curl command:

export SENDGRID_API_KEY='your-api-key'
curl --request POST \
  --url https://api.sendgrid.com/v3/mail/send \
  --header "Authorization: Bearer $SENDGRID_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{"personalizations": [{"to": [{"email": "[email protected]"}]}],"from": {"email": "[email protected]"},"subject": "Sendgrid email test","content": [{"type": "text/plain", "value": "Sendgrid email body content"}]}'

Once you test this, let’s proceed to configure on azure.

Configure Email setup with Sendgrid

  • Goto Integration again. Click on Outputs: Add Output
  • In Binding type, select Sendgrid
  • Message parameter name: $return
  • SendGrid API Key, Click on New (below the drop-down)
    • Give a name to its key, and put the API-key in value.
  • You can fill the rest of the fields or can provide from the code itself.

Azure Function sendgrid

Now, your integration looks like this:

Azure Function integration

Goto your Code + Test section. Put following code in index.json:

module.exports = function (context, myBlob) {
    context.log("JavaScript blob");
    context.log(JSON.stringify(context));
    context.log(JSON.stringify(myBlob));
    files = context.bindingData.name;
    context.log(files);
    var message = {
        "personalizations": [ { "to": [ { "email": "[email protected]" } ] } ],
        subject: "Files has been changed in azure container",
        content: [{
            type: 'text/plain',
            value: files
        }]
    };
    context.done(null, message);
};

On files drop-down, open function.json. It should have content like this:

{
  "bindings": [
    {
      "name": "myBlob",
      "direction": "in",
      "type": "blobTrigger",
      "path": "gtest/{name}",
      "connection": "AzureWebJobsStorage"
    },
    {
      "name": "$return",
      "apiKey": "GSINGAL_SENDGRID_APIKEY",
      "to": "[email protected]",
      "from": "[email protected]",
      "direction": "out",
      "type": "sendGrid"
    }
  ]
}

Logs

In Code + Test section, in bottom there is a section: Logs. Expand it. It will show a message something like:

Connecting to application insights

And, finally shows: Connected

Azure Function logs

This log console is an active window. It means if our function gets triggered, it will show the live logs.

Testing

Let’s test our setup. Goto your storage container which you configured. In my case, it is gtest

Try to add or modify any file. And, watch the console. The azure function will receive the notification within +- 5 seconds.

And if your setup is successful, if I change my file: test.txt. It will show output like:

2020-07-17T08:22:14Z   [Information]   Function started (Id=3fd17c37-e7c2-48b7-9ece-f9c3ea2bc3dd)
2020-07-17T08:22:14Z   [Information]   JavaScript blob
2020 - 07 - 17 T08: 22: 14 Z[Information] {
  "invocationId": "3fd17c37-e7c2-48b7-9ece-f9c3ea2bc3dd",
  "executionContext": {
    "invocationId": "3fd17c37-e7c2-48b7-9ece-f9c3ea2bc3dd",
    "functionName": "BlobTrigger1",
    "functionDirectory": "D:\\home\\site\\wwwroot\\BlobTrigger1"
  },
  "bindings": {
    "myBlob": "This is a test text.\nAnother text.\n"
  },
  "bindingData": {
    "blobTrigger": "gtest/test.txt",
    "uri": "https://gsingal.blob.core.windows.net/gtest/test.txt",
    "properties": {
      "cacheControl": null,
      "contentDisposition": null,
      "contentEncoding": null,
      "contentLanguage": null,
      "length": 35,
      "contentMD5": "CZfHw5C4V9GrN+SzoPfJdg==",
      "contentType": "text/plain",
      "eTag": "\"0x8D82A2A8241EB42\"",
      "lastModified": "7/17/2020 8:22:13 AM +00:00",
      "blobType": "BlockBlob",
      "leaseStatus": "Unlocked",
      "leaseState": "Available",
      "leaseDuration": "Unspecified",
      "pageBlobSequenceNumber": null,
      "appendBlobCommittedBlockCount": null,
      "isServerEncrypted": true
    },
    "metadata": {},
    "name": "test.txt",
    "sys": {
      "methodName": "BlobTrigger1",
      "utcNow": "2020-07-17T08:22:13.765Z"
    },
    "invocationId": "3fd17c37-e7c2-48b7-9ece-f9c3ea2bc3dd"
  }
}
2020-07-17T08:22:14Z   [Information]   "This is a test text.\nAnother text.\n"
2020-07-17T08:22:14Z   [Information]   test.txt
2020-07-17T08:22:14Z   [Information]   Function completed (Success, Id=3fd17c37-e7c2-48b7-9ece-f9c3ea2bc3dd, Duration=208ms)

In the above logs, I’ve beautified JSON just to make sure it is readable. And, it should trigger an email as well. Check out your email. Be sure to check your Junk email folder as well.

See solution for this problem in full automation with Azure ARM template and code deployment automation

Let me know if the setup does not work for you. Thanks for reading…

Share

Related Posts

How to automate create Function App with Blob Trigger and Sendgrid Notification through Azure Arm Template and deploy

How to automate create Function App with Blob Trigger and Sendgrid Notification through Azure Arm Template and deploy

In previous post (Trigger Email on Blob Trigger), we saw how we can create such…

Microsoft Azure Just-In-Time access control

Microsoft Azure Just-In-Time access control

According to Microsoft, Therefore, they recently posted about a feature in beta…

Azure Storage Blob - How to List and Download Blob from Azure Storage container in Python (No Azure library)

Azure Storage Blob - How to List and Download Blob from Azure Storage container in Python (No Azure library)

Introduction In this tutorial we will see, How to list and download storage…

Azure Storage Blob - How to List Blob, Download Blob from Azure Storage container in Python (pypy libs)

Azure Storage Blob - How to List Blob, Download Blob from Azure Storage container in Python (pypy libs)

Introduction In this tutorial we will see: How to instantiate different classes…

Claude Code Skills — Build a Better Engineering Workflow with AI-Powered Code Reviews, Security Scans, and More

Claude Code Skills — Build a Better Engineering Workflow with AI-Powered Code Reviews, Security Scans, and More

Most developers use Claude Code like a search engine — ask a question, get an…

Building an AI Voicebot for Visitor Check-In — A Practical Guide to Handling the Messy Parts

Building an AI Voicebot for Visitor Check-In — A Practical Guide to Handling the Messy Parts

Every office lobby has the same problem: a visitor walks in, nobody’s at the…

Latest Posts

AI Video Generation in 2025 — Models, Costs, and How to Build a Cost-Effective Pipeline

AI Video Generation in 2025 — Models, Costs, and How to Build a Cost-Effective Pipeline

AI video generation went from “cool demo” to “usable in production” in 2024-202…

AI Models in 2025 — Cost, Capabilities, and Which One to Use

AI Models in 2025 — Cost, Capabilities, and Which One to Use

Choosing the right AI model is one of the most impactful decisions you’ll make…

AI Image Generation in 2025 — Models, Costs, and How to Optimize Spend

AI Image Generation in 2025 — Models, Costs, and How to Optimize Spend

Generating one image with AI costs between $0.002 and $0.12. That might sound…

AI Coding Assistants in 2025 — Every Tool Compared, and Which One to Actually Use

AI Coding Assistants in 2025 — Every Tool Compared, and Which One to Actually Use

Two years ago, AI coding meant one thing: GitHub Copilot autocompleting your…

AI Agents Demystified — It's Just Automation With a Better Brain

AI Agents Demystified — It's Just Automation With a Better Brain

Let’s cut through the noise. If you read Twitter or LinkedIn, you’d think “AI…

Supply Chain Security — Protecting Your Software Pipeline

Supply Chain Security — Protecting Your Software Pipeline

In 2024, a single malicious contributor nearly compromised every Linux system on…