Cómo enviar correos electrónicos usando Microsoft Graph PowerShell
Los métodos de autenticación de correo electrónico heredados se están convirtiendo en una cosa del pasado, con la autenticación heredada para Exchange Online ahora muerta y los servicios de terceros cada vez son más difíciles de proteger, especialmente cuando es necesario agregarlos como fuentes confiables de correo para su dominio, un método alternativo de autenticación mediante programación. El envío de correos electrónicos es fundamental.
El cmdlet Send-MgUserMail en Microsoft Graph PowerShell proporciona una forma cómoda y sencilla de enviar correos electrónicos mediante programación mediante PowerShell en sesiones de PowerShell interactivas y no interactivas.
En este tutorial, le mostraré cómo usar Microsoft Graph PowerShell y Graph API para enviar correos electrónicos mediante programación utilizando su servicio Exchange Online existente.
Eliminando la necesidad de servicios de terceros
Dado que la autenticación heredada para Exchange Online ahora es inutilizable, otros métodos de retransmisión de correo electrónico de forma segura han sido una necesidad constante para muchas organizaciones. Si bien las aplicaciones exigentes (como Microsoft Dynamics) o los dispositivos detrás de la curva (como las impresoras multifunción) pueden usar fácilmente métodos como Office 365 Direct Send (siempre que estén detrás de una IP pública estática) o utilizar la infraestructura híbrida existente (si lo suficientemente desafortunado como para tenerlo todavía...), las soluciones programáticas han sido un desafío, especialmente al utilizar servicios como Azure Automation y tratar de evitar el uso de infraestructura de terceros.
Servicios de terceros como SMTP2Go o SendGrid pueden parecer opciones atractivas para resolver este problema, pero ahí radica la pregunta:
- ¿Deberías rotar las contraseñas?
- ¿Qué tan seguros son realmente?
- ¿Cumplen?
- ¿Cómo rastreo y superviso las vulnerabilidades?
- La lista continua…
La respuesta simple a este problema es no usarlos en absoluto y, en su lugar, usar lo que está disponible para usted, ¡la API Graph con PowerShell!
Acerca de Enviar-MgUserMail
El cmdlet Send-MgUserMail se puede encontrar en el módulo Microsoft.Graph.Users.Actions del SDK de Microsoft Graph PowerShell y el comando se puede utilizar con permisos tanto delegados como de aplicación. en diferentes contextos.
Para utilizar el cmdlet, debe dar su consentimiento al alcance del permiso mail.send, pero dependiendo de si da su consentimiento a este permiso mediante permisos delegados o de aplicación, se concede un nivel de acceso diferente.
Si acepta el permiso mail.send en un escenario delegado, puede notar que solo puede enviar correo como el usuario autenticado en su sesión actual (el contexto de usuario actual).
Sin embargo, al otorgar el permiso de aplicación equivalente, notará que puede enviar correo como cualquier usuario de su organización.
Como puede ver, mail.send es un permiso peligrosamente poderoso y debe usarse con cuidado. Si planea usar este permiso con Azure Automation, considere usar Identidades administradas para eliminar la necesidad de administrar secretos o certificados de cliente y mantener su entorno seguro.
Enviar correos electrónicos con Microsoft Graph PowerShell
Enviar un correo electrónico con permisos delegados
Para enviar correos electrónicos con permisos delegados en su propio contexto de usuario, debe conectarse a Microsoft Graph con el cmdlet Connect-MgGraph y el alcance del permiso Mail.Send:
Connect-MgGraph -scope Mail.SendLuego, el mensaje de correo real debe definirse como una tabla hash. A continuación se muestra un ejemplo sencillo para enviar un correo electrónico básico basado en texto desde una dirección específica. Asegúrese de cambiar el texto "SU CORREO ELECTRÓNICO AQUÍ" con el correo electrónico de la cuenta que utilizó para autenticarse en Microsoft Graph.
$body = @{
message = @{
subject = "My Microsoft Graph Test Email"
body = @{
contentType = "Text"
content = "Hello, this is a test email"
}
toRecipients = @(
@{
emailAddress = @{
address = "YOUR EMAIL HERE"
}
}
)
}
saveToSentItems = "false"
}
Por último, para enviar el correo electrónico, utilice el cmdlet Send-MgUserMail de la siguiente manera:
Send-MgUserMail -UserId %YourUPN% -BodyParameter $bodyEnviar un correo electrónico con permisos de la aplicación.
Como ya sabemos, los permisos de las aplicaciones exponen más poder al definir el permiso Mail.Send. Esto significa que podemos ser más flexibles con nuestro script.
Comience conectándose a Microsoft Graph. Si aún no está familiarizado con cómo hacer esto, siga mi guía aquí: Cómo conectarse a Microsoft Graph PowerShell con un secreto de cliente.
Se puede adoptar un enfoque ligeramente diferente al utilizar permisos de aplicaciones, como en mi ejemplo a continuación. Aquí puede ver que agregué los parámetros -to y -from a mi script, lo que permite al usuario definir a quién y de quién se enviará el correo electrónico. El valor de estos parámetros también se puede obtener de otras fuentes si la dirección de destino/de destino depende del resultado de una acción automática, como si está utilizando Azure Automation.
Param(
[Parameter(Mandatory)]
[ValidateNotNull()]
[mailaddress]
${to},
[Parameter(Mandatory)]
[ValidateNotNull()]
[mailaddress]
${from}
)
$ApplicationId = "APPID"
$SecuredPassword = "SECRETKEY"
$tenantID = "TENANTID"
$SecuredPasswordPassword = ConvertTo-SecureString -String $SecuredPassword -AsPlainText -Force
$ClientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecuredPasswordPassword
Connect-MgGraph -TenantId $tenantID -ClientSecretCredential $ClientSecretCredential
$body = @{
message = @{
subject = "My Microsoft Graph Test Email"
body = @{
contentType = "Text"
content = "Hello, this is a test email"
}
toRecipients = @(
@{
emailAddress = @{
address = "$to"
}
}
)
}
saveToSentItems = "false"
}
Send-MgUserMail -UserId $from -BodyParameter $bodyModificar encabezados de mensajes con Send-MgUserMail
Los encabezados de los mensajes contienen información importante sobre el origen de un correo electrónico y los servidores de correo electrónico por los que pasó el mensaje. Los administradores como nosotros podemos usar la información en el encabezado del mensaje para determinar detalles específicos sobre un correo electrónico para solucionar problemas. Para obtener información más detallada sobre los encabezados de mensajes, consulte mi tutorial: Revisar e interpretar encabezados de mensajes en Exchange Online.
En nuestro caso, podemos agregar información adicional a un mensaje enviado mediante el cmdlet Send-MgUserMail para ayudar a otros usuarios a determinar el origen del correo electrónico y otros factores de solución de problemas. Otra buena razón por la que quizás desee hacer esto es para poder aplicar o excluir reglas de transporte de Exchange específicas a estos mensajes; por ejemplo, puede excluir estos mensajes para cualquier regla de registro en diario.
Para hacer esto, debe agregar el siguiente código dentro de la tabla hash message=@{}:
InternetMessageHeaders = @(
@{
Name = "x-custom-header-name"
Value = "custom value"
}
)También puedes agregar varios encabezados a tu mensaje duplicando la tabla hash dentro de:
InternetMessageHeaders = @(
@{
Name = "x-custom-header-name"
Value = "custom value"
}
@{
Name = "x-custom-header-name2"
Value = "custom value2"
}
)Modifique el x-custom-header-name (asegurándose de que el encabezado comience con x-) a algo más específico junto con el valor personalizado. A continuación puedes ver un ejemplo de mi mensaje hasta el momento:
$body = @{
message = @{
subject = "My Microsoft Graph Test Email"
body = @{
contentType = "Text"
content = "Hello, this is a test email"
}
toRecipients = @(
@{
emailAddress = @{
address = "[email "
}
}
)
InternetMessageHeaders = @(
@{
Name = "x-ocn-header-source"
Value = "azure-automation"
}
)
}
saveToSentItems = "false"
}Una vez que haya creado su encabezado, envíe un correo electrónico de prueba y vea las propiedades del encabezado del mensaje. Si está utilizando OWA, puede hacer clic derecho en el mensaje y luego hacer clic en Ver > Ver detalles del mensaje.
Enviar archivos adjuntos con Microsoft Graph PowerShell
Los archivos adjuntos pueden contener información importante para el destinatario, por lo que es útil aprender cómo agregar archivos adjuntos a los correos electrónicos mientras se envían correos electrónicos mediante programación.
Se pueden agregar archivos adjuntos desde varias fuentes mientras se usa PowerShell, por ejemplo:
- Descargado de Internet usando Invoke-WebRequest
- Seleccionado manualmente usando el explorador de archivos en Windows
- Generado dentro del propio PowerShell
Si bien seleccionar manualmente un archivo es útil durante las sesiones interactivas de PowerShell, las sesiones no interactivas requerirán que manejes la adición automática de archivos adjuntos. Veamos cómo agregar archivos adjuntos tanto de forma manual como automática.
Seleccionar archivos adjuntos manualmente
Los archivos adjuntos existentes se pueden definir manualmente en su código para usarlos en mensajes de correo electrónico. Puede hacer esto definiendo la ruta de su archivo, convirtiéndola a una cadena base 64 e incluyéndola en el cuerpo de su mensaje.
Para recuperar el archivo adjunto, puede utilizar el siguiente ejemplo y cambiar la ruta del archivo C:\temp\MyTextFile.txt.
$Attachment = "C:\temp\MyTextFile.txt"
$MailAttachement = [Convert]::ToBase64String([IO.File]::ReadAllBytes($Attachment))Luego defina los archivos adjuntos dentro de la tabla hash message@{}.
attachments = @(
@{
"@odata.type" = "#microsoft.graph.fileAttachment"
name = "$Attachment"
contentType = "text/plain"
contentBytes = $MailAttachement
}
)La tabla hash de cuerpo completo ahora debería tener el siguiente aspecto:
$body = @{
message = @{
subject = "My Microsoft Graph Test Email"
body = @{
contentType = "Text"
content = "Hello, this is a test email"
}
toRecipients = @(
@{
emailAddress = @{
address = "[email "
}
}
)
attachments = @(
@{
"@odata.type" = "#microsoft.graph.fileAttachment"
name = "$Attachment"
contentType = "text/plain"
contentBytes = $MailAttachement
}
)
}
saveToSentItems = "false"
}Descargar archivos adjuntos en línea
Un lugar más conveniente para almacenar archivos es un repositorio central de GitHub. Por supuesto, si va a hacer públicos los documentos, solo deben ser archivos de plantilla básicos o scripts funcionales (que no incluyan ninguna empresa ni datos identificables; de lo contrario, se necesita un token de acceso para acceder a un repositorio privado).
El siguiente ejemplo utiliza el cmdlet Invoke-WebRequest para descargar un archivo de un repositorio público de GitHub y prepararlo para adjuntarlo a un mensaje.
$attachment = Invoke-WebRequest -Uri "https://raw.githubusercontent.com/DanielBradley1/Public/main/Testing/MyTestCSVFile.csv"
$encodedBytes = [System.Text.Encoding]::UTF8.GetBytes($attachment.Content)
$MailAttachment = [System.Convert]::ToBase64String($encodedBytes)Es posible que también desee definir el nombre del archivo adjunto dinámicamente, en cuyo caso puede usar Regex para seleccionar el nombre del archivo después de la última barra diagonal en la ruta del archivo. Por ejemplo:
$attachment.BaseResponse.ResponseUri.AbsolutePath -match '([^\/]+$)'
$matches[1]El código completo se verá así:
$attachment = Invoke-WebRequest -Uri "https://raw.githubusercontent.com/DanielBradley1/Public/main/Testing/MyTestTextFile.txt"
$encodedBytes = [System.Text.Encoding]::UTF8.GetBytes($attachment.Content)
$MailAttachment = [System.Convert]::ToBase64String($encodedBytes)
$attachment.BaseResponse.ResponseUri.AbsolutePath -match '([^\/]+$)'
$matches[1]
$params = @{
message = @{
subject = "Automated - Inactive User Report"
body = @{
contentType = "Text"
content = "Please see the attached!"
}
toRecipients = @(
@{
emailAddress = @{
address = "[email "
}
}
)
attachments = @(
@{
"@odata.type" = "#microsoft.graph.fileAttachment"
name = $matches[1]
contentType = "text/plain"
contentBytes = $MailAttachment
}
)
}
saveToSentItems = "false"
}Crear archivos adjuntos con objetos de PowerShell
Más comúnmente, es probable que cree informes utilizando PowerShell y luego envíe esos datos adjuntos a un correo electrónico. Una forma sencilla de hacer esto es crear una matriz fija de datos, luego convertirla en un informe HTML y adjuntarlo a su correo electrónico.
Digamos que ya tiene su conjunto de datos, un buen ejemplo para usar es mi script de informe de usuario inactivo aquí: https://ourcloudnetwork.com/create-an-inactive-m365-user-report-with-microsoft-graph-powershell /.
Para adjuntar la matriz $report que se creó con nuestro script a un correo electrónico, puede usar el siguiente ejemplo para convertirla al formato HTML, aplicar un borde para ordenar la tabla y luego prepararla para adjuntarla al correo electrónico.
$report = $report | ConvertTo-Html
$Report = $report -replace '<table>', '<table border="1">'
$encodedBytes = [System.Text.Encoding]::UTF8.GetBytes($report)
$MailAttachment = [System.Convert]::ToBase64String($encodedBytes)Luego, el archivo se puede adjuntar al correo electrónico de la misma manera que en los ejemplos anteriores.
Todas las opciones de correo electrónico para Send-MgUserMail
Fundamentalmente, existen muchas otras variaciones de propiedades de mensajes que se pueden enviar mediante Microsoft Graph. Para obtener más información sobre las propiedades de un mensaje que puede personalizar, consulte la documentación del tipo de recurso de mensaje de Microsoft Graph Docs: https://learn.microsoft.com/en-us/graph/api/resources/message? ver=gráfico-rest-beta
Si tiene algún problema para agregar más propiedades, comente a continuación y estaré encantado de ayudarle lo antes posible.


