In this post, we will discuss the process of creating that solution using Azure Function Apps and SendGrid to send emails based on your Powershell Functions which runs in your local machine. We will see that how can we build a serverless email solution that reports your disk usage with Azure Functions, SendGrid and Powershell.

We are going to examine this scenario in the following categories:

1- Configure SendGrid and Azure

2- Create an Azure Function App

3- Create an Azure Funciton – Experimental language was used  in this scenario

4- Create your local Powershell Script to learn aobut your disk space and usage

6- (Optional) Put your poweshell script into the task schedule and send your disk usage as an email by calling your Azure Function URL

Please keep in mind that you can customize your Azure Powershell function and local PowerShell script based on your requirements and needs. I think that it might be useful to implement this kind of logic into your solutions.

Configure SendGrid and Azure

In this demo, I preferred to use free SendGrid account which provides us a software plan as 25,000 emails per month to get things going.

You can find SendGrid Email Delivery in Azure Marketplace in the Web Category. Once the SendGrid account is successfully created, you need to obtain your SendGrid API key to use this API key later during the creation of the function. So that, make sure that you are going to keep it in a secure place.

Annotation 2019-01-12 165233
Annotation 2019-01-12 165405
Annotation 2019-01-12 165449

Once your SendGrid Account is created, you can click Manage in the left corner, and it will automatically direct you into the SendGrid Account. The next step that we are going to to do is to obtain your API key which is going to be needed to be used in your Function App.

Annotation 2019-01-12 165808

Please select Create API Key on the top of the right Corner. Specify your API Key details such as Name and Permissions and then Click “Create & View.”

image
Annotation 2019-01-12 165944
image


Remember that this is your only option to view and obtain your API Key. For security purposes, it will not allow the API Key value to be displayed.


Create an Azure Function App

As a next step, we are going to create our new function app service. As you see in the following screenshot, We need to use resource group and storage account to store the function code and its components.

Annotation 2019-01-12 170335

Since we are going to create our function app as Powershell script, we need to review and change our platform features. Please go to your previously created function and from the General Settings open up the Function App Settings section. Now we have to change our RunTime version from ~2 to ~1 to be able to access the Powershell language support once we are choosing our function template when experimental language support is enabled.

Annotation 2019-01-12 171430
image
Annotation 2019-01-12 171738

Since we are going to trigger our SendGrid API we are going to need to choose our template as HTTP Trigger. You can specify your function language, name and Authorization Level.

Annotation 2019-01-12 171759

The function HttpTriggerPowershell1 and run.ps1 script are going to be our sources which is going to be responsible to call the SendGrid API.


Create and Modify an Azure Function

Please provide following expected variables into your run.ps1 script. We need to define “to” and “from” sections in the body variable.

To be able to call post method, we need to populate our header variable, please provide your API KEY which is obtained in previous section.run.ps1

# POST method: $req
$requestBody = Get-Content $req -Raw | ConvertFrom-Json
$count = $requestBody.value.count $date = $requestBody.date
$firstline = "Id | Type | Size(GB) | FreeSpace(GB) | FreeSpace(%)"+"\n\n\n"
$info += $firstline
for($i=0;$i -lt $count;$i++){
    $line = $requestBody.value[$i].DeviceID + "\t" + $requestBody.value[$i].DriveType + "\t" + $requestBody.value[$i].'Size (GB)' + "\t"  + $requestBody.value[$i].'Free Space (GB)' + "\t" + $requestBody.value[$i].'Free Space (%)' +  "\t\t\n\n\n"
$info +=  $line }
$body = @" '{"personalizations": [{"to": [{"email": "TO_EMAIL_ADDRESS"}]}],"from": {"email": "FROM_EMAIL_ADDRESS"},"subject": "Current Disk Space Status --> $date","content": [{"type": "text/plain", "value": "$info"}]}' "@
$header = @{"Authorization"="Bearer YOUR API KEY HERE";"Content-Type"="application/json"} 
Invoke-RestMethod -Uri https://api.sendgrid.com/v3/mail/send -Method Post -Headers $header -Body $body

Create a Powershell Script to learn about your disk space and usage

Now we need to customize our local PS Script which call our Azure Function app to be able to invoke rest method. We need to obtain our function URL from Azure Portal and place into the expected parameter in the “Invoke-RestMethod”.

2

get_disk_space.ps1

$servername = "localhost"
$diskinfo = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $servername |
Select-Object @{Name="DeviceID";Expression={$_.DeviceID}},          @{Name="DriveType";Expression={switch ($_.DriveType){
0 {"Unknown"} 1 {"No Root Directory"}
2 {"Removable Disk"}
3 {"Local Disk"}
4 {"Network Drive"}
5 {"Compact Disc"}
6 {"RAM Disk"}
}};
},
@{Name="Size (GB)";Expression={"{0:N1}" -f ($_.Size/1GB)}},
@{Name="Free Space (GB)";Expression={"{0:N1}" -f($_.FreeSpace/1GB)}},
@{Name="Free Space (%)";
Expression={
if ($_.Size -gt 0){
"{0:P0}" -f($_.FreeSpace/$_.Size)
}
else
{
0
}
}
}
$data = @{date="{0:MM}/{0:dd}/{0:yyyy} {0:hh}:{0:mm}" -f (get-date);value = $diskinfo} $json = $data | ConvertTo-Json Invoke-RestMethod -Method post -uri "YOUR COPIED FUNCTION URL HERE" -Body $json

Configure to run a Powershell Script into Task Scheduler

To create a periodic action which send your participant about given specified machine’s disk usage status, we need to call our get_disk_space.ps1 script on a daily basis.

As an example I configured my schedule to send an email at 8:30 pm every day with the information of my current disk space usage.

tempsnip

In the action tab we need to call required script which collect our disk usage info and by calling Invoke-RestMethod with your function URL.

tempsnip2

Here is the outcome of our scenario;

tempsnip3