Background
Jocha previously released a very popular mail report-script for Windows Backup. Since the release of Azure Backup we’ve been getting a lot of inquiries regarding the different solutions. One downside with the Azure Backup-agent is that it did not offer mail reports on success/failures.
We’ve built a PowerShell-script that will give you a nice report summary of the last days backup job.
Requirements
– Elevated PowerShell-session.
– At least Windows Management Framework 3.0
– At least Azure PowerShell 1.4
Solution
This PowerShell-script will retrieve the backup jobs from the last 24 hours and send an email with a report of the results.
– Changelog –
2016-05-29 (1.4) Corrected “End Time” in the mail-report.
2016-05-28 (1.3) Streamlined functions and removed unnecessary HTML/CSS.
2016-05-27 (1.2) Now compatible with multiple sources per backup job (Thanks Milan Thaker).
2016-05-19 (1.1) Corrected typos and streamlined variables.
2016-05-17 (1.0) Initial release.
<# .SYNOPSIS Azure Online Backup Report via Mail Written by Jocha AB, https://jocha.se/blog/tech/azure-backup-mail-report-script .DESCRIPTION Version 1.4 This script will compile a report of the Azure Backup jobs from the last 24 hours. .EXAMPLE To automate this script, setup a scheduled task. Name: Azure Backup Email Task Description: Notifies backup admin of scheduled backup status Action: Start a Program Program: Powershell Arguments: -Command "C:\Scripts\OBJobReport.ps1" -ExecutionPolicy Bypass #> ####################################### #-------- Variables to change --------# # Set your Company name $Company = "MyCompany" # Set the recipient/sender email-address $MailTo = "[email protected]" $MailFrom = "$Company Backup <[email protected]>" # SMTP user account password $MailUser = "MyUser" $MailPassword = "MyPassword" # SMTP Server $MailServer = "smtpserver.company.com" # SMTP Port $MailPort = 587 # If your server uses SSL, otherwise set to $false $UseSSL = $true #---- Don't change anything below ----# ####################################### Try { Function FormatBytes { Param( [System.Int64]$Bytes ) [string]$BigBytes = "" #Convert to TB If ($Bytes -ge 1TB) {$BigBytes = [math]::round($Bytes / 1TB, 2); $BigBytes += " TB"} #Convert to GB ElseIf ($Bytes -ge 1GB) {$BigBytes = [math]::round($Bytes / 1GB, 2); $BigBytes += " GB"} #Convert to MB ElseIf ($Bytes -ge 1MB) {$BigBytes = [math]::round($Bytes / 1MB, 2); $BigBytes += " MB"} #Convert to KB ElseIf ($Bytes -ge 1KB) {$BigBytes = [math]::round($Bytes / 1KB, 2); $BigBytes += " KB"} #If smaller than 1KB, leave at bytes. Else {$BigBytes = $Bytes; $BigBytes += " Bytes"} Return $BigBytes } Function Log-BackupItems { Param( [System.String]$Name, [System.String]$Status, [System.String]$Start, [System.String]$End, [System.Int64]$Upload, [System.Int64]$Size ) $Item = New-Object System.Object; $Item | Add-Member -Type NoteProperty -Name "Name" -Value $Name; $Item | Add-Member -Type NoteProperty -Name "Status" -Value $Status; $Item | Add-Member -Type NoteProperty -Name "Start Time" -Value $Start; $Item | Add-Member -Type NoteProperty -Name "End Time" -Value $End; $Item | Add-Member -Type NoteProperty -Name "Uploaded" -Value (FormatBytes -Bytes $Upload); $Item | Add-Member -Type NoteProperty -Name "Total Size" -Value (FormatBytes -Bytes $Size); Return $Item; } Import-module Azure $Password = ConvertTo-SecureString $MailPassword -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential ($MailUser, $Password) $CurrentTime = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") $OBScope = (Get-Date).AddDays(-1) $OBJob = (Get-OBJob -Previous 99).JobStatus | Sort StartTime | Where { $_.StartTime -gt $OBScope } If ($OBJob.JobState -contains "Failed") { $OBResult = "Failed" } ElseIf ($OBJob.JobState -contains "Aborted") { $OBResult = "Aborted" } ElseIf ($OBJob.JobState -contains "Completed") { $OBResult = "Completed" } ElseIf ($OBJob.JobState -eq $null) { $OBResult = "Missing" } Else { $OBResult = "Unknown" } $results=@() If ($OBJob.JobState -ne $null) { $OBJob | % { $OBCount = 0 foreach($Source in $_.DatasourceStatus.Datasource) { $BackupItem = $null $BackupItem = Log-BackupItems -Start $_.StartTime.ToString("yyyy-MM-dd HH:mm:ss") -End $_.EndTime.ToString("yyyy-MM-dd HH:mm:ss") -Name $Source.DataSourceName -Status $_.Jobstate -Upload $_.DatasourceStatus.ByteProgress[$OBCount].Changed -Size $_.DatasourceStatus.ByteProgress[$OBCount].Total $results += $BackupItem $OBCount += 1 } } } Else { $results = Log-BackupItems -Start "N/A" -End "N/A" -Name "N/A" -Status "N/A" -Upload 0 -Size 0 } # Assemble the HTML Report $HTMLMessage = @"$Company Azure Backup Report "@ $email = @{ SMTPServer = $MailServer UseSSL = $UseSSL BodyAsHtml = $true Port = $MailPort Credential = $Credentials Encoding = ([System.Text.Encoding]::UTF8) To = $MailTo From = $MailFrom Subject = "Azure Backup $OBResult" Body = $HTMLMessage } Send-MailMessage @email } Catch { $email = @{ SMTPServer = $MailServer UseSSL = $UseSSL BodyAsHtml = $true Port = $MailPort Credential = $Credentials Encoding = ([System.Text.Encoding]::UTF8) To = $MailTo From = $MailFrom Subject = "Azure Backup Failed." Body = "The backup script failed to run!" } Send-MailMessage @email }$( $html = $results | ConvertTo-HTML -Fragment $xml=[xml]$html $attr=$xml.CreateAttribute('id') $attr.Value='items' $xml.table.Attributes.Append($attr) | out-null $html=$xml.OuterXml | out-string $html )
$Company Azure Backup Report
Backup Result: $OBResult
We hope you’ve found this article helpful, feel free to share it on your social platforms.
Please let us know if you have any questions!
Thanks for posting this script. One small modification is needed to make sure that user input is not required for credential.
Change Line 46 as following:
$Credentials = New-Object System.Management.Automation.PSCredential ($MailUser, $$Password)
Have to use the SecureString password to pass the credentials to PSCredential object
Hi Milan,
Glad it came to use. Quite right, if your SMTP-server does not require authentication that step is unnecessary.
Best regards,
Joakim
Accidentally included additional $ before $Password variable
$Credentials = New-Object System.Management.Automation.PSCredential ($MailUser, $Password)
Here is a slight modification that we made for a backup job consisting multiple drives. Get-OBJob return the result in a JSON array for multiple drive letters. This modification will take care of all the drive letters.
AddHours(-4) was added to normalize the time according to the time zone that I'm in.
$results=@()
If ($OBJob.JobState -ne $null) {
$OBJob | % {
$count = 0
foreach($obj in $_.DatasourceStatus.Datasource)
{
$BackupItem = $null
$OBStartTime = $_.StartTime.AddHours(-4).ToString("yyyy-MM-dd HH:mm:ss")
$OBEndTime = $_.EndTime.AddHours(-4).ToString("yyyy-MM-dd HH:mm:ss")
$BackupItem = Log-BackupItems -Start $OBStartTime -End $OBEndTime -Name $obj.DataSourceName -Status $_.Jobstate -Changed $_.DatasourceStatus.ByteProgress[$count].Changed -Bytes $_.DatasourceStatus.ByteProgress[$count].Total
$BackupItem
$results += $BackupItem
$count += 1
Hi Milan,
We've updated the script, it now runs with multiple sources per job. Thank you for the feedback!
Best regards,
Joakim
we do not need any smtp credentials, what do I have to change?
what do you mean with service account need access to azure?
Hi Ivano,
If you're running without authentication you should comment out (put a # at the beginning) row 84, 85, 148, and 164.
I have not tried these changes in our environment since they require authentication and SSL, please let me know if you need any more assistance.
Best regards,
Joakim
Hi Joakim
Now it is working fine!
The only thing is, that it appears as SPAM, any solution? :)
Thanks for the quick help!
Hi Ivano,
It is most likely because you're not authenticating. I would recommend using a safer configuration, or if its only going to send reports to you, whitelist the email-address.
Best regards,
Joakim
As a nice to have i did this:
# Set your Server name
$Server = $env:computername
In both Subject lines:
Subject = "$Server Azure Backup $OBResult"
Then you can see directly the Server in the Subject.
This helps when you habe more than one Server.
Cheers
Hi Ivano,
Thank you for the feedback Ivano. Makes sense if you're using a separate Recovery Point for each server.
Best regards,
Joakim
Since some days i recieve this message in the report email:
The backup script failed to run!
Can you tell me what could cause this problem?
Any chance the script can have a timezone added to it (my reports are reporting 12hours out)? I tried the above option Milan Thaker put in (for time) but this made the script report failed backups. Also does this script report if I have multiple backups set during the day in the one report? e.g 9am/12pm/9pm
You could set it up so that it would take parameters.
[CmdletBinding(DefaultParameterSetName = "Company")]
PARAM (
[Parameter(ParameterSetName = "Company", Mandatory = $True)]
[String]$Company,
[Parameter(Mandatory = $false, HelpMessage = "Specify the Sender Email Address")]
[ValidatePattern("[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")]
[String]$MailFrom="[email protected]",
[Parameter(Mandatory = $true, HelpMessage = "You must specify the Destination Email Address")]
# [ValidatePattern("[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")]
[String[]]$MailTo,
[Parameter(Mandatory = $false, HelpMessage = "Specify the Email Server to use (IPAddress or FQDN)")]
[String]$MailServer="LOCALHOST"
)
hi
I am new to this world,
just to be sure, this script needs to be run in every server I install the azure backup agent right?
since we are a Solution Provider this requirement might be an issue for us I think, since we need to install this in multiple customer
– Service account needs to have Azure access.
thanks
Hi Karlo,
Yes, this needs to be set up for each server running Azure Backup. Regarding the service account it does not need specific Azure access.
Hi Joakim,
Thank you so much for this script! It works great and I'm using Server 2012 R2.
I'm fairly new to Powershell so excuse my ignorance but I have a quick question.
I'm running this script against 10 servers and it's sending out 10 emails. This is fine but I'm looking to run it on even more servers and would prefer one email with all the success and failures of each server in that email – Is this something that can be achieved easily or would the script have to be changed completely?
Thanks,
Mo
Hi Mo,
The way it works currently (as far as i know) the commands need to be run on the local machine. You could possibly rewrite it to remote execute and then pull back the results, or schedule the script on all the servers, but instead of emailing it you could save the report on a file area, which you could then merge and send as a combined report… Not sure which would be the easiest.
But I recommend using the full Azure Backup software (which includes reporting) for an environment of that size instead of using this.
Best regards,
Joakim
hi
…and for a 7 days scope in ascending order?
any idea?
Adjust line 91 from -1 to how many days you want to go back
Hi Joakim,
Thank you so much for this script! It works great.
I would like to retrieve restoration jobs only and not the backup job.
Is it possible to do this.
thank you.
The only thing it has told me so far is that the script failed to run (even though a manual review via the portal indicates otherwise). So, while the e-mail portion of it functions for me, the actual reporting does not.
Hi Jeff,
Try removing the Try/Catch to see where it fails for you.
Best wishes,
Joakim
Hi,
Thank you for this script.
I would like to display the Restore backup job in "Jobtype"?
Ps line command: (Get-obJob -previous 5).Jobtype
Tks.
Any suggestion
Hi
Thank you for your script, I am new to powershell scripts and have 2 issue
1.is i get asked for "Windows Powershell Credital Require"
2.I get error Send-MailMessage : An invalid character was found in the mail header: '>'.
At C:\Users\Administrator\Desktop\AzureBackupReport.ps1:171 char:5
+ Send-MailMessage @email
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: ([email protected]>:String) [Send-MailMessage], FormatException
+ FullyQualifiedErrorId : FormatException,Microsoft.PowerShell.Commands.SendMailMessage
Please could you advise me on these issues?
Kind Regards
Paul
ignore issue number 2 that was typo on my behalf in the email address I have another issue all i get is backup script failed to run email through to me when I run this?
I have sold issue 1 we dont use authentication for our smtp so followed your steps I had missed and commented the lines, just the "Backup Script Failed To Run" issue to resolve.
Ignore I have solved all my issues.
Hi ,
Do i need to run this script on very VM inside the os or any way to run from outside the vm like ,,, from my own laptop to extract backup report for my subscription