Pages

Friday, February 27, 2026

Home grown email monitor

Medium to large sized companies typically have a complex email environment. Especially with outgoing email that likely has to go thru some form of DLP, anti-virus/anti-spam, and mutliple hosts before being sent out externally.

We recently had an issue with the aforementioned DLP and some external-bound emails were rejected, and we had no process to monitor that issue and was only alerted to the problem when our users reported them.

On a good note, most medium to large companies have at least 2 M365 tenants, one for production and the other for testing or dev purposes. In my Github,I have crafted a simple 3-part script that:

  • Sends an email from production tenant to test/dev tenant, simulating an externally-bound email.
  • Checks the test/dev tenant for said email.
  • Sends alert to IT team if a failure occurs.

    It's all crafted with Graph API, requires a service principal on the production tenant that can send-as from a shared mailbox. Requires another service principal on the test/dev tenant that can read from a shared mailbox.

    Will post the code here in the next few days, https://github.com/panoy86/sysadmin/tree/main/mailmonitor

  • Microsoft Graph API in Azure AutomationAccount

    In my last post, I created an AutomationAccount that had a PowerShell 5.1 runbook and running the Exchange Online module. This time around, I added Graph API.

    Some notes...

  • Create a new runtime environment (RE) using PowerShell 7.4, I could not get Graph API modules to work with older versions.
  • Pre-load the new RE with the minimum Graph API modules such as: Microsoft.Graph.Authentication, Microsoft.Graph.Users, and Microsoft.Graph
  • With a system-assigned managed identity, easy to connect using: Connect-MgGraph -Identity -NoWelcome
  • Saturday, February 21, 2026

    Using Azure Automation with PowerShell

    I have a variety of PowerShell scripts I use for daily work, but wanted to see which ones I can use as a runbook in Azure Automation, so here's my quick foray into it.

    Enable AutomationAccount in the Azure subscription

    • go to Settings/Resource Providers
    • search for Microsoft.AutomationAccount
    • select and register

    Create a new AutomationAccount
    Microsoft article for more details

    • https://portal.azure.com/#create/Microsoft.AutomationAccount
    • subscription: {your subscription}
    • resource group: {your resource group}
    • automation account name: {create a name}
    • region: East US {or your own region}
    • managed identities: system assigned
    • network connectivity: public access
    • tags: {optional, for billing purposes}

    Add the Exchange Online PowerShell module to the AutomationAccount

    • Find/select the Automation account, you may have to switch to "Old Experience"
    • In the search flyout, type "Modules", select Modules from results
    • On the Modules flyout, select Add module icon, Add a module
    • On the Add a module page, configure the following settings:
      • Upload a module file: Select Browse from gallery
      • PowerShell module file: Select Click here to browse from gallery
      • In the Browse Gallery page, type "ExchangeOnlineManagement", select ExchangeOnlineManagement from the results
      • On the details page, select Select to return to the Add a module page
      • Runtime version: Select 5.1 or 7.1 (Preview) or 7.2. To add another version, repeat the steps
      • When you're finished, select Import
    • Back on the Modules search flyout, type "ExchangeOnlineManagement", ensure the Status is Available

    Note: you may need to pre-install modules PowerShellPackageManagement and PowerShellGet with the corresponding version.
    Tip: ensure the runbook and modules are the same version, i.e., 5.1 across, had trouble getting 7.2 to work.

    Grant the Exchange.ManageAsApp API permission for the managed identity to call Exchange Online

    • Open PowerShell, Connect-MgGraph -Scopes AppRoleAssignment.ReadWrite.All,Application.Read.All
    • Confirm if available, Get-MgServicePrincipal -Filter "AppId eq '00000002-0000-0ff1-ce00-000000000000'"
    • From the AutomationAccount\Settings\Identity\System Assigned, get the objectId and save to $MI_ID variable
    • Run the following:
      $MI_ID = "id-from-automation-account"
      $AppRoleID = "dc50a0fb-09a3-484d-be87-e023b12c6440"
      $ResourceID = (Get-MgServicePrincipal -Filter "AppId eq '00000002-0000-0ff1-ce00-000000000000'").Id
      New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $MI_ID -PrincipalId $MI_ID -AppRoleId $AppRoleID -ResourceId $ResourceID

    Add the Exchange Recipient Administrator role to the AutomationAccount

    • Go to portal.azure.com "Roles and administrators"
    • Find/select "Exchange Recipient Administrator", Add assignments
    • Type the AutomationAccount name
    • Add, it should show as a Service Principal

    Create a runbook

    • AutomationAccount\Process Automation\Runbooks
    • Create a runbook, give it name, runbook type: PowerShell
    • Select Runtime version that is the same as the modules you recently imported
    • Description: optional, Review and create
    • On this runbook, click on Edit\Edit in portal and test this code:
      Import-Module ExchangeOnlineManagement
      Connect-ExchangeOnline -ManagedIdentity -Organization yourorg.onmicrosoft.com
      $listOfMailbox = Get-Mailbox -ResultSize 5
      $testOutput = $listOfMailbox | ft
      Write-Output $testOutput
    • Save and click on Test pane