Dev Life
Créer des flux de travail d’emails transactionnels pour les réinitialisations de mot de passe avec l’API de Mailgun
Emails transactionnels sont des emails automatisés déclenchés par les actions des utilisateurs sur un site web, une application ou un service. Contrairement aux emails de marketing, qui assurent la promotion de produits ou de services, les emails transactionnels fournissent des informations essentielles, souvent en temps réel.
Les flux de travail d’emails transactionnels vont encore plus loin en automatisant une séquence d’emails basée sur les actions des utilisateurs pour garantir une communication opportune et une expérience utilisateur fluide. Les entreprises s’appuient sur des services comme Mailgun pour les emails transactionnels, car ils sont rapides, pertinents et déclenchés par des actions immédiates des utilisateurs. Par exemple, le flux de travail permet à un utilisateur de réinitialiser rapidement son mot de passe et de retrouver l’accès à son compte.
Dans ce tutoriel, vous apprendrez à créer un flux de travail d’emails transactionnels pour les réinitialisations de mot de passe avec l’API de Mailgun.
Configurer un compte Mailgun
Si vous n’avez pas encore de compte Mailgun, la première chose à faire est d’en créer un. Assurez-vous de consulter l’email associé à votre compte Mailgun et de vérifier votre compte :

Ensuite, saisissez votre numéro de téléphone et le code d’autorisation fourni pour activer votre compte :

Une fois votre compte Mailgun configuré, il est temps d’obtenir une clé API pour commencer à utiliser le service.
Obtenir une clé API
Pour que votre application interagisse avec les services de Mailgun, elle doit être authentifiée via une clé API. Pour obtenir votre clé API, accédez au tableau de bord Mailgun et sélectionnez Démarrer à gauche pour afficher un Guide de démarrage :

Cliquez sur le bouton Démarrer sous Créer une clé API. Ensuite, fournissez une description qui décrit correctement l’objectif de la clé API. Par exemple, si la clé API est destinée aux processus d’authentification des utilisateurs, vous pouvez la nommer user_authentication et cliquer sur Créer une clé :

Assurez-vous de copier et de conserver cette clé en lieu sûr, car c’est la seule fois qu’elle sera affichée :

Créer l’interface de l’application avec FastAPI
Pour créer l’interface de l’application qui alimente le flux de travail d’emails, la première chose à faire est d’installer les bibliothèques nécessaires. Avant cela, créez un répertoire de projet en exécutant mkdir my_fastapi_app et lancez un environnement virtuel dans le répertoire.
Ensuite, installez les bibliothèques nécessaires avec la commande suivante :
pip install fastapi jinja2 requests uvicorn python-multipart
Ici, vous installez :
fastapi, qui sert de framework backend principaljinja2, qui sert vos modèles frontendrequests, qui envoie des requêtes HTTP à l’API de Mailgun
Bien que FastAPI soit principalement destiné à la création d’API, l’ajout de la bibliothèque jinja2 permet un développement full-stack, mais cela nécessite une configuration de répertoire appropriée. La structure de votre projet doit suivre ce format :
my_fastapi_app/
│── main.py # Fichier principal de l'application FastAPI
│── users.json # Fichier JSON stockant les données utilisateur
│── templates/ # Dossier des modèles HTML
│ ├── login.html # Page de connexion
│ ├── home.html # Page d'accueil
│ ├── passwordReset.html # Page de réinitialisation de mot de passe
│── static/ # Dossier des fichiers statiques
│ ├── styles.css # Styles pour les fichiers login.html et passwordReset.html
Vous pouvez trouver tout le code de ce tutoriel dans ce dépôt GitHub.
Une fois la structure de votre projet en place, vous pouvez copier et coller le code dans les fichiers respectifs ou cloner le dépôt GitHub ci-dessus avec la commande suivante :
git clone https://github.com/EphraimX/building-transactional-email-workflows-for-password-resets-with-mailgun-api.git
Jetons un coup d’œil à la première section du fichier main.py. C’est dans ce fichier que toute la magie opère, car il connecte les opérations frontend et backend :
import osrnimport jsonrnimport uuidrnimport requestsrnimport urllib.parsernfrom fastapi import FastAPI, Request, Formrnfrom pydantic import BaseModelrnfrom fastapi.responses import HTMLResponsernfrom fastapi.staticfiles import StaticFilesrnfrom fastapi.templating import Jinja2Templatesrnrnapp = FastAPI()rnapp.mount("/static", StaticFiles(directory="static"), name="static")rntemplates = Jinja2Templates(directory="templates")rnrnclass loginData(BaseModel):rn username: strrn password: strrnrn@app.get("/login", response_class=HTMLResponse)rnasync def login(request: Request):rn return templates.TemplateResponse("login.html", {"request": request, "message": ""})rnrn@app.get("/passwordResetView/", response_class=HTMLResponse)rnasync def password_reset_view(request: Request):rn return templates.TemplateResponse(rn "passwordReset.html", {"request": request, "message": ""}rn )rnrn@app.post("/home", response_class=HTMLResponse)rnasync def password_reset(rn request: Request, email_address: str = Form(...), password: str = Form(...)rn):rnrn # Open and read the JSON DB filern try:rn with open("users.json", "r") as file:rn users = json.load(file)rn except (FileNotFoundError, json.JSONDecodeError):rn users = []rnrn for user in users:rnrn if user["email_address"] == email_address and user["password"] == password:rn return templates.TemplateResponse("home.html", {"request": request})rnrn # If no match was found, return an error messagern return templates.TemplateResponse(rn "login.html",rn {rn "request": request,rn "message": "Email or Password Incorrect. If you cannot remember your password, kindly reset it.",rn },rn )rn
Dans ce code, l’application gère l’authentification en servant des pages de connexion et de réinitialisation de mot de passe tout en vérifiant les identifiants dans users.json. L’application initialise FastAPI, configure les modèles et définit un modèle loginData pour la validation. Les routes /login et /passwordResetView/ servent leurs pages respectives, tandis que /home vérifie les identifiants, redirigeant les utilisateurs valides ou affichant des erreurs. La fonction de réinitialisation de mot de passe génère un lien unique en utilisant uuid et l’envoie via l’API de Mailgun.
Pour tester cela, ouvrez votre base de données de fortune (users.json) et collez ce qui suit :
[rn {rn "username" : "sinchy",rn "email_address" : "sinch@gmail.com",rn "password" : "sinch12345"rn },rn {rn "username" : "grinchy",rn "email_address" : "rinch@gmail.com",rn "password" : "grinch67890"rn }rn]
Vous devez également autoriser ces adresses emails via le tableau de bord Mailgun si vous utilisez un domaine sandbox.
Démarrez votre application en exécutant la commande uvicorn main:app –reload. Ensuite, rendez-vous sur http://localhost:8000/login, où vous devriez voir ceci :

Si vous essayez de vous connecter avec l’un des identifiants du fichier users.json, vous serez redirigé vers la page d’accueil :

Si vous saisissez de mauvaises informations de connexion, vous verrez ceci :

Configurer une connexion à Mailgun
Pour envoyer des emails avec Mailgun, vous devez établir une connexion entre votre application et le service d’emailing de Mailgun.
Pour ce faire, ouvrez main.py et collez le code suivant, en remplaçant , et par des valeurs valides :
def send_simple_message(API_KEY):rn response = requests.post(rn "https://api.mailgun.net/v3/<SANDBOX_URL>/messages",rn auth=("api", f"{API_KEY}"),rn data={"from": "Mailgun Sandbox <postmaster@<SANDBOX_URL>>",rn "to": "<RECIPIENT_NAME> <RECIPIENT_EMAIL>",rn "subject": "Hello <RECIPIENT_NAME>",rn "text": "Congratulations <RECIPIENT_NAME>, you just sent an email with Mailgun! You are truly awesome!"rn }rn )rnrn print(response.json())rn return responsern
À des fins de test, transmettez votre clé API directement lors de l’appel de la fonction :
send_simple_message("your-api-key-here")
Lancez le script en exécutant ce qui suit :
python main.py
En cas de succès, la fonction affichera une réponse similaire à celle-ci :
{
"id": "",
"message": "Queued. Thank you."
}
Cela confirme que la requête d’email a bien été mise en file d’attente par Mailgun.
Concevoir et configurer le modèle d’email
Pour travailler sur la logique de réinitialisation de mot de passe, vous devez concevoir le modèle de l’email envoyé à l’utilisateur. Avec Mailgun, il existe deux façons de concevoir un email : le HTML ou le constructeur de modèle « drag-and-drop » de Mailgun. Vous utiliserez ici l’approche HTML.
Pour commencer la conception, accédez à votre tableau de bord Mailgun et naviguez vers Envoi > Envoi > Modèles :

Ensuite, cliquez sur Créer un modèle de message, sélectionnez l’option pour le coder en HTML et cliquez sur le modèle Vierge :

Remplissez le formulaire de modèle avec le nom, la description et les détails de l’email :

Ensuite, faites défiler jusqu’à l’onglet Éditeur et copiez-collez le code du fichier email_template.html :

Lorsque vous sélectionnez l’onglet Données de test, vous verrez deux variables dynamiques : username et reset_link.
Sélectionnez l’onglet Aperçu pour voir le modèle :

Enfin, cliquez sur le bouton Créer pour le créer.
Mise en œuvre de la fonctionnalité d’envoi d’emails
Une fois votre modèle d’email prêt, il est temps de développer la fonctionnalité d’envoi d’emails. Ouvrez le fichier main.py et collez le code suivant :
@app.post("/resetPassword/")rnasync def reset_password(request: Request, email_address: str = Form(...)):rnrn # Open and read the JSON DB filern try:rn with open("users.json", "r") as file:rn users = json.load(file)rn except (FileNotFoundError, json.JSONDecodeError):rn users = []rnrn for user in users:rn if user["email_address"] == email_address:rnrn email_address = user["email_address"]rn username = user["username"]rn reset_link = await generate_password_reset_link(email_address)rnrn response = await send_password_reset_email(rn username, email_address, reset_linkrn )rnrn if response["success"]:rnrn return templates.TemplateResponse(rn "login.html",rn {rn "request": request,rn "message": "Kindly check your email to reset your password.",rn },rn )rnrn else:rnrn return templates.TemplateResponse(rn "passwordReset.html",rn {rn "request": request,rn "message": "Unfortunately, we ran into an error while trying to reset your password. Kindly try again, and if the issue persists, please contact support.",rn },rn )rnrn # If no match was found, return an error messagern return templates.TemplateResponse(rn "passwordReset.html",rn {rn "request": request,rn "message": "Unfortunately, we do not have a record of your email. Kindly reach out to the site administrator.",rn },rn )rnrnasync def send_password_reset_email(username, email_address, reset_link):rnrn API_KEY = os.getenv("API_KEY") # Fetch API key from environmentrnrn if not API_KEY:rn print("Error: API_KEY is not set!")rn return {"success": False, "error": "API key is missing"}rnrn try:rn response = requests.post(rn "https://api.mailgun.net/v3/<SANDBOX_URL>/messages",rn auth=("api", API_KEY),rn data={rn "from": "Mailgun Sandbox <postmaster@<SANDBOX_URL>>",rn "to": f"{username} <{email_address}>",rn "subject": f"Hello {username}",rn "template": "<EMAIL_TEMPLATE_NAME>",rn "h:X-Mailgun-Variables": json.dumps(rn {"reset_link": reset_link, "username": username}rn ),rn },rn )rnrn if response.status_code == 200:rn print(f"Password reset email sent successfully to {email_address}")rn return {"success": True, "message": "Email sent successfully"}rn else:rn print(rn f"Failed to send email. Status Code: {response.status_code}, Response: {response.text}"rn )rn return {"success": False, "error": response.text}rnrn except requests.exceptions.RequestException as e:rn print(f"Request failed: {str(e)}")rn return {"success": False, "error": str(e)}rnrnasync def generate_password_reset_link(rn email_address, base_url="https://mailgunny.com/reset-password"rn):rn token = uuid.uuid4()rn encoded_email = urllib.parse.quote(email_address)rn return f"{base_url}?email={encoded_email}&token={token}"rn
Dans ce code, la fonction reset_password (@app.post("/resetPassword/")) traite les requêtes de réinitialisation de mot de passe en vérifiant si l’email soumis existe dans la base de données users.json. S’il est trouvé, elle génère un lien de réinitialisation unique à l’aide de generate_password_reset_link(email_address) et envoie l’email de réinitialisation via send_password_reset_email(username, email_address, reset_link). La fonction renvoie ensuite un message de réussite si l’email a été envoyé, ou affiche un message d’erreur dans le cas contraire. Si aucun email correspondant n’est trouvé, une réponse d’erreur appropriée est fournie.
Remarque : Remplacez la variable API_KEY par la clé de votre compte Mailgun.
Pour tester l’implémentation, exécutez uvicorn main:app –reload et ouvrez http://localhost:8000/login. Cliquez sur le lien Mot de passe oublié ? :

Saisissez un email présent dans votre fichier users.json et cliquez sur Réinitialiser le mot de passe :

En cas de succès, vous devriez être redirigé vers la page de connexion, où vous recevrez des instructions pour vérifier vos emails. Vous devriez voir l’email suivant dans la boîte de réception du destinataire :

Intégration avec les événements de l’application
S’intégrer aux événements de l’application à l’aide de webhooks permet à votre système de répondre automatiquement aux mises à jour en temps réel provenant de services externes.
Un webhook est essentiellement un rappel HTTP. Chaque fois qu’un événement spécifique se produit dans une application externe (comme une confirmation de paiement, une inscription d’utilisateur ou une demande de réinitialisation de mot de passe), le service envoie une requête à l’URL de votre webhook prédéfinie. Cela permet une automatisation fluide, réduisant ainsi le besoin d’intervention manuelle ou d’interrogations périodiques. En configurant votre application pour qu’elle écoute ces événements de webhook, vous pouvez déclencher des actions pertinentes, telles que la mise à jour d’une base de données, l’envoi de notifications ou le traitement de transactions, dès que l’événement se produit.
Pour intégrer des webhooks avec Mailgun, vous devez créer un point de terminaison. Pour ce faire, ouvrez le fichier main.py et collez le code suivant à la fin :
@app.post("/webhooks/password-reset")rnasync def handle_webhook(request: Request):rn data = await request.json()rn print(f"Password reset email clicked: {data}")rn return {"status": "received", "status_code": 200}rn
Retournez sur le tableau de bord et accédez à Envoi > Envoi > Webhooks :

Cliquez sur Ajouter un webhook dans le coin supérieur droit. Dans la liste déroulante des types d’événements, sélectionnez Messages remis, et dans le champ URL, saisissez la route vers l’URL de votre webhook. Dans ce cas, c’est https:///webhooks/password-reset. Une fois que vous avez terminé, cliquez sur Créer un webhook :

Testez le webhook. Votre résultat devrait ressembler à ceci :

Côté serveur, vous devriez obtenir le message suivant :
Password reset email clicked: {'signature': {'token': '41929b08bb287b8a0b157f7834844b6bc483b7b090692a2b15', 'timestamp': '1739785355', 'signature': '117f70dcf985c72df30c07b02898dd458d1cbbad29d0457ccee8c4497f89c5ac'}, 'event-data': {'id': 'CPgfbmQMTCKtHW6uIWtuVe', 'timestamp': 1521472262.908181, 'log-level': 'info', 'event': 'delivered', 'delivery-status': {'tls': True, 'mx-host': 'smtp-in.example.com', 'code': 250, 'description': '', 'session-seconds': 0.4331989288330078, 'utf8': True, 'attempt-no': 1, 'message': 'OK', 'certificate-verified': True}, 'flags': {'is-routed': False, 'is-authenticated': True, 'is-system-test': False, 'is-test-mode': False}, 'envelope': {'transport': 'smtp', 'sender': 'bob@sandbox9199067bcb654265aae9ce9e308b6150.mailgun.org', 'sending-ip': '209.61.154.250', 'targets': 'alice@example.com'}, 'message': {'headers': {'to': 'Alice ', 'message-id': '20130503182626.18666.16540@sandbox9199067bcb654265aae9ce9e308b6150.mailgun.org', 'from': 'Bob ', 'subject': 'Test delivered webhook'}, 'attachments': [], 'size': 111}, 'recipient': 'alice@example.com', 'recipient-domain': 'example.com', 'storage': {'url': 'https://se.api.mailgun.net/v3/domains/sandbox9199067bcb654265aae9ce9e308b6150.mailgun.org/messages/message_key', 'key': 'message_key'}, 'campaigns': [], 'tags': ['my_tag_1', 'my_tag_2'], 'user-variables': {'my_var_1': 'Mailgun Variable #1', 'my-var-2': 'awesome'}}}
Cela peut changer en fonction de l’email envoyé.
Suivi et gestion des emails
Peter Drucker, célèbre consultant en management, a dit un jour :
Ce qui ne se mesure pas ne s’améliore pas.
Dans cette optique, Mailgun propose des outils pour vérifier les performances des emails envoyés. Par exemple, la page Envoi > Envoi > Statistiques permet de mesurer le pourcentage d’emails remis, ouverts et cliqués :

Sur la page Envoi > Rapports > Statistiques, vous pouvez obtenir des informations détaillées sur les performances de vos emails :

Vous pouvez également choisir les statistiques que vous souhaitez consulter sur une période donnée :

Mailgun met également des journaux à votre disposition au cas où vous souhaiteriez approfondir les événements de remise et enquêter sur les échecs lorsqu’ils se produisent :

Enfin, Mailgun propose une classification des rebonds pour voir combien de vos emails n’ont pas abouti. Cela vous permet également de savoir combien de ces rebonds sont critiques :

Conclusion
Dans ce tutoriel, vous avez appris à créer un flux de travail d’emails transactionnels complet pour les réinitialisations de mot de passe avec l’API de Mailgun. Après avoir configuré un compte Mailgun et obtenu une clé API, vous avez créé une interface d’application à l’aide de FastAPI. Vous avez ensuite conçu et configuré un modèle d’email, implémenté la fonctionnalité d’envoi d’emails et intégré des webhooks pour le suivi des événements en temps réel.
Les opérations d’emails transactionnels sont essentielles pour offrir une expérience utilisateur fluide et sécurisée, en particulier pour les réinitialisations de mot de passe. Mailgun peut vous aider à automatiser ce processus, améliorant ainsi la sécurité et la productivité tout en éliminant les interventions manuelles. La mise en œuvre de cette approche dans vos projets augmentera non seulement la satisfaction de la clientèle, mais contribuera également à maintenir un système d’authentification fiable.