Dev Life

Créer des flux de travail d’emails transactionnels pour les réinitialisations de mot de passe avec l’API de Mailgun

Vous avez des difficultés à envoyer des emails de réinitialisation de mot de passe sécurisés ? Ce guide pratique vous accompagne dans la création d'un flux de travail d'emails fiable et automatisé à l'aide de l'API de Mailgun et de FastAPI.…
Image pour 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 :

Account Verification Image

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

Account Verification Phone Number image

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 :

API Get Started Guide Image

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é :

Create New API Key Image

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

New API Key Image

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 principal
  • jinja2, qui sert vos modèles frontend
  • requests, 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 :

API Login Image

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

Successful API Login Image

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

Unsuccessful API Login Image

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 :

Templates Image

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 :

Blank Option image

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

Template Details image

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

Template Editor Image

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 :

Reset Password Image

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é ?  :

Forgot Password Link Image

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

Forgot Password Reset Image

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 :

Reset Password Request Image

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 :

Add Webhooks Image

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 :

New Webhook Image

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

Test webhook Image

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 :

Analytics Image

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

Metrics image

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

Customized Metrics Image

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 :

Logs Image

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 :

Bounce Classification Image

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.