Dev Life

Como criar fluxos de trabalho de e-mail transacional para redefinir senhas com a API do Mailgun

Com dificuldades para enviar e-mails seguros para redefinir senhas? Este guia prático mostra como criar um fluxo de trabalho de e-mail automatizado e confiável usando a API do Mailgun e o FastAPI.…
Imagem para Como criar fluxos de trabalho de e-mail transacional para redefinir senhas com a API do Mailgun

E-mails transacionais são e-mails automatizados acionados por ações do usuário em um site, aplicativo ou serviço. Ao contrário dos e-mails de marketing, que promovem produtos ou serviços, os e-mails transacionais fornecem informações essenciais, muitas vezes em tempo real.

Os fluxos de trabalho de e-mail transacional vão além, automatizando uma sequência de e-mails com base nas ações do usuário para garantir uma comunicação pontual e uma experiência do usuário tranquila. As empresas contam com serviços como Mailgun para e-mails transacionais porque são rápidos, relevantes e acionados por ações imediatas do usuário. Por exemplo, o fluxo de trabalho permite que o usuário possa redefinir sua senha rapidamente e recuperar o acesso à sua conta.

Neste tutorial, você aprenderá como criar um fluxo de trabalho de e-mail transacional para redefinir senhas com a API do Mailgun.

Configurando uma conta do Mailgun

Se você ainda não tem uma conta no Mailgun, a primeira coisa que precisa fazer é criar uma. Não se esqueça de checar o e-mail associado à sua conta no Mailgun e verificá-la:

Account Verification Image

Em seguida, insira seu número de telefone e o código de autorização fornecido para ativar sua conta:

Account Verification Phone Number image

Assim que sua conta no Mailgun estiver configurada, é hora de obter uma chave de API para começar a usar o serviço.

Como obter uma chave de API

Para que seu aplicativo interaja com os serviços do Mailgun, ele precisa ser autenticado por meio de uma chave de API. Para obter sua chave de API, acesse o painel do Mailgun e selecione “Começar” à esquerda para visualizar um “Guia de introdução”:

API Get Started Guide Image

Clique no botão “Começar” abaixo de “Criar uma chave de API”. Depois, forneça uma descrição que explique corretamente o propósito da chave de API. Por exemplo, se a chave de API for para processos de autenticação de usuários, você pode chamá-la de algo como user_authentication e clicar em “Criar chave”:

Create New API Key Image

Não se esqueça de copiar e guardar essa chave em um local seguro, pois esta é a única vez que ela será exibida:

New API Key Image

Criando a interface do aplicativo usando FastAPI

Para criar a interface do aplicativo que impulsiona o fluxo de trabalho de e-mail, a primeira coisa a fazer é instalar as bibliotecas necessárias. Antes de fazer isso, crie um diretório de projeto executando mkdir my_fastapi_app e inicie um ambiente virtual no diretório.

Em seguida, instale as bibliotecas necessárias com o seguinte comando:

pip install fastapi jinja2 requests uvicorn python-multipart

Aqui, você instala:

  • fastapi, que serve como o framework principal de backend
  • jinja2, que serve seus modelos de frontend
  • requests, que envia requisições HTTP para a API do Mailgun

Embora o FastAPI seja principalmente para a criação de APIs, a adição da biblioteca jinja2 permite o desenvolvimento full-stack, mas requer uma configuração de diretório adequada. A estrutura do seu projeto deve seguir este formato:

my_fastapi_app/
│── main.py # Arquivo principal do aplicativo FastAPI
│── users.json # Arquivo JSON que armazena dados do usuário
│── templates/ # Pasta de modelos HTML
│ ├── login.html # Página de login
│ ├── home.html # Página inicial
│ ├── passwordReset.html # Página para redefinir senha
│── static/ # Pasta de arquivos estáticos
│ ├── styles.css # Estilos para os arquivos login.html e passwordReset.html

Você pode encontrar todo o código para este tutorial no este repositório do GitHub.

Com a estrutura do seu projeto em vigor, você pode copiar e colar o código nos respectivos arquivos ou clonar o repositório do GitHub acima com o seguinte comando:

git clone https://github.com/EphraimX/building-transactional-email-workflows-for-password-resets-with-mailgun-api.git

Vamos dar uma olhada na primeira seção do arquivo main.py. Este arquivo é onde toda a mágica acontece, pois conecta as operações de frontend e 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
                                
                            

Neste código, o aplicativo lida com a autenticação servindo páginas de login e para redefinir senhas enquanto verifica as credenciais em users.json. O aplicativo inicializa o FastAPI, configura os modelos e define um modelo loginData para validação. As rotas /login e /passwordResetView/ servem suas respectivas páginas, enquanto a /home verifica as credenciais, redirecionando usuários válidos ou exibindo erros. A função para redefinir a senha gera um link exclusivo usando o uuid e o envia pela API do Mailgun.

Para testar isso, abra seu banco de dados improvisado (users.json) e cole o seguinte:

                                

                                    [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]
                                
                            

Você também deve autorizar esses endereços de e-mail pelo painel do Mailgun se você estiver usando um domínio de sandbox.

Inicie seu aplicativo executando o comando uvicorn main:app –reload. Depois, acesse http://localhost:8000/login, onde você deverá ver isto:

API Login Image

Se você tentar fazer login com alguma das credenciais no arquivo users.json, você será levado para a página inicial:

Successful API Login Image

Se você inserir as informações de login incorretas, verá o seguinte:

Unsuccessful API Login Image

Configurando uma conexão com o Mailgun

Para enviar e-mails usando o Mailgun, você precisa estabelecer uma conexão entre seu aplicativo e o serviço de e-mail do Mailgun.

Para fazer isso, abra o main.py e cole o código a seguir, substituindo , e por valores válidos:

                                

                                    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
                                
                            

Para fins de teste, passe sua chave de API diretamente ao chamar a função:

send_simple_message("your-api-key-here")

Execute o script com o seguinte comando:

python main.py

Se for bem-sucedida, a função imprimirá uma resposta semelhante a esta:

{
"id": "",
"message": "Queued. Thank you."
}

Isso confirma que a requisição de e-mail foi adicionada à fila com sucesso pelo Mailgun.

Como criar e configurar o modelo de e-mail

Para trabalhar na lógica de redefinir a senha, você precisa criar o modelo para o e-mail que é enviado ao usuário. Com o Mailgun, há duas maneiras de criar um e-mail: HTML ou o construtor de modelos de arrastar e soltar do Mailgun. Você usará a abordagem HTML aqui.

Para iniciar a criação, acesse seu painel do Mailgun e navegue até “Enviar” > “Envio” > “Modelos”:

Templates Image

Em seguida, clique em “Criar modelo de mensagem”, selecione a opção para programá-lo em HTML e clique no modelo “Em branco”:

Blank Option image

Preencha o formulário do modelo com o nome, a descrição e os detalhes do e-mail:

Template Details image

Depois, role a página até a guia “Editor” e copie e cole o código do email_template.html arquivo:

Template Editor Image

Ao selecionar a guia “Dados de teste”, você verá duas variáveis dinâmicas: username e reset_link.

Selecione a guia “Pré-visualização” para ver o modelo:

Reset Password Image

Por fim, clique no botão “Criar” para criá-lo.

Implementando a funcionalidade de envio de e-mail

Assim que seu modelo de e-mail estiver pronto, é hora de desenvolver a funcionalidade de envio de e-mails. Abra o arquivo main.py e cole o código a seguir:

                                

                                    @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
                                
                            

Neste código, a função reset_password (@app.post("/resetPassword/")) processa as solicitações para redefinir a senha, verificando se o e-mail enviado existe no banco de dados users.json. Se encontrado, ela gera um link de redefinição exclusivo usando generate_password_reset_link(email_address) e envia o e-mail de redefinição por meio da send_password_reset_email(username, email_address, reset_link). A função então retorna uma mensagem de sucesso se o e-mail foi enviado ou exibe uma mensagem de erro caso contrário. Se nenhum e-mail correspondente for encontrado, uma resposta de erro apropriada é fornecida.

Nota: substitua a variável API_KEY pela chave da sua conta no Mailgun.

Para testar a implementação, execute uvicorn main:app –reload e abra http://localhost:8000/login. Clique em “Esqueceu a senha?” link:

Forgot Password Link Image

Insira um e-mail presente no seu arquivo users.json e clique em “Redefinir senha”:

Forgot Password Reset Image

Se for bem-sucedido, você deverá ser direcionado de volta para a página de login, onde receberá instruções para verificar seu e-mail. Você deverá ver o seguinte e-mail na caixa de entrada de e-mail do destinatário:

Reset Password Request Image

Integrando com eventos do aplicativo

Integrando com eventos do aplicativo usando webhooks permite que seu sistema responda automaticamente a atualizações em tempo real de serviços externos.

Um webhook é essencialmente um HTTP callback. Sempre que ocorre um evento específico em um aplicativo externo (como uma confirmação de pagamento, inscrição do usuário ou solicitação para redefinir a senha), o serviço envia uma requisição para a sua URL do webhook predefinida. Isso possibilita uma automação perfeita, reduzindo a necessidade de intervenção manual ou de consultas periódicas. Ao configurar seu aplicativo para escutar esses eventos de webhook, você pode acionar ações relevantes, como atualizar um banco de dados, enviar notificações ou processar transações, assim que o evento acontecer.

Para integrar webhooks com o Mailgun, você precisa criar um endpoint. Para fazer isso, abra o arquivo main.py e cole o seguinte código no final:

                                

                                    @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
                                
                            

Volte para o painel e acesse “Enviar” > “Envio” > “Webhooks”:

Add Webhooks Image

Clique em “Adicionar webhook” no canto superior direito. Na lista suspensa de tipos de evento, selecione “Mensagens entregues” e, no campo URL, insira a rota para a sua URL do webhook. Nesse caso, é https:///webhooks/password-reset. Quando terminar, clique em “Criar webhook”:

New Webhook Image

Teste o webhook. O resultado deverá ser semelhante a este:

Test webhook Image

No lado do servidor, você deverá receber a seguinte mensagem:

E-mail para redefinir a senha clicado: {'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'}}}

Isso pode mudar dependendo do e-mail que está sendo enviado.

Monitorando e gerenciando e-mails

Peter Drucker, um famoso consultor de gestão, disse uma vez:

Se você não pode medir, não pode melhorar.

Em sintonia com isso, o Mailgun fornece ferramentas para verificar o desempenho dos e-mails enviados. Por exemplo, a página “Enviar” > “Envio” > “Análises” ajuda a medir qual a porcentagem de e-mails que estão sendo entregues, abertos e clicados:

Analytics Image

Na página “Enviar” > “Relatórios” > “Métricas”, você pode obter informações detalhadas sobre o desempenho dos seus e-mails:

Metrics image

Você também pode escolher as métricas que deseja ver em um determinado período:

Customized Metrics Image

O Mailgun também fornece logs caso você queira se aprofundar nos eventos entregues e investigar falhas quando elas ocorrerem:

Logs Image

Por último, o Mailgun fornece uma classificação de devolução para ver quantos dos seus e-mails não foram entregues. Ele também informa quantas dessas devoluções são críticas:

Bounce Classification Image

Conclusão

Neste tutorial, você aprendeu como criar um fluxo de trabalho de e-mail transacional completo para redefinir senhas usando a API do Mailgun. Após configurar uma conta no Mailgun e obter uma chave de API, você criou uma interface de aplicativo usando o FastAPI. Em seguida, você desenhou e configurou um modelo de e-mail, implementou a funcionalidade de envio de e-mail e integrou webhooks para o rastreamento de eventos em tempo real.

As operações de e-mail transacional são essenciais para fornecer uma experiência do usuário perfeita e segura, especialmente para redefinir senhas. O Mailgun pode ajudá-lo a automatizar esse processo, melhorando a segurança e a produtividade enquanto elimina a intervenção manual. Implementar essa abordagem em seus projetos não apenas aumentará a satisfação do cliente, mas também ajudará a manter um sistema de autenticação confiável.