Les emails expédiés par une application, un site, un webservice (…) sont généralement confiés à un serveur en utilisant le protocole SMTP (Simple Mail Transfer Protocol).
Les contraintes de sécurité actuelles peuvent rendre l'utilisation de ce protocole complexe. C'est le cas lorsque l'hébergeur du serveur SMTP ajoute une double authentification avec OAuth 2, comme Google pour Gmail, ou Microsoft avec Office365. En effet lorsqu'une authentification oAuth est demandée par un service de messagerie :
En fonction des besoins, on peut donc être amené à remplacer l'appel des fonctions EmailOuvreSession et EmailEnvoieMessage, par l'appel de la fonction RESTEnvoie afin d'envoyer les emails non pas à un serveur SMTP, mais à une API en ligne. Le principe de token sera identique :
- une première requête à l'API en HTTPS va demander le token,
- une seconde requête va envoyer l'email grâce au token obtenu.
Voici un exemple de code avec l'API Microsoft Graph :
Requête est une restRequête Réponse est une httpRéponse Token est un JSON
sClientId est une chaîne = "---" // Données du compte Azure dans lequel l'application est définie sTenantId est une chaîne = "---" sClientSecret est une chaîne = "---" sURI est une chaîne = "https://login.microsoftonline.com/%1/oauth2/v2.0/token" // Ou suivant le cas : "https://login.microsoftonline.com/common/oauth2/v2.0/token"
Requête..URL = ChaîneConstruit(sURI, sTenantId) Requête..Méthode = httpPost Requête..ContentType = "application/x-www-form-urlencoded" HTTPCréeFormulaire("FORM_TOKEN") HTTPAjouteParamètre("FORM_TOKEN","grant_type","client_credentials") HTTPAjouteParamètre("FORM_TOKEN","client_id",sClientId) HTTPAjouteParamètre("FORM_TOKEN","client_secret", sClientSecret) HTTPAjouteParamètre("FORM_TOKEN","scope","https://graph.microsoft.com/.default") Réponse = HTTPEnvoieFormulaire("FORM_TOKEN",Requête) Token = Réponse..Contenu
VariableRAZ(Requête) sExpéditeur est une chaîne = "adresse@expediteur.demo" sURI = "https://graph.microsoft.com/v1.0/users/%1/sendMail" sURI = ChaîneConstruit(sURI, sExpéditeur )
MonMessage est un Email
monAttache est un emailAttache
sFichier est une chaîne = "c:\temp\exemple-image.jpg" MonMessage.Message = "Mon email texte" MonMessage.HTML = "Message <b>HTML</b>" MonMessage.Expediteur = sExpéditeur MonMessage.Sujet = "Test : API Graph Microsoft" MonMessage.Destinataire.Ajoute("adresse@destinataire.demo") monAttache.Nom = fExtraitChemin(sFichier, fFichier + fExtension) monAttache.Contenu = fChargeBuffer(sFichier) monAttache.ContentType = "image/jpeg" monAttache.ContentDescription = "Une image jointe" Ajoute(MonMessage.Attache, monAttache)
MessageEnBuffer est un Buffer MonMessage.ConstruitSource(emailOptionEncodeEntête) MessageEnBuffer = MonMessage.Source MessageEnBuffer = ChaîneVersUTF8(MessageEnBuffer.Encode(encodeBASE64)) // (*)
Requête..URL = sURI Requête..Méthode = httpPost Requête..ContentType = "text/plain"
Requête.Entête["Authorization"] = Token.token_type+" "+Token.access_token
Requête.Contenu = MessageEnBuffer Réponse = RESTEnvoie(Requête) SI Réponse.CodeEtat = 202 ALORS OK...
Variantes et astuces de mise au point :
- La propriété ProcédureTrace du type RestRequete permet d'avoir le contenu complet de l'échange avec le serveur. Elle est pratique en phase de mise au point afin de recherche une éventuelle erreur dans le contenu envoyé :
Requête..ProcédureTrace = RESTEnvoie_Trace
Avec :
PROCEDURE INTERNE RESTEnvoie_Trace( nTypeInfo est un entier, bufData est un Buffer )
SELON nTypeInfo CAS httpTraceEntêteEnvoyé : Trace("Entête envoyée" + UTF8VersChaîne( bufData ) )
CAS httpTraceDonnéeEnvoyée : Trace("Données envoyée" + bufData )
CAS httpTraceEntêteRecu : Trace("Entête reçue" + UTF8VersChaîne( bufData ) )
CAS httpTraceDonnéeRecue : Trace("DOnnées reçues" + bufData ) FIN
FIN
-
Important : les autorisations associées à un token renvoyé par un service, donne des possibilités dépendantes du "scope" indiqué envoyée à l'API. On peut donc avoir obtenu un token valide, mais avoir un échec pour envoyer le message car le scope du token n'autorise pas l'envoi. Si un token ne donne pas accès à une fonctionnalité, c'est donc :
-
que le "scope" donné pour l'authentification n'avait pas la fonctionnalité nécessaire dans l'application dans le portail Azure,
-
ou que l'application configurée dans le service d'authentification n'autorise pas la fonctionnalité demandée,
-
ou que l'application configurée dans le service d'authentification autorise la fonctionnalité demandée mais avec des caractéristiques inadaptées (ex dans le cas de Office365 un type "Déléguée" au lieu de "Application" dans Azure)...
- Pour simplifier l'exemple ne traite pas les réponses du serveur. Il faut ajouter des contrôles systématique sur Réponse..CodeEtat et Token = Réponse..Contenu. Si le token n'est pas obtenu il ne faut pas envoyer l'email et à la place indiquer la réponse du serveur.
- (*) Dans cette conversion :
MessageEnBuffer = ChaîneVersUTF8(MessageEnBuffer.Encode(encodeBASE64)) ChaineVersUTF8 permet d'être certain de conserver des données en ANSI dans toutes les configurations. En effet, la fonction Encode retourne une chaîne. Si la configuration courante est en UNICODE, par exemple sous iOS, sans cette conversion le buffer aurait donc eu les données encodées en base64 mais avec des 0 binaires entre chaque caractère.
|
|
< Retour
|
|
|
|
|
|