Emails HTML depuis PowerShell via Microsoft Graph
Introduction
Faitza_Mail.ps1 expose deux fonctions pour interagir avec les boîtes mail
via Microsoft Graph : envoyer un email HTML avec pièces jointes depuis
n'importe quelle boîte applicative, et lire les messages d'une boîte entrante pour
automatiser le traitement des réponses. Les deux fonctions passent par les endpoints
/v1.0/users/{from}/sendMail et /v1.0/users/{cible}/mailFolders/inbox/messages.
Les deux fonctions utilisent Get-Faitza_Modul_Headers -resource "graph" pour
obtenir un Bearer token valide. Voir l'article dédié :
Token Bearer pour les APIs Microsoft en PowerShell.
Permissions Microsoft Graph (application) requises :
Mail.Send— envoyer depuis une boîte applicativeMail.ReadWrite— lire les messages d'une boîte
SendMail — Envoyer un email HTML
Envoie un email HTML depuis une boîte applicative via Graph. Supporte plusieurs destinataires, CC et pièces jointes (xlsx, csv, pdf, zip, txt).
function Send-Faitza_Mail {
[CmdletBinding()]
param (
[string[]]$to,
[string]$subject,
[string]$from = "[email protected]",
[string]$body = "",
[string[]]$cc,
[string[]]$attachments
)
try {
Write-Host "$($PSStyle.Background.Red)>>> Send-Faitza_Export_Mail_v3 <<<$($PSStyle.Reset)"
if (-not $from) { throw "Il manque le mail d'envoi -from" }
if (-not $to) { throw "Il manque le mail de reception -to" }
if (-not $subject) { throw "Il manque le sujet -subject" }
$headers = Get-Faitza_Modul_Headers -resource "graph"
$to_liste = @($to | ForEach-Object { @{ emailAddress = @{ address = $_ } } })
$mail_content = @{
subject = $subject
body = @{ contentType = "HTML"; content = $body }
toRecipients = $to_liste
}
if ($cc) { $mail_content["ccRecipients"] = @($cc | ForEach-Object { @{ emailAddress = @{ address = $_ } } }) }
$attachments = @($attachments | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
if ($attachments.Count -gt 0) {
$attach_types = @{
'.csv' = 'text/csv'
'.pdf' = 'application/pdf'
'.zip' = 'application/zip'
'.txt' = 'text/plain'
'.xlsx' = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
}
$mail_content["attachments"] = @($attachments | ForEach-Object {
$attach_path = $_
if (-not (Test-Path -LiteralPath $attach_path -PathType Leaf)) { throw "Piece jointe introuvable : $attach_path" }
$ext = [System.IO.Path]::GetExtension($attach_path).ToLower()
@{
"@odata.type" = "#microsoft.graph.fileAttachment"
name = Split-Path $attach_path -Leaf
contentType = if ($attach_types[$ext]) { $attach_types[$ext] } else { "application/octet-stream" }
contentBytes = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes($attach_path))
}
})
}
$mail_param = @{ message = $mail_content; saveToSentItems = "true" }
$mail_json = $mail_param | ConvertTo-Json -Depth 10 -Compress
Invoke-RestMethod -Method Post -Uri "https://graph.microsoft.com/v1.0/users/$from/sendMail" -Headers $headers -Body $mail_json
Write-Host "Mail envoye avec succes !"
return @{ retour = $true }
} catch {
throw "erreur Send-Faitza_Export_Mail_v3 : $_"
} finally {
Write-Host "$($PSStyle.Background.Red)<<< Send-Faitza_Export_Mail_v3 >>>$($PSStyle.Reset)"
}
}
Exemple d'utilisation
# Email simple
Send-Faitza_Mail `
-from "[email protected]" `
-to @("[email protected]", "[email protected]") `
-subject "Rapport hebdomadaire" `
-body "<h2>Rapport</h2><p>Voir pièce jointe.</p>"
# Avec pièce jointe et CC
Send-Faitza_Mail `
-from "[email protected]" `
-to "[email protected]" `
-cc "[email protected]" `
-subject "Export mensuel" `
-body "<p>Bonjour,<br>Veuillez trouver le rapport en pièce jointe.</p>" `
-attachments @("C:\Temp\rapport.xlsx", "C:\Temp\log.csv")
GetMail — Lire une boîte mail
Lit les N derniers messages de la boîte de réception d'une adresse mail via Graph. Pour chaque message, récupère le sujet, le corps HTML, l'expéditeur, la date de réception et le contenu des pièces jointes (base64). Utile pour automatiser le traitement de mails entrants dans un pipeline.
function Get-Faitza_Mail {
[CmdletBinding()]
param (
[string]$cible = "[email protected]",
[int]$top = 25
)
try {
Write-Host "$($PSStyle.Background.Red)>>> Get-Faitza_Export_Mail <<<$($PSStyle.Reset)"
if (-not $cible) { throw "Il manque la boite mail cible -cible" }
$headers = Get-Faitza_Modul_Headers -resource "graph"
$cible_encoded = [uri]::EscapeDataString($cible)
$uri = "https://graph.microsoft.com/v1.0/users/$cible_encoded/mailFolders/inbox/messages?`$top=$top&`$orderby=receivedDateTime desc&`$select=id,subject,body,hasAttachments,receivedDateTime,from"
$response = Invoke-RestMethod -Method Get -Uri $uri -Headers $headers -ErrorAction Stop
$messages = @()
foreach ($mail in @($response.value)) {
$pj = @()
if ($mail.hasAttachments) {
$attachmentsUri = "https://graph.microsoft.com/v1.0/users/$cible_encoded/messages/$($mail.id)/attachments?`$select=id,name,contentType,size,isInline"
$attachmentsResponse = Invoke-RestMethod -Method Get -Uri $attachmentsUri -Headers $headers -ErrorAction Stop
$pj = @($attachmentsResponse.value | ForEach-Object {
$attachmentDetailUri = "https://graph.microsoft.com/v1.0/users/$cible_encoded/messages/$($mail.id)/attachments/$($_.id)"
$attachmentDetail = Invoke-RestMethod -Method Get -Uri $attachmentDetailUri -Headers $headers -ErrorAction Stop
[pscustomobject]@{
Id = $attachmentDetail.id
Name = $attachmentDetail.name
ContentType = $attachmentDetail.contentType
Size = $attachmentDetail.size
IsInline = $attachmentDetail.isInline
ContentBytes = $attachmentDetail.contentBytes
}
})
}
$messages += [pscustomobject]@{
Id = $mail.id
Sujet = $mail.subject
Body = $mail.body.content
PJ = $pj
From = $mail.from.emailAddress.address
ReceivedDateTime = $mail.receivedDateTime
}
}
return $messages
} catch {
throw "erreur Get-Faitza_Export_Mail : $_"
} finally {
Write-Host "$($PSStyle.Background.Red)<<< Get-Faitza_Export_Mail >>>$($PSStyle.Reset)"
}
}
Exemple d'utilisation
# Lire les 25 derniers mails (defaut)
$mails = Get-Faitza_Mail -cible "[email protected]"
# Afficher les sujets
$mails | Select-Object Sujet, From, ReceivedDateTime
# Lire 10 messages et sauvegarder les pieces jointes
$mails = Get-Faitza_Mail -cible "[email protected]" -top 10
foreach ($mail in $mails) {
foreach ($pj in $mail.PJ) {
if (-not $pj.IsInline) {
$bytes = [Convert]::FromBase64String($pj.ContentBytes)
[System.IO.File]::WriteAllBytes("C:\Temp\$($pj.Name)", $bytes)
Write-Host "Sauvegarde : $($pj.Name)"
}
}
}
// Commentaires
Aucun commentaire pour l'instant.