Series

Extending EasyLife 365 with Webhooks:
  1. 1: Extending EasyLife 365 with Webhooks: A Step-by-Step Guide to Email Notifications (you are reading this article)

A Step-by-Step Guide to Email Notifications

Today, we're exploring how to extend EasyLife 365 Collaboration’s functionality using webhooks. Webhooks let you execute custom code at different stages of an object’s lifecycle. In this guide, we'll create an Azure Functions-based solution that sends email notifications using the Graph API whenever a team is created using a specific template.

Introduction to EasyLife 365 Webhooks

The EasyLife 365 Collaboration platform supports webhooks at multiple points in the workflow:

  • During resource provisioning (Teams, Groups, SharePoint sites, guest accounts)
  • When metadata changes are made to existing resources
  • As part of escalation actions in policies

This allows you to build sophisticated automation workflows that integrate with your existing systems and processes.

Components and Setup

Our sample solution showcases a common webhook use case: sending email notifications when new teams are created. The solution architecture consists of:

Azure Components

  • Function App with PowerShell runtime
  • App Service Plan
  • Storage Account for queuing
  • Application Insights for monitoring

Function Components

Two Azure Functions working together:

  • mailrequest HTTP-triggered function that receives webhook requests from EasyLife and writes them to a storage queue
  • mailqueue: Queue-triggered function that processes messages and sends emails via Graph API

This architecture ensures reliable message processing with built-in retry capabilities through Azure Storage Queues.

Prerequisites

Before starting:

Infrastructure Deployment

With PowerShell and Azure CLI

First, we will use PowerShell and Azure CLI to login to our Azure Subscription, create a resource group and function app and add environment variables to the function app:

_powershell_

# Update these variables

$resourceGroup = "rg-easylife-webhook"
$location = "westeurope"
$storageAccount = "saeasylifewebhook"
$functionApp = "func-easylife-webhook"
$mailFromAddress = "noreply@easylife365.cloud"
$mailToAddresses = "user1@easylife365.cloud user2@easylife365.cloud"

# Login to Azure

az login

# Create Resource Group

az group create --name $resourceGroup --location $location

# Create Storage Account

az storage account create `
    --name $storageAccount `
    --location $location `
    --resource-group $resourceGroup `
    --sku Standard_LRS

# Create Function App

$funcAppOutput = az functionapp create `
    --name $functionApp `
    --storage-account $storageAccount `
    --consumption-plan-location $location `
    --resource-group $resourceGroup `
    --runtime powershell `
    --functions-version 4 `
    --assign-identity '[system]' | ConvertFrom-Json

# Add Function App Environment Variables

az functionapp config appsettings set `
    --name $functionApp `
    --resource-group $resourceGroup `
    --settings mailFromAddress=$mailFromAddress mailToAddresses=$mailToAddresses

Note: The code is available on our GitHub, where you will also find bicep templates. I’ll walk you through that process in a future post.

Assigning Permissions

The Azure Function uses its system assigned managed identity to authenticate with Microsoft Graph. After deploying your function app, you'll need to grant the following Graph API permissions to its managed identity:

  • User Read All
  • Group Read All
  • Mail Send

powershell

# Get service principals for permission assignment

# the PowerShell deployment option will set the following variable
$servicePrincipalId = $funcAppOutput.identity.principalId
$graphObjectId = (az ad sp list --display-name 'Microsoft Graph' | ConvertFrom-Json)[0].id

# Assign permissions to the managed identity

@(
    'df021288-bdef-4463-88db-98f22de89214', # user.read.all
    '5b567255-7703-4780-807c-7be8301ae99b', # group.read.all
    'b633e1c5-b582-4048-a93e-9f11b44c7e96' # mail.send
) | ForEach-Object {
    $body = @{
        principalId = $servicePrincipalId
        resourceId = $graphObjectId
        appRoleId = $_
    } | ConvertTo-Json -Compress
    $uri = "https://graph.microsoft.com/v1.0/servicePrincipals/$servicePrincipalId/appRoleAssignments"
    $header = "Content-Type=application/json"
    az rest --method POST --uri $uri --header $header --body $body.Replace('"',"'")
}

Deploying the PowerShell Code

Once the infrastructure is set up, the next step is to deploy the function code. The repository contains two main functions:

  • mailrequest/run.ps1: The HTTP-triggered function that receives webhooks
  • mailqueue/run.ps1: The queue-triggered function that sends emails

Deploy the code using PowerShell and Azure CLI:

powershell

# Update deploy package

$deployPath = Get-ChildItem | `
    Where-Object { $_.Name -notmatch "deploypkg" -and $_.Name -notmatch "_automation" } | `
    Compress-Archive -DestinationPath deploypkg.zip -Force -PassThru

# Deploy the zipped package

az functionapp deployment source config-zip `
    --name $functionAppName `
    --resource-group $resourceGroupName `
    --src $deployPath.FullName

Testing the Function

After deploying the function app and uploading the PowerShell code, we’re ready for testing.

1. Get Function URL:

  • Open your Function App in Azure Portal
  • Navigate to Functions > mailrequest
  • Click "Get Function URL"
  • Copy the complete URL with code parameter

2. Test with PowerShell:

Use the following snippet to send a simulated EasyLife webhook to the function app to validate it is working as intended. Please note, the first execution of the function app will be slower than subsequent executions.

powershell

# Call Function App HTTP endpoint

$uri = 'https://<functionAppName>.azurewebsites.net/api/mailrequest?code=<code>'
$body = @{
    eventType = "groupcreated"
    # the user object contains information about the creator of the team
    user = @{
        # use real userPrincipalName
        userPrincipalName = "testuser@yourdomain.com"
    }
    # the group object contains information about the team
    group = @{
        displayName = "Test Team"
        # Use real group ID of a team
        id = "00000000-0000-0000-0000-000000000000"
    }
} | ConvertTo-Json –Compress
Invoke-RestMethod -Uri $uri -Body $body -Method Post

Configuring EasyLife

If the test is successful, we are finally ready to add the function app’s URL to the webhook configuration in the EasyLife Cockpit:

  • Open the EasyLife Cockpit
  • Navigate to Templates > Teams
  • Select an existing template or create a new one
  • Under Provisioning, paste your function URL in the webhook field
  • Save changes

To verify:

  • Create a new team using your configured template
  • Check for the email notification being sent
  • Review Application Insights logs for any issues

Best Practices

  • Error Handling: Implement comprehensive error handling in your functions.
  • Monitoring: Use Application Insights to monitor function performance.
  • Security: Rotate function keys regularly and store sensitive data securely in Key Vault.
  • Testing: Use a dedicated development environment for testing.
  • Logging: Implement detailed logging for troubleshooting.

Additional Resources

Conclusion: Tailor Your Microsoft 365 Governance with Webhook Integration

Webhooks offer a powerful way to enhance EasyLife 365 Collaboration’s functionality and integrate it seamlessly with your existing systems. This example demonstrates just one possible use case - sending email notifications - but the same pattern can be adapted for many other scenarios, such as:

  • Ticketing system integration
  • Custom notifications for policy escalations
  • Custom SharePoint site provisioning
  • Policy compliance reporting
  • Custom approval workflows

Keep an eye out for upcoming posts in this series, where we’ll dive into more exciting use cases.

For more information and support, visit our documentation at docs.easylife365.cloud or reach out to our experts for personalized guidance and support.

Other Articles