Sending Email with PowerShell
A script that finishes a job should be able to tell someone. Send-MailMessage sends mail through any SMTP server in one command — and for production scripts, Microsoft Graph is the durable path now that basic SMTP auth is fading.
Documentation: Send-MailMessage documentation
What Send-MailMessage does
Send-MailMessage hands a message to an SMTP server: sender, recipients, subject, body, optional attachments, and the server details. It is the fastest way to make a script report its own results — a nightly job that emails its log, a monitor that alerts when a service stops.
Two things to know up front. First, the cmdlet is obsolete in PowerShell 7: it still ships and still works, but Microsoft will not improve it, and it prints an obsolescence warning. Second, the cmdlet is silent on success — no output means the mail was accepted by the server, not that it arrived in the inbox.
For scripts that must keep working for years, the durable path is Microsoft Graph: Send-MgUserMail sends through a real mailbox with modern authentication. It needs app registration and the Graph module, so it is more setup — but it is the path that survives the death of basic SMTP authentication.
See the objects move
Inspect this authored example with fictional data in the bounded browser model. The numbered stages show how its objects change.
Send-MailMessage -From 'you@contoso.com' -To 'you@contoso.com' `- Stage 1Send-MailMessage -From 'you@contoso.com' -To
Try it: send a test message
Send a message
The classic one-liner. Port 587 with -UseSsl is the modern submission port; port 25 is often blocked by networks:
Get-Credential prompts for the password instead of writing it in the script — never hard-code a password in a .ps1 file. Add -Attachments 'C:\Reports\backup.csv' to attach files, and -BodyAsHtml when the body is HTML rather than plain text.
For Microsoft 365 mailboxes, SMTP AUTH must be enabled on the mailbox or the server rejects the login, and personal Gmail accounts need an app password — plain passwords no longer work there. When either is true, the error message says authentication failed even though the password is correct.
Try it: send a test message
Send yourself a test message. Replace the addresses and server with your own, and expect no output — silence is success here:
Check the inbox, including junk mail — a first message from a new sender often lands there. If the command errors, read the error: authentication failures point at credentials or SMTP AUTH settings, connection failures point at the server name, port, or a blocked port 25.
Common mistakes
- Passwords in the script. A password written in a .ps1 file is visible to anyone who can read the file. Use Get-Credential, a stored secure string, or a managed identity with Graph.
- Missing -UseSsl on port 587. Modern servers require TLS on the submission port. Without it, the connection is refused or the login is rejected.
- Assuming delivery from silence. Send-MailMessage only proves the SMTP server accepted the message. Check the inbox — spam filters and rules decide the rest.
- Using Gmail with a normal password. Google no longer accepts plain passwords for SMTP. Use an app password, or switch to Graph.
- Treating the obsolete warning as an error. In PowerShell 7 the warning is expected and the mail still sends. For new production scripts, prefer Graph anyway.
Your turn
On your own machine, send yourself an email with a subject, a short body, and one attachment — a small text file you create for the test. Then send the same report as HTML with -BodyAsHtml and a bold heading, and compare how the two arrive.
Prove it: write it alone
Blank editor. No starter, no hints. Write the command that emails a daily disk-space summary to yourself through your SMTP server, with credentials prompted — not written — and an attachment of the report file.
Practise this
Send a report email
Send an email with a subject, a body and one attachment through an SMTP server.
The sandbox is visible now. Sign in with Google only when you run or check a task; commands and temporary files are discarded when you leave.
Run a command to inspect its result.
Inspect starting data
Supported syntax
Virtual files
Recap
Send-MailMessage sends mail through SMTP in one command: sender, recipient, subject, body, server, port, -UseSsl and a credential. Keep passwords out of scripts with Get-Credential, remember silence means accepted — not delivered — and choose Microsoft Graph for production scripts that must survive the end of basic SMTP auth.