Vous consultez une page technique concernant le logiciel de gestion Mercator. Celle-ci contient des informations spécifiques destinées aux professionnels de Mercator. Souhaitez-vous être redirigés vers des informations plus générales ?


   Ne plus poser cette question

Mise à disposition d'un client pour l'envoi de mails via Office365 - Api Graph dans MercatorTunnel.dll

0000003124     -      11/10/2023

MercatorTunnel.dll version 10.10.165 ou ultérieure permet l'envoi de mails par code via l'Api Graph d'Office 365. Cette façon d'envoyer un email n'utilise pas le protocole SMTP. Toutefois, pour des raisons de compatibilité ascendante des programmations existantes, le code reste similaire à celui documenté sur cette page.

La difficulté majeure dans la mise en place de ce système est la configuration des droits d'accès dans le portail Azure.

La première donnée nécessaire est l'ID d'annuaire (Tenant). Cette information est disponible dans le portail Azure, en cliquant sur l'engrenage (Paramètres).

Ensuite, il est nécessaire de créer une application et de la configurer. Pour cela, il faut  

  • sélectionner Microsoft Entra ID dans le menu latéral gauche
  • choisir Inscriptions d'applications
  • cliquer sur Nouvelle inscription
  • Donner un nom à cette application, par exemple MercatorMails
  • Noter l'ID d'application (client), il s'agit de votre ClientId
  • Cliquer sur Ajouter un certificat ou un secret
  • Cliquer sur Nouveau secret client
  • Choisir une durée
  • Notez la valeur du secret. Il s'agit de votre ClientSecret. Attention : cette valeur n'est visible qu'une seule fois.
  • Cliquer sur API autorisées et configurer ces autorisations

En général, le Userid est l'adresse mail principale du compte.

Ensuite, le code pour envoyer un mail est simplement :

Zoom
IneoSmtp.Smtp.SendMailOffice365GraphParameters sendMailOffice365GraphParameters = new Smtp.SendMailOffice365GraphParameters
(
    "ClientId",
    "ClientSecret",
    "Tenant",
    "UserId"
);
IneoSmtp.Smtp smtp = new IneoSmtp.Smtp
{
    SendMailOffice365GraphParams = sendMailOffice365GraphParameters,
    SenderEmail = "sender@mail.com",
    Recipient = "\"Paul Petit\"<destinataire1@mail.com>",
    CC = "destinataire2@mail.com",
    Subject = "Test de mail via Office 365",
    Filenames = @"C:\Test\test.pdf",
};
if (smtp.SendMail())
    MessageBox.Show("OK");
else
    MessageBox.Show(smtp.Error);

 

Si SenderEmail n'est pas identique à UserId, il faut donner des droits "Send as" à la mailbox UserId.

Il est important de noter que le ClientSecret a une durée de vie limitée. Il est donc nécessaire de le placer dans un endroit centralisé, afin de pouvoir le mettre à jour facilement. Avant sa péremption, le ClientSecret devra être renouvelé dans le portail Azure et sa nouvelle valeur utilisée dans la mécanique décrite ci-dessus.

Pour faciliter le stockage centralisé et sécurisé du ClientSecret, nous proposons la méthode suivante :

1. Créer une table libre dont le nom, au choix, est Secrets

2. Ajouter un mémo dans cette table dont le nom, au choix, est Secret

alter table free_table_secrets add Secret varchar(max) not null default ''

3. Crypter cette colonne SECRET

4. Dans cette table libre, ajouter une ligne :

  • Id = Off365Secr
  • Secret = la valeur du ClientSecret

5. Modifier le code ci-dessus en récupérant le ClientSecret comme suit :

Zoom
string clientSecret = MercatorController.xFunctions.xLookUpString("free_table_secrets", "id", "Off365Secr", "secret");

 


On peut aussi mettre en place une centralisation des 4 paramètres, en créant 4 records dans la table libre :

  • Off365ClId : ClientId
  • Off365ClSe : ClientSecret
  • Off365Tena : Tenant
  • Off365UId : UserId

Cet accesseur fournit directement l'objet SendMailOffice365GraphParameters :

Zoom
public static IneoSmtp.Smtp.SendMailOffice365GraphParameters SendMailOffice365GraphParameters
{
    get //!\ ne pas mémoriser dans une statique car le clientSecret va changer
    {
        var l = Api.Zselect<SecretDescriptor>(Globals.RepData, "select id,secret from free_table_secrets where id like 'Off365%'");
        if (l == null)
            throw new ApplicationException("SendMailOffice365GraphParameters SQL error : " + Api.LastError);
        foreach(string key in new string[4] { "Off365ClId", "Off365ClSe", "Off365Tena", "Off365UId" })
            if (!l.Any(p => p.Id == key))
                throw new ApplicationException($"SendMailOffice365GraphParameters key \"{key}\" is missing !");
        return new IneoSmtp.Smtp.SendMailOffice365GraphParameters(
                                    l.First(p => p.Id == "Off365ClId").Secret,
                                    l.First(p => p.Id == "Off365ClSe").Secret,
                                    l.First(p => p.Id == "Off365Tena").Secret,
                                    l.First(p => p.Id == "Off365UId").Secret);
    }
}

public class SecretDescriptor
{
    public string Id { get; set; }
    public string Secret { get; set; }
}

Dans la classe IneoSmtp.Smtp, c'est le fait que SendMailOffice365GraphParams est non null, qui détermine que le mail sera envoyé vers Office365 via l'Api Graph. Toutes les autres propriétés conservent un fonctionnement similaire. Les propriétés suivantes sont toutefois inutiles, et donc ignorées :

  • MailServer
  • ServerPort
  • Username
  • Password
  • EnableSsl
  • AlternateViews

A lire : Dépréciation de l’authentification de base dans Exchange Online