In questo post viene spiegato come è possibile inviare una mail tramite Graph API di Azure restringendo la possibilità di usare solo uno specifico mittente.

Questa possibilità torna utile per evitare che una applicazione possa inviare mail impersonando qualunque utente del tenant.

Cosa serve:
  • Un App Registration
  • Un utente con mailbox da usare come mittente
  • Una policy su Exchange online
  • il codice C# di invio

App Registration

Per poter inviare una mail tramite le Graph API è necessario creare un App Registration su Azure Active Directory creando un secret che servirà successivamente (oltre al tenanId e al clientId).

A questa app va assegnato il permesso Mail.Send di tipo Application
App Registration
App Registration
Il permesso va confermato, da un amministratore, premendo su Grant admin consent for ...

Mailbox

Per l'invio è necessario usare la mail box di un utente.
Si può usare un utente esistente o crearne uno nuovo, dedicato all'applicazione, con relativa mailbox (ad esempio usersend@xxxx.onmicrosoft.com).

Exchange online

Tramite i comandi PowerShell di Exchange online va creata la policy che vincola la App Registration ad usare solo una mailbox come mittente.

Per eseguire questi comandi è necessario installarli

PowerShell

# installa il modulo ExchangeOnlineManagement
Install-Module -Name ExchangeOnlineManagement

# lo importa nella console PowerShell
Import-Module ExchangeOnlineManagement

# imposta la policy di esecuzione degli script
Set-ExecutionPolicy RemoteSigned
Eseguire questi comandi in elevati privilegi

Successivamente va creata la policy che restringe l'accesso solo ad una specifica mailbox

PowerShell

# l'utente admin su Exchange online con cui fare login
$loginUser = "useradmin@xxxx.onmicrosoft.com"
# il clientID dell'App Registration
$clientId = "17430451-xxxx-xxxx-xxxx-f256ab48cbf3"
# il nome con cui verrà creato il distribution group in cui verrà inserito il mittente
$distributionGroup = "TestSendMailRestrictedSgartIt"
# l'unico mittente con cui sarà possibile inviare le mail
$fromAddress = "usersend@xxxx.onmicrosoft.com"

# connessione con Exchange online
Connect-ExchangeOnline -UserPrincipalName $loginUser

# creazione di un Distribution Group
$ds = New-DistributionGroup -Name $distributionGroup -Alias $distributionGroup.toLower() -Type security
$primarySmtpAddress = $ds.PrimarySmtpAddress

# creo una nuova policy di tipo "RestrictAccess" e la associo alla App Registration e al Distribution Group
$aap = New-ApplicationAccessPolicy -AppId $clientId -PolicyScopeGroupId $primarySmtpAddress  -AccessRight RestrictAccess -Description "Restrict this app to members of distribution group $distributionGroup"

# aggiungo al Distribution Group la mailbox da usare come mittente
Add-DistributionGroupMember -Identity $distributionGroup -Member $fromAddress -Confirm:$false

# visualizzo l'appartenenza al gruppo
Get-DistributionGroupMember $distributionGroup

Codice di esempio

Adesso ci sono tutti gli elementi per realizzare un esempio di invio mail in C#.

Per la demo sarà necessario installare questi 2 pacchetti NuGet

XML: Nuget

<PackageReference Include="Azure.Identity" Version="1.9.0" />
<PackageReference Include="Microsoft.Graph" Version="5.14.0" />
e il codice di esempio è questo

C#: Invio mail in .NET 6 con Graph API restricted

using Azure.Identity;
using Microsoft.Graph.Models;
using Microsoft.Graph;
using Microsoft.Graph.Users.Item.SendMail;

TestSendMail().Wait();

static async Task TestSendMail()
{
    string tenantId = "b32d8...2dca9";
    string clientId = "17430....bf3";
    string clientSecret = "yM_....or";

    // questo è l'unico mittente accettato
    string fromAddress = "usersend@xxxx.onmicrosoft.com";

    // destinatario
    string toAddress = "destinatario@dominio.it";
    string subject = "Prova invio mail restricted";
    string body = "<b>invio riuscito</b>";

    try
    {
        // connessione alle Graph API
        ClientSecretCredential credential = new(tenantId, clientId, clientSecret);
        using GraphServiceClient graphClient = new(credential);

        // Costruisco il messaggio da inviare
        // di tipo Microsoft.Graph.Users.Item.SendMail.SendMailPostRequestBody
        SendMailPostRequestBody postRequest = new()
        {
            SaveToSentItems = true,
            Message = new()
            {
                Subject = subject,
                Body = new ItemBody
                {
                    ContentType = BodyType.Html,
                    Content = body
                },
                ToRecipients = new List<Recipient>()
                {
                    new Recipient
                    {
                        EmailAddress = new EmailAddress
                        {
                            Address = toAddress
                        }
                    }
                }
            }
        };

        // Invio il messaggio
        await graphClient
            .Users[fromAddress]
            .SendMail
            .PostAsync(postRequest);

    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
        throw;
    }
}
Da notare il parametro SaveToSentItems che permette di scegliere se conservare una copia del messaggio nella mailbox.
Per verificare la restrizione sul mittente e sufficiente cambiare la variabile fromAddress con un altra mail del tenant, si otterrà un errore di accesso
Exception of type 'Microsoft.Graph.Models.ODataErrors.ODataError' was thrown
Exception
Exception
Tags:
C#236 Azure7 .NET Core26
Potrebbe interessarti anche: