Dev Life
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:

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

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

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

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

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 backendjinja2, que serve seus modelos de frontendrequests, 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:

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

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

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

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

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

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

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:

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:

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

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:

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

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

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

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:

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

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

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

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:

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.