Sep 6, 2026

Automating IT Alerts: Sending SMS and Email Notifications from Monitoring Scripts

4 min readIntermediate

An alert that only shows up in a dashboard nobody’s watching at 3 AM isn’t an alert, it’s a log entry. This is a reliable pattern for turning a monitoring check (SCOM, or really any script-based check) into an SMS and email notification that reaches someone immediately, plus the details that trip people up the first time they build this.

The basic pattern

Every alerting script follows the same shape: run a check, evaluate a condition, and if it fails, fire a notification through two independent channels. Never just one, since email delivery has its own failure modes, and so does SMS.

Email notification from PowerShell

function Send-AlertEmail {
    param(
        [string]$Subject,
        [string]$Body,
        [string]$To = "[email protected]"
    )
    $params = @{
        From       = "[email protected]"
        To         = $To
        Subject    = "[ALERT] $Subject"
        Body       = $Body
        SmtpServer = "smtp.yourcompany.com"
        Port       = 587
        UseSsl     = $true
        Credential = (Import-Clixml "C:\Scripts\smtp-cred.xml")
    }
    Send-MailMessage @params
}

Two things worth calling out: use Import-Clixml for the credential rather than a plaintext password in the script (generate it once with Get-Credential | Export-Clixml, run as the same service account that will execute the scheduled task, since Clixml credentials are tied to the user and machine that created them), and set a real “From” address your mail system won’t flag as suspicious, since alerting scripts sending from a generic or unauthenticated address are a common reason alerts silently land in spam.

SMS notification via a carrier email-to-SMS gateway (no third-party service needed)

The simplest way to get a text message without signing up for an SMS API: most carriers accept email sent to a specific address that gets converted to SMS.

function Send-AlertSMS {
    param([string]$Message)
    # Example gateway addresses - confirm current ones with the carrier,
    # these do change:
    # AT&T:      [email protected]
    # T-Mobile:  [email protected]
    # Verizon:   [email protected]
    Send-MailMessage -From "[email protected]" -To "[email protected]" `
        -Subject "" -Body $Message -SmtpServer "smtp.yourcompany.com" -Port 587 -UseSsl
}

This is genuinely reliable for a small on-call rotation and costs nothing extra. For anything at real scale (dozens of recipients, delivery confirmation, two-way acknowledgment), a proper SMS API (Twilio being the most common) is worth the small per-message cost, since the email-to-SMS gateway approach has no delivery guarantee and carriers occasionally change or retire these addresses without much notice.

Wiring it into a SCOM (or any) monitoring check

$diskFreePercent = (Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'" |
    Select-Object -ExpandProperty FreeSpace) / (Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'" |
    Select-Object -ExpandProperty Size) * 100

if ($diskFreePercent -lt 10) {
    $msg = "$env:COMPUTERNAME: C: drive at $([math]::Round($diskFreePercent,1))% free"
    Send-AlertEmail -Subject "Low disk space" -Body $msg
    Send-AlertSMS -Message $msg
}

The same shape works for literally any check: a failed backup job, a service that’s down, a certificate expiring within N days, an error string appearing in a log file. Swap out the condition, keep the notification calls the same.

The mistake almost everyone makes early on: no throttling

The very first version of an alerting script almost always spams the same alert every time the scheduled task runs (every 5 minutes, forever, until someone fixes the underlying issue), turning something urgent into something everyone starts ignoring. Add a simple state file so you only alert once per incident, then again if it clears and re-triggers:

$stateFile = "C:\Scripts\state\diskspace-alerted.flag"
if ($diskFreePercent -lt 10) {
    if (-not (Test-Path $stateFile)) {
        Send-AlertEmail -Subject "Low disk space" -Body $msg
        Send-AlertSMS -Message $msg
        New-Item $stateFile -ItemType File -Force | Out-Null
    }
} else {
    Remove-Item $stateFile -ErrorAction SilentlyContinue
}

Frequently asked questions

Should I use this pattern instead of SCOM’s built-in notification subscriptions?
If you’re already fully on SCOM, its native notification channels are usually the better default. This pattern is most useful for the gaps: custom scripts, scheduled tasks, or checks running outside SCOM’s monitored scope entirely, where you still want the same reliable two-channel alerting.

Is email-to-SMS reliable enough for a critical production alert?
For a small team it’s genuinely fine and many organizations run on exactly this for years, just don’t treat it as guaranteed delivery for a single point of failure. If a single missed alert would be a serious incident on its own, pair it with a proper on-call/paging platform (PagerDuty, Opsgenie) rather than relying on the gateway alone.