Powershell : Critical SMTP communications should never fail, unknowingly!


In today's interconnected business environment, email remains a critical communication channel for many organizations. When important messages fail to arrive, it can disrupt operations, delay critical processes, and potentially impact customer service. This is especially true for automated system notifications, inter-departmental communications, and messages from external partners.

In this blog post, I'll share a PowerShell solution that monitors email communications between specific addresses and sends alerts when expected messages aren't received. Whether you're monitoring incoming messages from a business partner or ensuring outgoing notifications are properly sent, this script provides peace of mind through automated verification.

The Problem: Missing Critical Emails

Has your organization ever faced these scenarios?

  • A vital daily report email from a business partner never arrived, but nobody noticed until it was too late
  • Your automated notification system failed to send confirmation emails to customers

Traditional monitoring solutions often overlook email flows, focusing instead on server health or general mail flow. Our solution addresses this gap by monitoring specific sender-recipient pairs and alerting you when expected communications don't arrive within a designated timeframe.

Email Monitoring Script

This script leverages Exchange Online's message tracking capabilities to search for emails between specific addresses within a defined time window. If no matching emails are found, it sends a professionally formatted alert email to your designated monitoring address.

Key Features

  • Directional Monitoring: Monitor both inbound and outbound email flows
  • Configurable Check Intervals: Define how frequently to check for messages
  • Professional Alert Emails: Sends eye-catching HTML emails with clear warning indicators
  • Console Visibility: Real-time status updates in the PowerShell console
  • Detailed Logging: All activities recorded to a log file for audit purposes

Prerequisites

  • PowerShell 5.1 or later
  • Exchange Online PowerShell module installed (Install-Module ExchangeOnlineManagement)
  • Appropriate Exchange Online permissions to run message tracking queries
  • Access to an SMTP server for sending alert emails

Understanding the Script Components

The script consists of several core components:

  1. Configuration Parameters: Define monitoring behavior and connection details
  2. Exchange Online Connection: Establish access to message tracking logs
  3. Email Checking Logic: Search for messages within the specified timeframe
  4. Alert Generation: Create and send professional HTML notification emails
  5. Monitoring Loop: Continuously check for messages on the defined schedule

Let's examine each component in detail.

Configuration Parameters

The script accepts several parameters to customize its behavior:

param (
    [Parameter(Mandatory=$false)]
    [string]$LogPath = "C:\Logs\EmailMonitoring.log",
    
    [Parameter(Mandatory=$false)]
    [int]$CheckIntervalMinutes = 5,
    
    [Parameter(Mandatory=$false)]
    [ValidateSet("Inbound", "Outbound")]
    [string]$Direction = "Inbound",
    
    [Parameter(Mandatory=$false)]
    [string]$AlertEmail = "alerts@company.com",
    
    [Parameter(Mandatory=$true)]
    [string]$SMTPServer = "smtp.company.com"
)

# Predefined sender and receiver addresses
$SenderEmail = "sender@center.com"
$ReceiverEmail = "receiver@company.com"
$MailboxEmail = "monitoring@company.com"

These parameters and variables control:

  • Where logs are stored
  • How often to check for messages (default: every 5 minutes)
  • Which direction to monitor (inbound or outbound)
  • Where to send alerts when messages are missing
  • Which SMTP server to use for sending alerts
  • The specific email addresses to monitor

Exchange Online Connection

The script connects to Exchange Online using modern authentication:

try {
    Write-Host "Attempting to connect to Exchange Online using modern authentication..."
    -ForegroundColor Cyan
    Write-Log "Attempting to connect to Exchange Online using modern authentication..."
    
    # Import the Exchange Online Management module
    Import-Module ExchangeOnlineManagement -ErrorAction Stop
    
    # Connect using modern authentication
    Connect-ExchangeOnline -ShowBanner:$false
    
    Write-Host "Successfully connected to Exchange Online" -ForegroundColor Green
} 
catch {
    $errorMessage = "Failed to connect to Exchange Online: $_"
    Write-Host $errorMessage -ForegroundColor Red
    Write-Log $errorMessage
    exit 1
}

This establishes the connection needed to query message tracking logs in Office 365.

Email Checking Logic

The heart of the solution is the email checking function, which searches message traces for communications between the specified addresses:

function Check-Emails {
    try {
        # Calculate time threshold (current time minus interval)
        $timeThreshold = (Get-Date).AddMinutes(-$CheckIntervalMinutes)
        
        # Search for emails based on direction
        if ($Direction -eq "Inbound") {
            # Checking inbound: emails FROM sender TO receiver
            $recentEmails = Get-MessageTrace -SenderAddress $SenderEmail 
            -RecipientAddress $ReceiverEmail -StartDate $timeThreshold 
            -EndDate (Get-Date)
        } else {
            # Checking outbound: emails FROM receiver TO sender
            $recentEmails = Get-MessageTrace -SenderAddress $ReceiverEmail 
           -RecipientAddress $SenderEmail -StartDate $timeThreshold -EndDate (Get-Date)
        }
        
        $emailCount = ($recentEmails | Measure-Object).Count
        
        # Return true if emails were found, false otherwise
        return ($emailCount -gt 0)
    }
    catch {
        $errorMessage = "Error checking emails: $_"
        Write-Host $errorMessage -ForegroundColor Red
        Write-Log $errorMessage
        return $false
    }
}

This function:

  1. Calculates the time window to check (last X minutes)
  2. Queries Exchange Online message tracking based on the direction
  3. Returns a boolean indicating whether any matching emails were found

Alert Email Generation

When expected emails aren't found, the script sends a professional HTML alert:

function Send-AlertEmail {
    param (
        [string]$Subject,
        [string]$BodyText
    )
    
    try {
        # Create professional HTML email body with warning elements
        $htmlBody = @"
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial, sans-serif; margin: 0; padding: 0; }
        .banner { background-color: #FF0000; color: white; padding: 15px; 
        text-align: center; font-weight: bold; font-size: 18px; }
        .warning-icon { font-size: 36px; margin-right: 10px; vertical-align: middle; }
        .content { padding: 20px; }
        .footer { font-size: 12px; color: #666; padding: 10px; border-top: 1px solid #eee; }
        .highlight { background-color: #FFF0F0; padding: 15px; border-left: 5px solid 
         #FF0000; margin: 10px 0; }
    </style>
</head>
<body>
    <div class="banner">
        <span class="warning-icon">⚠️</span> ALERT: EMAIL MONITORING SYSTEM
    </div>
    <div class="content">
        <h2>Email Communication Failure Detected</h2>
        <div class="highlight">
            <p><strong>$BodyText</strong></p>
            <p>Please investigate this issue immediately as it may indicate 
            a communication breakdown.</p>
        </div>
        <p>Details:</p>
        <ul>
            <li><strong>Time of Alert:</strong> $(Get-Date 
            -Format 'yyyy-MM-dd HH:mm:ss')</li>
            <li><strong>Direction:</strong> $Direction</li>
            <li><strong>Monitoring Period:</strong> Last $CheckIntervalMinutes minutes</li>
        </ul>
        <p>This is an automated alert from the Email Monitoring System.</p>
    </div>
    <div class="footer">
        <p>IT Operations | Do not reply to this email | Internal use only</p>
    </div>
</body>
</html>
"@
        
        # Send email using SMTP server (no authentication)
        $emailParams = @{
            From = $MailboxEmail
            To = $AlertEmail
            Subject = $Subject
            Body = $htmlBody
            BodyAsHtml = $true
            SmtpServer = $SMTPServer
            Port = 25
        }
        
        Send-MailMessage @emailParams
    }
    catch {
        Write-Host "Failed to send alert email: $_" -ForegroundColor Red
        Write-Log "Failed to send alert email: $_"
    }
}

The alert email includes:

  • A bold red header with warning icon
  • Clear description of the missing communication
  • Important context details (time, direction, monitoring period)
  • Professional formatting that draws attention to the issue

Monitoring Loop

Finally, the script runs in a continuous loop, checking for emails at the specified interval:

# Main monitoring loop
while ($true) {
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    Write-Host "`n===== Email Monitoring Check: $timestamp =====" -ForegroundColor Magenta
    
    $emailsReceived = Check-Emails
    
    if (-not $emailsReceived) {
        if ($Direction -eq "Inbound") {
            $alertSubject = "⚠️ ALERT: Missing Inbound Email from $SenderEmail"
            $alertBody = "No inbound emails from $SenderEmail to 
            $ReceiverEmail have been received in the last $CheckIntervalMinutes minutes."
        } else {
            $alertSubject = "⚠️ ALERT: Missing Outbound Email to $SenderEmail"
            $alertBody = "No outbound emails from $ReceiverEmail to 
            $SenderEmail have been sent in the last $CheckIntervalMinutes minutes."
        }
        
        Send-AlertEmail $alertSubject $alertBody
    } else {
        Write-Host "Communication status: OK - No action needed" -ForegroundColor Green
    }
    
    # Wait before checking again
    $nextCheckTime = (Get-Date).AddMinutes($CheckIntervalMinutes)
    .ToString("yyyy-MM-dd HH:mm:ss")
    Write-Host "Next check scheduled for: $nextCheckTime" -ForegroundColor Cyan
    
    Start-Sleep -Seconds ($CheckIntervalMinutes * 60)
}

This loop:

  1. Checks for emails using our defined function
  2. Sends alerts when expected emails are missing
  3. Waits for the specified interval before checking again

Running the Script

To use this script in your environment:

  1. Save the complete script to a file (e.g., Monitor-Mailbox.ps1)
  2. Edit the predefined email addresses to match your monitoring needs
  3. Run the script with your SMTP server:
.\Monitor-Mailbox.ps1 -SMTPServer "your-smtp-server.com"

You can customize other parameters as needed:

.\Monitor-Mailbox.ps1 -SMTPServer "your-smtp-server.com" -Direction "Outbound"
 -CheckIntervalMinutes 10 -AlertEmail "emergency@company.com"

What the Alert Email Looks Like

When an expected email isn't found, the script sends a professionally formatted alert that looks like this:

The clear red banner and highlighted warning text immediately draw attention to the issue, its also designed very differently to other "failure" emails.

Previous Post Next Post

نموذج الاتصال