- PowerShell permite enviar correos con Send-MailMessage o SmtpClient, ideal para scripts y tareas programadas.
- El cmdlet Send-MailMessage está obsoleto y muchos proveedores bloquean la autenticación básica SMTP.
- Outlook.com y Office 365 exigen autenticación moderna, por lo que hay que recurrir a Graph o a otros servidores SMTP.
- Para automatizar avisos por email conviene usar un SMTP controlado o servicios preparados para automatizaciones.
Automatizar correos desde la terminal es una de las formas más sencillas de montar avisos, alertas o pequeños sistemas de reporting sin invertir en herramientas complejas. Tanto en Linux con Bash como en Windows con PowerShell puedes enviar emails diarios con estados de sistemas, logs de tareas programadas o cualquier información que puedas generar con un script.
La clave está en entender bien cómo hablar con un servidor SMTP (el que realmente envía el correo) y qué limitaciones imponen hoy proveedores como Outlook.com, Office 365 o Gmail, sobre todo desde que han dejado de permitir autenticación básica con usuario y contraseña “a pelo”. A continuación se recopila y reorganiza todo lo que aportan las mejores guías que ya hay en Internet, pero explicado con otras palabras y con un enfoque más práctico y actualizado.
Enviar correos desde PowerShell: opciones clásicas y modernas
PowerShell lleva muchos años permitiendo el envío de correos de forma nativa, bien usando el cmdlet Send-MailMessage o directamente la clase System.Net.Mail.SmtpClient. Ambos enfoques siguen funcionando en muchos escenarios on‑premise, aunque Microsoft ha marcado ya a Send-MailMessage como obsoleto y desaconseja su uso con servidores externos modernos, especialmente en Internet.
Antes de entrar en los detalles, conviene tener claro que siempre vas a necesitar un servidor SMTP: puede ser el de tu empresa, el de tu proveedor de correo o incluso un servidor local de pruebas. Sin él, ningún comando de PowerShell enviará nada, porque PowerShell solo prepara el mensaje y lo entrega a ese servidor.
En entornos controlados (laboratorios, intranets, servidores internos) aún tiene sentido tirar de métodos antiguos y sencillos; para Outlook.com, Exchange Online u otros servicios grandes, en cambio, ya no basta con mandar usuario y contraseña: tendrás que irte a OAuth2, tokens de app o soluciones específicas como Microsoft Graph.
Cómo funciona Send-MailMessage por dentro
El cmdlet Send-MailMessage se diseñó para facilitar al máximo el envío de correos desde scripts. Su sintaxis admite un montón de parámetros para controlar desde los destinatarios hasta el formato del cuerpo o la prioridad del mensaje.
La forma más habitual de verlo es con parámetros sueltos, pero internamente acepta conjuntos de parámetros mucho más amplios, incluyendo credenciales de autenticación, puertos personalizados y uso de SSL/TLS. La sintaxis general es larga, pero a grandes rasgos se resume en:
Send-MailMessage -From <remitente> -To <destinatarios> -Subject <asunto> -Body <cuerpo> -SmtpServer <servidor SMTP> ...
Los parámetros mínimos que casi siempre vas a usar son:
- From: dirección de correo del remitente. Puede incluir nombre descriptivo, por ejemplo
"Admin <admin@empresa.com>". - To: uno o varios destinatarios, en formato de dirección o con nombre y dirección.
- Subject: texto del asunto del correo.
- Body: contenido del mensaje, ya sea texto plano o HTML.
- SmtpServer: nombre o IP del servidor SMTP al que se conectará PowerShell.
- Port: puerto SMTP (típicamente 25 sin cifrado en LAN, o 587 con TLS STARTTLS).
Cuando el servidor exige autenticación, cosa que hoy es prácticamente siempre, tienes que añadir el parámetro -Credential con un objeto PSCredential. Además, si el servidor requiere cifrado, hay que activar -UseSsl para que el cmdlet negocie una conexión segura TLS.
Ejemplos prácticos con Send-MailMessage
Un ejemplo muy típico es el envío de un correo sencillo entre dos usuarios de la misma organización, usando el servidor SMTP definido en $PSEmailServer (variable global de PowerShell para el SMTP por defecto):
$parametros = @{
From = 'User01 <user01@fabrikam.com>'
To = 'User02 <user02@fabrikam.com>'
Subject = 'Correo de prueba'
}
Send-MailMessage @parametros
En este caso, no se pasa -Body, así que el texto del asunto se usa como contenido del correo. Es una forma rápida de mandar alertas cortas sin liarte con varias líneas de texto.
Si lo que quieres es enviar un fichero adjunto, por ejemplo un CSV generado por otro script, puedes hacerlo casi igual de fácil añadiendo el parámetro -Attachments y otros detalles como el nivel de prioridad o la petición de notificaciones de entrega:
$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
La prioridad alta y las notificaciones de éxito o fallo pueden ser muy útiles en scripts críticos. El correo se reenviará a la cuenta del remitente si algo va mal al entregar el mensaje.
También puedes jugar con diferencias entre CC y CCO (Bcc) para listas de distribución, o usar -BodyAsHtml si quieres mandar un informe con formato HTML (tablas, colores, etc.). En un entorno corporativo es bastante común usarlo para avisos de backups, estado de servidores o resúmenes diarios de logs.
Parámetros avanzados: copias, codificación, respuestas, etc.
El cmdlet es mucho más completo de lo que parece a primera vista. Algunos parámetros interesantes que conviene conocer son:
- -Cc y -Bcc: permiten añadir destinatarios en copia y copia oculta con el mismo formato que
-To. Es útil, por ejemplo, para mandar un aviso a un grupo de soporte y dejar en CCO a un responsable. - -BodyAsHtml: indica que el contenido de
-Bodyestá en HTML. Ideal para informes bonitos generados a partir de scripts (por ejemplo, resultados de inventario de equipos en tabla). - -Attachments: acepta una o varias rutas a ficheros existentes. Puedes canalizar rutas de salida de otros comandos hacia este parámetro para automatizar reportes.
- -DeliveryNotificationOption: permite controlar si quieres notificaciones de entrega
OnSuccess,OnFailure,Delay,Nevero ninguna (None). - -Encoding: define la codificación con la que se envía el contenido del mensaje. Por defecto se usa UTF‑8 sin BOM en versiones recientes, pero puedes especificar
ASCII,Unicode, códigos de página específicos, etc. - -ReplyTo: permite fijar direcciones diferentes a
Frompara que las respuestas del destinatario vayan a otro sitio. - -Port: cambia el puerto SMTP (típicamente 25, 587 o 465 según servidor y tipo de conexión).
- -UseSsl: fuerza a establecer la sesión SMTP usando SSL/TLS, imprescindible con la mayoría de proveedores externos.
Todos estos parámetros se combinan libremente en un mismo envío, de forma que puedes afinar mucho el comportamiento sin salir del propio cmdlet ni escribir demasiadas líneas de código.
Obsolescencia de Send-MailMessage y alternativas recomendadas
Microsoft ha marcado Send-MailMessage como cmdlet obsoleto (nota de compatibilidad DE0005). El motivo principal es que no garantiza por sí mismo conexiones seguras ni soporta bien los requisitos modernos de autenticación que exigen muchos servidores actuales, especialmente en la nube.
En su documentación oficial, Microsoft sugiere que para escenarios donde necesites seguridad y compatibilidad total con TLS y autenticación moderna recurras a librerías externas como MailKit (muy potente para SMTP, IMAP y POP3) o, en el caso concreto de Exchange Online y Outlook en la nube, al cmdlet Send-MgUserMail del SDK de Microsoft Graph para PowerShell.
¿Significa esto que Send-MailMessage deja de funcionar ya? No necesariamente. Seguirá funcionando en muchos servidores SMTP clásicos, sobre todo dentro de redes internas o en servidores configurados para permitir autenticación simple. Pero cada vez será menos viable contra servicios grandes como Outlook.com, Office 365 o Gmail, donde se ha deshabilitado la autenticación básica.
Problemas típicos al enviar correos con PowerShell y Outlook.com / Office 365
Uno de los casos reales más frecuentes hoy en día es el de quien usaba un guion sencillo con System.Net.Mail.SmtpClient contra smtp.office365.com y, de repente, el script deja de funcionar con mensajes de error relacionados con la autenticación segura, como los descritos en problemas con Outlook en Windows 10.
Un ejemplo muy representativo es el de un usuario con una cuenta gratuita de Outlook.com que utilizaba algo como esto en 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)
Durante años este patrón ha funcionado sin problemas, pero recientemente muchos usuarios han empezado a recibir un fallo del estilo:
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."
Este mensaje indica que, aunque se esté usando TLS (EnableSsl = $true), la autenticación que se está haciendo es del tipo “usuario/contraseña básicos”, y esa modalidad ha sido deshabilitada por Microsoft en Outlook.com / Exchange Online para reforzar la seguridad de las cuentas.
El correo de aviso de Microsoft y lo que realmente significa
Cuando esto ocurre, normalmente el usuario recibe un email de advertencia del tipo:
“Para ayudar a mantener su cuenta segura, Microsoft ya no admitirá el uso de aplicaciones de correo electrónico y calendario de terceros que le pidan que inicie sesión solo con su nombre de usuario y contraseña…”
Traducido al terreno práctico, quiere decir que no vale con mandar usuario y contraseña en texto claro (aunque vaya dentro de TLS). Microsoft quiere que todo acceso a su plataforma de correo pase por “métodos de autenticación modernos”, que en la práctica se basan en OAuth2, tokens y permisos delegados o de aplicación.
El problema para un simple script de PowerShell que solo pretende mandar dos correos al día es que implementar OAuth2 a mano no es precisamente trivial. Y, en el caso concreto de cuentas personales de Outlook.com sin suscripción ni tenant de Azure AD asociado, ni siquiera dispones de todas las opciones que tiene un cliente corporativo.
¿Se puede seguir usando Outlook.com para scripts sencillos?
Con una cuenta 100 % personal de Outlook.com, sin suscripción empresarial, estás muy limitado para seguir usando SMTP con autenticación básica desde scripts caseros. Microsoft no deja una opción clara para “desactivar la seguridad” solo para esa cuenta, y el mensaje que ves de error va en esa línea: autenticación básica desactivada, uses lo que uses delante.
Algunas posibilidades, cada una con sus pros y sus contras, serían:
- Pasarte a un servidor SMTP que todavía permita autenticación básica, como uno propio (Postfix, Exim, etc.) o un proveedor alternativo que soporte “contraseña de aplicación” o similar.
- Montar un pequeño relé SMTP interno que acepte autenticación débil desde tu script y, a su vez, se conecte a un proveedor por métodos modernos (esto ya se complica bastante para un uso doméstico).
- Utilizar otra cuenta o proveedor específicamente orientado a automatizaciones (por ejemplo, servicios pensados para envíos transaccionales que aún permiten credenciales simples bajo TLS).
Lo que no es viable es “dar marcha atrás” a la decisión de Microsoft desde la interfaz de Outlook.com: no hay un check mágico para reactivar la autenticación antigua solo para tu caso, aunque la cuenta se use únicamente para notificaciones y no te importe su nivel de seguridad.
Alternativas modernas: Microsoft Graph, MailKit y compañía
Si tu correo está en Exchange Online dentro de un entorno de Microsoft 365 empresarial, lo más alineado con lo que recomienda Microsoft es usar Microsoft Graph. Con el SDK de Graph para PowerShell dispones del cmdlet Send-MgUserMail, que envía mensajes a través de la API con autenticación moderna, sin pelearte con SMTP directamente.
Para escenarios más generales y proveedores variados, una opción muy usada es MailKit, una biblioteca .NET que soporta SMTP con toda la artillería moderna de cifrado y autenticación. Desde PowerShell puedes cargar el ensamblado de MailKit y utilizarlo como si estuvieras programando en C#, pero con la flexibilidad de los scripts.
En ambos casos, eso sí, vas a necesitar registrar aplicaciones, obtener IDs de cliente, secretos o certificados, y trabajar con tokens OAuth2. Son soluciones sólidas y seguras, pero bastante más complejas que el clásico SmtpClient.Credentials = New-Object System.Net.NetworkCredential(...).
Ejemplos de scripts PowerShell de envío de correo con adjuntos y autenticación
Aunque el panorama con los grandes proveedores haya cambiado, los patrones clásicos siguen siendo muy útiles para LANs, servidores internos o proveedores que todavía aceptan autenticación básica bajo TLS. A partir de ahí puedes adaptar los ejemplos a tus necesidades.
Un ejemplo muy sencillo para enviar un correo con un adjunto desde PowerShell podría ser:
$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
}
Si el servidor SMTP requiere autenticación, puedes definir usuario y contraseña con un PSCredential así:
$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
El mismo patrón lo puedes estirar añadiendo copia, copia oculta, cuerpo HTML o más adjuntos, según requiera tu caso de uso. Es muy habitual, por ejemplo, incluir logs o ficheros de resultado de un backup o de una instalación automática como adjunto para tener rastro de lo que ha ocurrido.
Uso de SmtpClient directamente en PowerShell
Otra forma extendida de enviar correos desde PowerShell es instanciar directamente un System.Net.Mail.SmtpClient. Eso te da más control fino sobre el mensaje, especialmente cuando necesitas múltiples adjuntos, HTML avanzado, cabeceras personalizadas, etc.
Un ejemplo básico, utilizado durante años con Gmail u otros servidores, sería:
$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)
Y si quieres adjuntar un archivo, podrías construir un MailMessage más completo:
$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)
Este enfoque, muy cómodo hace unos años, se ha visto igualmente afectado por los cambios en la autenticación básica de proveedores grandes como Gmail u Outlook.com, por lo que a día de hoy es más apropiado para SMTP controlados por ti o por tu organización que para servicios gratuitos de consumo.
Automatizar scripts de correo con el Programador de Tareas de Windows
Una vez que tienes tu script de PowerShell funcionando a mano, el siguiente paso lógico es programarlo para que se ejecute solo a la hora que quieras, o en respuesta a un evento concreto. En Windows eso se hace fácilmente con el Programador de tareas.
La idea típica es guardar tu script en un .ps1 en una ruta accesible (por ejemplo, C:\scripts\enviar_correo.ps1) y crear un pequeño batch para lanzarlo:
@echo off
cd C:\scripts
powershell ./enviar_correo.ps1
En el Programador de tareas configuras una nueva tarea cuya acción sea “Iniciar un programa” y, en la línea de programa, indicas algo como:
powershell -file "C:\scripts\enviar_correo.ps1"
Con eso puedes asociar la ejecución del script a un horario, un inicio de sesión, un evento del sistema o prácticamente cualquier disparador que soporte el Programador de tareas, y recibirás tus correos de aviso sin tener que preocuparte de nada más.
En servidores antiguos como Windows Server 2008, recuerda que puede ser necesario habilitar primero la ejecución de scripts con Set-ExecutionPolicy Unrestricted, y que la forma de llamar a PowerShell desde la tarea puede variar un poco (por ejemplo, omitiendo el parámetro -file).
Combinando estas piezas (script + batch + tarea programada) puedes montar con cuatro líneas un sistema simple pero efectivo de notificaciones por email, sin depender de interfaces gráficas ni herramientas de terceros.
Con todo lo anterior, la idea general que te debes llevar es que seguir enviando correos desde Bash o PowerShell es perfectamente viable, pero el terreno ha cambiado respecto a hace unos años: los ejemplos clásicos con autenticación básica solo encajarán ya en servidores SMTP bajo tu control o proveedores que sigan soportando ese modelo. Para grandes plataformas como Outlook.com, Office 365 o Gmail, la jugada pasa por adoptar autenticación moderna (Graph, OAuth2, bibliotecas como MailKit) o, si solo buscas algo rápido y sin complicaciones, optar por un servidor SMTP alternativo con políticas menos estrictas y pensado precisamente para automatizaciones de este tipo.
Redactor apasionado del mundo de los bytes y la tecnología en general. Me encanta compartir mis conocimientos a través de la escritura, y eso es lo que haré en este blog, mostrarte todo lo más interesante sobre gadgets, software, hardware, tendencias tecnológicas, y más. Mi objetivo es ayudarte a navegar por el mundo digital de forma sencilla y entretenida.