- PowerShell It allows you to send emails with Send-MailMessage or SmtpClient, ideal for scripts and scheduled tasks.
- The Send-MailMessage cmdlet is deprecated and many providers block basic SMTP authentication.
- Outlook.com and Office 365 require modern authentication, so you have to use Graph or other SMTP servers.
- To automate email notifications, it is advisable to use a controlled SMTP server or services designed for automation.

Automate emails from the terminal It's one of the simplest ways to set up notifications, alerts, or small reporting systems without investing in complex tools. Both in Linux with Bash as in Windows With PowerShell you can send emails system status logs, logs of scheduled tasks or any information you can generate with a script.
The key is to understand well How to talk to an SMTP server (the one who actually sends the email) and what limitations providers like Outlook.com, Office 365, or Gmail impose today, especially since they've stopped allowing basic authentication with just a username and password. Below, we've compiled and reorganized everything from the best guides already available online, but explained in different terms and with a more practical and up-to-date approach.
Sending emails from PowerShell: classic and modern options
PowerShell has allowed sending emails natively for many years.either using the cmdlet Send-MailMessage or directly the class System.Net.Mail.SmtpClientBoth approaches continue to work in many on-premises scenarios, although Microsoft has already marked Send-MailMessage as obsolete and advises against its use with modern external servers, especially on the Internet.
Before going into the details, it's important to understand that You will always need an SMTP serverThis could be your company's server, your email provider's server, or even a local test server. Without it, no PowerShell command will send anything, because PowerShell only prepares the message and delivers it to that server.
In controlled environments (laboratories, intranets, internal servers) It still makes sense to use old and simple methods; for Outlook.com, Exchange Online or other large services, however, sending a username and password is no longer enough: you will have to go to OAuth2, app tokens or specific solutions like Microsoft Graph.
How Send-MailMessage works internally
The cmdlet Send-MailMessage It was designed to make sending emails from scripts as easy as possible. Its syntax supports a multitude of parameters to control everything from recipients to body formatting and message priority.
The most common way to view it is with individual parameters, but internally it accepts much larger sets of parameters, including authentication credentials, custom ports, and SSL/TLS usageThe general syntax is lengthy, but broadly speaking it can be summarized as follows:
Send-MailMessage -From <remitente> -To <destinatarios> -Subject <asunto> -Body <cuerpo> -SmtpServer <servidor SMTP> ...
The minimum parameters you'll almost always use are:
- from: Sender's email address. You can include a descriptive name, for example
"Admin <admin@empresa.com>". - That's it: one or more recipients, in address format or with name and address.
- Subject: email subject text.
- Bodysuit : message content, whether plain text or HTML.
- SmtpServer: name or IP of the SMTP server to which PowerShell will connect.
- Port (The Harbour District): SMTP port (typically 25 without encryption on LAN, or 587 with TLS STARTTLS).
When the server requires authentication, which is practically always the case these days, You need to add the parameter -Credential with an object PSCredentialAdditionally, if the server requires encryption, it must be enabled. -UseSsl so that the cmdlet can negotiate a secure TLS connection.
Practical examples with Send-MailMessage
A very typical example is sending a simple email between two users of the same organization, using the SMTP server defined in $PSEmailServer (PowerShell global variable for default SMTP):
$parametros = @{
From = 'User01 <user01@fabrikam.com>'
To = 'User02 <user02@fabrikam.com>'
Subject = 'Correo de prueba'
}
Send-MailMessage @parametros
In this case, It doesn't happen -BodySo the subject line text is used as the email content. It's a quick way to send short alerts without getting bogged down in multiple lines of text.
If what you want is to send a attached fileFor example, a CSV generated by another script, you can do it almost as easily by adding the parameter -Attachments and other details such as priority level or delivery notification requests:
$parametros = @{
From = 'User01 <user01@fabrikam.com>'
To = 'User02 <user02@fabrikam.com>', 'User03 <user03@fabrikam.com>'
Subject = 'Envío de adjunto'
Body = "Te envío el adjunto que faltaba."
Attachments = '.\datos.csv'
Priority = 'High'
DeliveryNotificationOption = 'OnSuccess','OnFailure'
SmtpServer = 'smtp.fabrikam.com'
}
Send-MailMessage @parametros
High priority and success or failure notifications They can be very useful in critical scripts. The email will be forwarded to the sender's account if something goes wrong delivering the message.
You can also play with Differences between CC and CCO (Bcc) for mailing lists, or use -BodyAsHtml If you want to send a report in HTML format (tables, colors, etc.). In a corporate environment, it's quite common to use it for backup notifications, server status, or daily log summaries.
Advanced parameters: copies, encoding, responses, etc.
The cmdlet is much more comprehensive than it first appears. Some interesting parameters that are worth knowing are:
- -Cc and -Bcc: allow adding recipients in carbon copy and blind carbon copy using the same format as
-ToIt's useful, for example, to send a notification to a support group and leave a responsible party in the BCC field. - -BodyAsHtml: indicates that the content of
-BodyIt's in HTML. Ideal for attractive reports generated from scripts (e.g., equipment inventory results in a table). - -Attachments: accepts one or more paths to existing files. You can pipe outgoing paths from other files. commands towards this parameter to automate reports.
- -DeliveryNotificationOption: allows you to control whether you want delivery notifications
OnSuccess,OnFailure,Delay,Neveror none (None). - -Encoding: defines the encoding used to send the message content. UTF-8 without BOM is used by default in recent versions, but you can specify
ASCII,Unicode, specific page codes, etc. - -ReplyTo: allows setting different addresses to
Fromso that the recipient's responses go to another location. - -Harbor: Change the SMTP port (typically 25, 587 or 465 depending on the server and connection type).
- -UseSsl: forces the SMTP session to be established using SSL/TLS, which is essential with most external providers.
All these parameters are freely combined. in a single submission, so you can fine-tune the behavior without leaving the cmdlet itself or writing too many lines of code.
Obsolescence of Send-MailMessage and recommended alternatives
Microsoft has marked Send-MailMessage as an obsolete cmdlet (Compatibility note DE0005). The main reason is that it does not guarantee secure connections on its own, nor does it properly support the modern authentication requirements demanded by many current servers, especially in the cloud.
In its official documentation, Microsoft suggests that for scenarios where you need full security and compatibility with TLS and modern authentication, you should use external libraries such as MailKit (very powerful for SMTP, IMAP and POP3) or, in the specific case of Exchange Online and Outlook in the cloud, to the cmdlet Send-MgUserMail of the Microsoft Graph SDK for PowerShell.
Does this mean that Send-MailMessage Will it stop working now? Not necessarily. It will continue to work on many classic SMTP servers, especially within internal networks or on servers configured to allow simple authentication. But it will become increasingly less viable against large services like Outlook.com, Office 365, or Gmail, where basic authentication has been disabled.
Typical problems when sending emails with PowerShell and Outlook.com / Office 365
One of the most frequent real-life cases today is that of someone who used a simple script with System.Net.Mail.SmtpClient against smtp.office365.com and suddenly, the script stops working with error messages related to secure authentication, such as those described in Outlook problems on Windows 10.
A very representative example It is that of a user with a free Outlook.com account which used something like this in PowerShell:
$EmailFrom = 'usuario@outlook.com'
$EmailTo = 'destinatario@dominio.com'
$SMTPServer = 'smtp.office365.com'
$SMTPClient = New-Object Net.Mail.SmtpClient($SMTPServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential('usuario@outlook.com','contraseña');
$Subject = $args
$Body = $args
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
For years this pattern has worked without problems, but recently Many users have started experiencing an error similar to:
Exception calling "Send" with "4" argument(s): "The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.57 Client not authenticated to send mail. Error: 535 5.7.139 Authentication unsuccessful, basic authentication is disabled."
This message indicates that, even though TLS is being used (EnableSsl = $true), The authentication being performed is of the "basic username/password" type.And that feature has been disabled by Microsoft in Outlook.com / Exchange Online to strengthen account security.
Microsoft's notification email and what it really means
When this happens, the user usually receives a warning email of the type:
“To help keep your account secure, Microsoft will no longer support the use of third-party email and calendar applications that require you to sign in using only your username and password…”
Translated into practical terms, this means that Sending the username and password in plain text (even if it's within TLS) is not enough.Microsoft wants all access to its email platform to go through "modern authentication methods," which in practice are based on OAuth2, tokens, and delegated or application permissions.
The problem for a simple PowerShell script that only intends to send two emails per day is that Implementing OAuth2 manually is not exactly trivial.And, in the specific case of personal Outlook.com accounts without an associated Azure AD subscription or tenant, you don't even have all the options available to a corporate customer.
Can Outlook.com still be used for simple scripts?
With a 100% personal Outlook.com account, without a business subscription, You are very limited. To continue using SMTP with basic authentication from custom scripts, Microsoft doesn't provide a clear option to "disable security" specifically for that account, and the error message you're seeing reflects this: basic authentication is disabled, regardless of what you use in front of it.
Some PossibilitiesEach with its pros and cons, would be:
- Switch to an SMTP server that still allows basic authentication, such as your own (Postfix, Exim, etc.) or an alternative provider that supports "application password" or similar.
- Install a small internal SMTP relay that accepts weak authentication from your script and, in turn, connects to a provider using modern methods (this already gets quite complicated for home use).
- Use a different account or provider specifically designed for automations (for example, services designed for transactional submissions that still allow simple credentials under TLS).
What is not feasible is to "reverse" Microsoft's decision from the Outlook.com interface: There is no magic check to reactivate the old authentication just for your case, even if the account is used only for notifications and you don't care about its security level.
Modern alternatives: Microsoft Graph, MailKit, and others
If your email is in Exchange Online within an environment of Microsoft 365 For businesses, the most aligned approach with Microsoft's recommendations is to use Microsoft GraphThe Graph SDK for PowerShell provides the cmdlet Send-MgUserMail, which sends messages through the API with modern authentication, without dealing with SMTP directly.
For more general scenarios and varied providers, a commonly used option is MailKitMailKit is a .NET library that supports SMTP with all the modern encryption and authentication capabilities. From PowerShell, you can load the MailKit assembly and use it as if you were programming in C#, but with the flexibility of scripting.
In both cases, however, You'll need to register applications, obtain client IDs, secrets or certificates, and work with OAuth2 tokensThey are solid and secure solutions, but considerably more complex than the classic SmtpClient.Credentials = New-Object System.Net.NetworkCredential(...).
Examples of PowerShell scripts for sending emails with attachments and authentication
Although the landscape with major suppliers has changed, Classic patterns remain very useful For LANs, internal servers, or providers that still accept basic authentication under TLS. From there, you can adapt the examples to your needs.
Un very simple example To send an email with an attachment from PowerShell, you could do the following:
$file = 'C:\log_install.log'
$time = Get-Date -DisplayHint Time
$from = 'linuxsysymas@dominio.com'
$to = 'destino@dominio.com'
$subject = 'Envío de log desde PowerShell'
$smtpserver = 'servermail.midominio.com'
foreach ($recipient in $to) {
Write-Host "Enviando mail a $recipient"
Send-MailMessage -SmtpServer $smtpserver -From $from -To $recipient -Subject $subject -Body "Saludos $time" -Attachments $file
}
If the SMTP server requires authentication, you can define a username and password with a PSCredential So:
$user = 'linuxsysymas@dominio.com'
$passwd = ConvertTo-SecureString 'micontraseña' -AsPlainText -Force
$credenciales = New-Object System.Management.Automation.PSCredential ($user, $passwd)
Send-MailMessage -SmtpServer $smtpserver -From $from -To $to -Subject $subject -Body "Saludos $time" -Attachments $file -Credential $credenciales
You can stretch the same pattern by adding copy, blind carbon copy, HTML body, or more attachmentsas required by your use case. It is very common, for example, to include logs or output files from a backup or an automatic installation as an attachment to keep track of what has happened.
Using SmtpClient directly in PowerShell
Another common way to send emails from PowerShell is to directly instantiate a System.Net.Mail.SmtpClientThis gives you more fine control over the message, especially when you need multiple attachments, advanced HTML, custom headers, etc.
Un basic example, used for years with Gmail or other servers, would be:
$EmailPropio = 'usuario@gmail.com'
$EmailDestino = 'destino@dominio.com'
$Asunto = 'Asunto del email'
$Mensaje = 'Texto del mensaje'
$ServidorSMTP = 'smtp.gmail.com'
$ClienteSMTP = New-Object Net.Mail.SmtpClient($ServidorSMTP, 587)
$ClienteSMTP.EnableSsl = $true
$ClienteSMTP.Credentials = New-Object System.Net.NetworkCredential('usuario','contraseña');
$ClienteSMTP.Send($EmailPropio, $EmailDestino, $Asunto, $Mensaje)
And if you want to attach a file, you could build a MailMessage more complete:
$EmailPropio = 'usuario@gmail.com'
$EmailDestino = 'destino@dominio.com'
$Asunto = 'Email con adjunto'
$Texto = 'Cuerpo del mensaje'
$ServidorSMTP = 'smtp.gmail.com'
$Archivo = 'C:\carpeta\archivo.txt'
$Mensaje = New-Object System.Net.Mail.MailMessage
$Mensaje.From = $EmailPropio
$Mensaje.To.Add($EmailDestino)
$Mensaje.IsBodyHtml = $true
$Mensaje.Subject = $Asunto
$Mensaje.Body = $Texto
$Adjunto = New-Object Net.Mail.Attachment($Archivo)
$Mensaje.Attachments.Add($Adjunto)
$ClienteSMTP = New-Object Net.Mail.SmtpClient($ServidorSMTP,587)
$ClienteSMTP.EnableSsl = $true
$ClienteSMTP.Credentials = New-Object System.Net.NetworkCredential('usuario','contraseña');
$ClienteSMTP.Send($Mensaje)
This approach, very convenient a few years ago, has also been affected by changes in basic authentication from major providers like Gmail or Outlook.com, so Today it is more appropriate for SMTP servers controlled by you or by your organization for free consumer services.
Automate email scripts with the Windows Task Scheduler
Once you have your PowerShell script working manually, the next logical step is program it to run automatically at any time you want, or in response to a specific event. In Windows, this is easily done with the Task Scheduler.
The typical idea is to save your script in a .ps1 on an accessible route (for example, C:\scripts\enviar_correo.ps1and create a small batch to launch it:
@echo off
cd C:\scripts
powershell ./enviar_correo.ps1
In the Task Scheduler you configure a new task whose action is “Start a program"And, in the program line, you indicate something like:"
powershell -file "C:\scripts\enviar_correo.ps1"
With that you can associate the script execution to a schedule, a login, a system event or virtually any trigger that Task Scheduler supports, and you'll receive your notification emails without having to worry about anything else.
On older servers like Windows Server 2008, remember that you may need to enable script execution first. Set-ExecutionPolicy Unrestrictedand that the way to call PowerShell from the task may vary slightly (for example, by omitting the parameter -file).
Combining these pieces (script + batch + scheduled task) With just four lines of code, you can set up a simple but effective email notification system, without relying on graphical interfaces or third-party tools.
With all of the above, the general idea you should take away is that Continuing to send emails from Bash or PowerShell is perfectly viableHowever, the landscape has changed compared to a few years ago: classic examples with basic authentication will only work on SMTP servers under your control or providers that still support that model. For large platforms like Outlook.com, Office 365, or Gmail, the solution lies in adopting modern authentication (Graph, OAuth2, libraries like MailKit) or, if you're just looking for something quick and straightforward, opting for an alternative SMTP server with less stringent policies, specifically designed for this type of automation.
Passionate writer about the world of bytes and technology in general. I love sharing my knowledge through writing, and that's what I'll do on this blog, show you all the most interesting things about gadgets, software, hardware, tech trends, and more. My goal is to help you navigate the digital world in a simple and entertaining way.