faitza.com
faitza.com
> blog_tech

Emails HTML depuis PowerShell via Microsoft Graph

Calcul... powershell email microsoft-graph automation
Emails HTML PowerShell 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.

Prérequis

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 applicative
  • Mail.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.