{"id":19934,"date":"2026-09-14T18:33:05","date_gmt":"2026-09-14T18:33:05","guid":{"rendered":"https:\/\/www.mailgun.com\/blog\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/"},"modified":"2026-09-14T18:33:06","modified_gmt":"2026-09-14T18:33:06","slug":"como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas","status":"publish","type":"blog","link":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/","title":{"rendered":"Creaci\u00f3n de flujos de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/mailchimp.com\/marketing-glossary\/transactional-email\/\" target=\"_tabs\" rel=\"noopener noreferrer\">Emails transaccionales<\/a> son emails automatizados activados por acciones de los usuarios en un sitio web, una aplicaci\u00f3n o un servicio. A diferencia de <a href=\"https:\/\/www.brevo.com\/blog\/what-is-email-marketing\/\" target=\"_tabs\" rel=\"noopener noreferrer\">emails de marketing<\/a>, que promocionan productos o servicios, los emails transaccionales ofrecen informaci\u00f3n fundamental, a menudo en tiempo real.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Los flujos de trabajo de emails transaccionales van un paso m\u00e1s all\u00e1 y automatizan una secuencia de emails a partir de las acciones de los usuarios para garantizar una comunicaci\u00f3n oportuna y una buena experiencia de usuario. Las empresas conf\u00edan en servicios como <a href=\"https:\/\/www.mailgun.com\/es\/\" target=\"_tabs\" rel=\"noopener noreferrer\">Mailgun<\/a> para sus emails transaccionales porque son r\u00e1pidos, relevantes y se activan mediante acciones inmediatas de los usuarios. Por ejemplo, el flujo de trabajo permite a los usuarios restablecer r\u00e1pidamente su contrase\u00f1a y recuperar el acceso a su cuenta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En este tutorial, descubrir\u00e1s c\u00f3mo crear un flujo de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun.<\/p>\n\n\n\r\n    <nav data-content-type=\"longform\" class=\"toc-block longform-spacings px-5 py-6 px-md-6 px-lg-7 py-md-7 bg-light fs-sm rounded-lg\" aria-labelledby=\"toc-title-2752\"><p class=\"h5 m-0\" id=\"toc-title-2752\">\u00cdndice<\/p><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">01<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#configurar-una-cuenta-de-mailgun\">Configurar una cuenta de Mailgun<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">02<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#obtencion-de-una-clave-de-api\">Obtenci\u00f3n de una clave de API<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">03<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#creacion-de-la-interfaz-de-la-aplicacion-con-fastapi\">Creaci\u00f3n de la interfaz de la aplicaci\u00f3n con FastAPI<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">04<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#configuracion-de-la-conexion-a-mailgun\">Configuraci\u00f3n de la conexi\u00f3n a Mailgun<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">05<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#diseno-y-configuracion-de-la-plantilla-de-email\">Dise\u00f1o y configuraci\u00f3n de la plantilla de email<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">06<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#implementacion-de-la-funcionalidad-de-envio-de-emails\">Implementaci\u00f3n de la funcionalidad de env\u00edo de emails<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">07<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#integracion-con-eventos-de-aplicaciones\">Integraci\u00f3n con eventos de aplicaciones<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">08<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#seguimiento-y-gestion-de-emails\">Seguimiento y gesti\u00f3n de emails<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">09<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#en-resumen\">En resumen<\/a><\/div><\/div><\/nav>\n\n\n<h2 class=\"wp-block-heading\">Configurar una cuenta de Mailgun<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Si a\u00fan no tienes una cuenta de Mailgun, lo primero que debes hacer es <a href=\"https:\/\/signup.mailgun.com\/new\/signup\" target=\"_tabs\" rel=\"noopener noreferrer\">crear una<\/a>. Aseg\u00farate de revisar el email asociado a tu cuenta de Mailgun y de verificar tu cuenta:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3961\" width=\"888\" height=\"572\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/1__1_.png\" alt=\"Account Verification Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/1__1_.png 888w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/1__1_-300x193.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/1__1_-768x495.png 768w\" sizes=\"(max-width: 888px) 100vw, 888px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A continuaci\u00f3n, introduce tu n\u00famero de tel\u00e9fono y el c\u00f3digo de autorizaci\u00f3n proporcionado para activar tu cuenta:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3963\" width=\"1348\" height=\"502\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/2__1_.png\" alt=\"Account Verification Phone Number image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/2__1_.png 1348w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/2__1_-300x112.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/2__1_-768x286.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/2__1_-1024x381.png 1024w\" sizes=\"(max-width: 1348px) 100vw, 1348px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Una vez configurada tu cuenta de Mailgun, llega el momento de obtener una clave de API para empezar a utilizar el servicio.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Obtenci\u00f3n de una clave de API<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para que tu aplicaci\u00f3n interact\u00fae con los servicios de Mailgun, es necesario autenticarla a trav\u00e9s de una clave de API. Para conseguir tu clave de API, ve al panel de control de Mailgun y selecciona <b>Get started<\/b> a la izquierda para consultar la gu\u00eda <b>Get started guide<\/b>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3964\" width=\"1554\" height=\"688\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/3__1_.png\" alt=\"API Get Started Guide Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/3__1_.png 1554w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/3__1_-300x133.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/3__1_-768x340.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/3__1_-1024x453.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/3__1_-1536x680.png 1536w\" sizes=\"(max-width: 1554px) 100vw, 1554px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Haz clic en el bot\u00f3n <b>Get started<\/b> que aparece bajo <b>Create an API Key<\/b>. A continuaci\u00f3n, incluye una descripci\u00f3n que refleje bien el prop\u00f3sito de la clave de la API. Por ejemplo, si la clave de API es para procesos de autenticaci\u00f3n de usuarios, puedes llamarla algo como user_authentication y hacer clic en <b>Create Key<\/b>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3969\" width=\"1536\" height=\"656\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/4__2_.png\" alt=\"Create New API Key Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/4__2_.png 1536w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/4__2_-300x128.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/4__2_-768x328.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/4__2_-1024x437.png 1024w\" sizes=\"(max-width: 1536px) 100vw, 1536px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Aseg\u00farate de copiar y guardar esta clave en un lugar seguro, ya que esta es la \u00fanica vez que se mostrar\u00e1:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3973\" width=\"1540\" height=\"678\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/5__2_.png\" alt=\"New API Key Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/5__2_.png 1540w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/5__2_-300x132.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/5__2_-768x338.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/5__2_-1024x451.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/5__2_-1536x676.png 1536w\" sizes=\"(max-width: 1540px) 100vw, 1540px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Creaci\u00f3n de la interfaz de la aplicaci\u00f3n con FastAPI<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para crear la interfaz de la aplicaci\u00f3n que procesa el flujo de trabajo de los emails, lo primero que debes hacer es instalar las bibliotecas necesarias. Antes de hacerlo, crea un directorio de proyecto ejecutando <code>mkdir my_fastapi_app<\/code> y pon en marcha un <a href=\"https:\/\/www.freecodecamp.org\/news\/how-to-setup-virtual-environments-in-python\/\" target=\"_tabs\" rel=\"noopener noreferrer\">entorno virtual<\/a> en el directorio.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Despu\u00e9s, instala las bibliotecas necesarias con el comando siguiente:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>pip install fastapi jinja2 requests uvicorn python-multipart<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aqu\u00ed debes instalar lo siguiente:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>fastapi<\/code>, que sirve como el principal framework de backend<\/li>\n\n\n\n<li><code>jinja2<\/code>, que proporciona las plantillas de frontend<\/li>\n\n\n\n<li><code>requests<\/code>, que env\u00eda peticiones HTTP a la API de Mailgun<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Aunque FastAPI sirve sobre todo para crear API, la incorporaci\u00f3n de la biblioteca <code>jinja2<\/code> permite el desarrollo full-stack, pero requiere una configuraci\u00f3n adecuada de los directorios. La estructura de tu proyecto debe seguir este formato:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>my_fastapi_app\/<br>\n\u2502\u2500\u2500 main.py # Archivo principal de la aplicaci\u00f3n FastAPI<br>\n\u2502\u2500\u2500 users.json # Archivo JSON donde se guardan los datos de los usuarios<br>\n\u2502\u2500\u2500 templates\/ # Carpeta de plantillas HTML<br>\n\u2502 \u251c\u2500\u2500 login.html # P\u00e1gina de inicio de sesi\u00f3n<br>\n\u2502 \u251c\u2500\u2500 home.html # P\u00e1gina de inicio<br>\n\u2502 \u251c\u2500\u2500 passwordReset.html # P\u00e1gina para restablecer la contrase\u00f1a<br>\n\u2502\u2500\u2500 static\/ # Carpeta de archivos est\u00e1ticos<br>\n\u2502 \u251c\u2500\u2500 styles.css # Estilos para los archivos login.html y passwordReset.html<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Puedes encontrar todo el c\u00f3digo de este tutorial en <a href=\"https:\/\/github.com\/EphraimX\/building-transactional-email-workflows-for-password-resets-with-mailgun-api\" target=\"_tabs\" rel=\"noopener noreferrer\">este repositorio de GitHub<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una vez definida la estructura del proyecto, puedes copiar y pegar el c\u00f3digo en los archivos correspondientes o bien clonar el anterior repositorio de GitHub con el siguiente comando:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>git clone https:\/\/github.com\/EphraimX\/building-transactional-email-workflows-for-password-resets-with-mailgun-api.git<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Veamos la primera secci\u00f3n del archivo main.py. En este archivo es donde sucede toda la magia, ya que conecta las operaciones del frontend y del backend:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copia al portapapeles\" data-clipboard-success-label=\"\u00a1Copiado!\" data-clipboard-error-label=\"No se ha podido copiar\" data-tooltip=\"Copia al portapapeles\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copia al portapapeles\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    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(&quot;\/static&quot;, StaticFiles(directory=&quot;static&quot;), name=&quot;static&quot;)rntemplates = Jinja2Templates(directory=&quot;templates&quot;)rnrnclass loginData(BaseModel):rn    username: strrn    password: strrnrn@app.get(&quot;\/login&quot;, response_class=HTMLResponse)rnasync def login(request: Request):rn    return templates.TemplateResponse(&quot;login.html&quot;, {&quot;request&quot;: request, &quot;message&quot;: &quot;&quot;})rnrn@app.get(&quot;\/passwordResetView\/&quot;, response_class=HTMLResponse)rnasync def password_reset_view(request: Request):rn    return templates.TemplateResponse(rn        &quot;passwordReset.html&quot;, {&quot;request&quot;: request, &quot;message&quot;: &quot;&quot;}rn    )rnrn@app.post(&quot;\/home&quot;, 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(&quot;users.json&quot;, &quot;r&quot;) as file:rn            users = json.load(file)rn    except (FileNotFoundError, json.JSONDecodeError):rn        users = []rnrn    for user in users:rnrn        if user[&quot;email_address&quot;] == email_address and user[&quot;password&quot;] == password:rn            return templates.TemplateResponse(&quot;home.html&quot;, {&quot;request&quot;: request})rnrn    # If no match was found, return an error messagern    return templates.TemplateResponse(rn        &quot;login.html&quot;,rn        {rn            &quot;request&quot;: request,rn            &quot;message&quot;: &quot;Email or Password Incorrect. If you cannot remember your password, kindly reset it.&quot;,rn        },rn    )rn\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">En este c\u00f3digo, la aplicaci\u00f3n gestiona la autenticaci\u00f3n mostrando las p\u00e1ginas de inicio de sesi\u00f3n y de restablecer contrase\u00f1as, al tiempo que comprueba las credenciales en <code>users.json<\/code>. La aplicaci\u00f3n inicializa FastAPI, configura las plantillas y define un modelo loginData para la validaci\u00f3n. Las rutas <code>\/login <\/code> y <code>\/passwordResetView\/ <\/code> ofrecen sus respectivas p\u00e1ginas, mientras que \/home comprueba las credenciales, redirige a los usuarios v\u00e1lidos o muestra los errores correspondientes. La funci\u00f3n de restablecer contrase\u00f1as genera un enlace \u00fanico mediante uuid y lo env\u00eda a trav\u00e9s de la API de Mailgun.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para probarlo, abre tu base de datos provisional (<code>users.json<\/code>) y pega lo siguiente:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copia al portapapeles\" data-clipboard-success-label=\"\u00a1Copiado!\" data-clipboard-error-label=\"No se ha podido copiar\" data-tooltip=\"Copia al portapapeles\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copia al portapapeles\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    [rn    {rn        &quot;username&quot; : &quot;sinchy&quot;,rn        &quot;email_address&quot; : &quot;sinch@gmail.com&quot;,rn        &quot;password&quot; : &quot;sinch12345&quot;rn    },rn    {rn        &quot;username&quot; : &quot;grinchy&quot;,rn        &quot;email_address&quot; : &quot;rinch@gmail.com&quot;,rn        &quot;password&quot; : &quot;grinch67890&quot;rn    }rn]\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Tambi\u00e9n debes <a href=\"https:\/\/help.mailgun.com\/hc\/en-us\/articles\/217531258-Authorized-Recipients\" target=\"_tabs\" rel=\"noopener noreferrer\">autorizar<\/a> estas direcciones de email a trav\u00e9s del panel de control de Mailgun si vas a usar un dominio sandbox.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Inicia la aplicaci\u00f3n ejecutando el comando uvicorn main:app &#8211;reload. A continuaci\u00f3n, ve a <a href=\"http:\/\/localhost:8000\/login\" target=\"_tabs\" rel=\"noopener noreferrer\">http:\/\/localhost:8000\/login<\/a>, donde deber\u00edas ver esto:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3979\" width=\"1536\" height=\"718\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/6__2_.png\" alt=\"API Login Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/6__2_.png 1536w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/6__2_-300x140.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/6__2_-768x359.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/6__2_-1024x479.png 1024w\" sizes=\"(max-width: 1536px) 100vw, 1536px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Si intentas iniciar sesi\u00f3n con alguna de las credenciales del archivo users.json, acceder\u00e1s a la p\u00e1gina de inicio:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3981\" width=\"1538\" height=\"716\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/7__1_.png\" alt=\"Successful API Login Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/7__1_.png 1538w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/7__1_-300x140.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/7__1_-768x358.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/7__1_-1024x477.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/7__1_-1536x715.png 1536w\" sizes=\"(max-width: 1538px) 100vw, 1538px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Si introduces una informaci\u00f3n de inicio de sesi\u00f3n incorrecta, ver\u00e1s lo siguiente:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3982\" width=\"1540\" height=\"716\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/8__1_.png\" alt=\"Unsuccessful API Login Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/8__1_.png 1540w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/8__1_-300x139.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/8__1_-768x357.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/8__1_-1024x476.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/8__1_-1536x714.png 1536w\" sizes=\"(max-width: 1540px) 100vw, 1540px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Configuraci\u00f3n de la conexi\u00f3n a Mailgun<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para enviar emails con Mailgun, es preciso establecer una conexi\u00f3n entre la aplicaci\u00f3n y el servicio de env\u00edo de emails de Mailgun.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para ello, abre main.py y pega el c\u00f3digo siguiente, pero cambia <code><\/code>, <code><\/code> y  por valores que sean v\u00e1lidos:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copia al portapapeles\" data-clipboard-success-label=\"\u00a1Copiado!\" data-clipboard-error-label=\"No se ha podido copiar\" data-tooltip=\"Copia al portapapeles\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copia al portapapeles\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    def send_simple_message(API_KEY):rn    response = requests.post(rn        &quot;https:\/\/api.mailgun.net\/v3\/&lt;SANDBOX_URL&gt;\/messages&quot;,rn        auth=(&quot;api&quot;, f&quot;{API_KEY}&quot;),rn        data={&quot;from&quot;: &quot;Mailgun Sandbox &lt;postmaster@&lt;SANDBOX_URL&gt;&gt;&quot;,rn              &quot;to&quot;: &quot;&lt;RECIPIENT_NAME&gt; &lt;RECIPIENT_EMAIL&gt;&quot;,rn              &quot;subject&quot;: &quot;Hello &lt;RECIPIENT_NAME&gt;&quot;,rn              &quot;text&quot;: &quot;Congratulations &lt;RECIPIENT_NAME&gt;, you just sent an email with Mailgun! You are truly awesome!&quot;rn              }rn    )rnrn    print(response.json())rn    return responsern\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Para realizar pruebas, pasa tu clave de API directamente al llamar a la funci\u00f3n:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>send_simple_message(\"your-api-key-here\")<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pon en marcha el script ejecutando lo siguiente:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>python main.py<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Si todo ha ido bien, la funci\u00f3n imprimir\u00e1 una respuesta similar a esta:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>{<br>\n\"id\": \"\",<br>\n\"message\": \"Queued. Thank you.\"<br>\n}<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Esto confirma que la solicitud de email se ha puesto en la cola correctamente mediante Mailgun.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Dise\u00f1o y configuraci\u00f3n de la plantilla de email<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para trabajar en la l\u00f3gica para restablecer contrase\u00f1as, tienes que dise\u00f1ar la plantilla del email que se enviar\u00e1 al usuario. Mailgun ofrece dos formas de dise\u00f1ar un email: en HTML o con el creador de plantillas de arrastrar y soltar de Mailgun. Aqu\u00ed usar\u00e1s el enfoque de HTML.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para empezar con el dise\u00f1o, entra en el panel de control de Mailgun y ve a <b>Send &gt; Sending &gt; Templates<\/b>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3985\" width=\"1532\" height=\"678\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/9__1_.png\" alt=\"Templates Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/9__1_.png 1532w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/9__1_-300x133.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/9__1_-768x340.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/9__1_-1024x453.png 1024w\" sizes=\"(max-width: 1532px) 100vw, 1532px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Despu\u00e9s, haz clic en <b>Create message template<\/b>, selecciona la opci\u00f3n para programarlo en HTML y haz clic en la plantilla en blanco (<b>Blank<\/b>):<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3989\" width=\"1532\" height=\"648\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/10.png\" alt=\"Blank Option image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/10.png 1532w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/10-300x127.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/10-768x325.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/10-1024x433.png 1024w\" sizes=\"(max-width: 1532px) 100vw, 1532px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Rellena el formulario de la plantilla con el nombre, la descripci\u00f3n y los detalles del email:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3995\" width=\"1570\" height=\"682\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/11.png\" alt=\"Template Details image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/11.png 1570w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/11-300x130.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/11-768x334.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/11-1024x445.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/11-1536x667.png 1536w\" sizes=\"(max-width: 1570px) 100vw, 1570px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A continuaci\u00f3n, despl\u00e1zate hasta la pesta\u00f1a <b>Editor<\/b> y copia y pega el c\u00f3digo del archivo  <a href=\"https:\/\/github.com\/EphraimX\/building-transactional-email-workflows-for-password-resets-with-mailgun-api\/blob\/main\/building-transactional-email-workflows-for-password-resets-with-mailgun-api\/email_template.html\" target=\"_tabs\" rel=\"noopener noreferrer\">email_template.html<\/a> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-3998\" width=\"1560\" height=\"710\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/12.png\" alt=\"Template Editor Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/12.png 1560w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/12-300x137.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/12-768x350.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/12-1024x466.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/12-1536x699.png 1536w\" sizes=\"(max-width: 1560px) 100vw, 1560px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Al seleccionar la pesta\u00f1a <b>Test Data<\/b>, ver\u00e1s dos variables din\u00e1micas: <code>username<\/code> y <code>reset_link<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Selecciona la pesta\u00f1a <b>Preview<\/b> para ver la plantilla:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4005\" width=\"1550\" height=\"768\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/13.png\" alt=\"Reset Password Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/13.png 1550w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/13-300x149.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/13-768x381.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/13-1024x507.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/13-1536x761.png 1536w\" sizes=\"(max-width: 1550px) 100vw, 1550px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Por \u00faltimo, haz clic en el bot\u00f3n <b>Create<\/b> para crearla.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementaci\u00f3n de la funcionalidad de env\u00edo de emails<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Cuando la plantilla de email est\u00e9 lista, llegar\u00e1 el momento de crear la funci\u00f3n de env\u00edo de emails. Abre el archivo <code>main.py<\/code> y pega el siguiente c\u00f3digo:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copia al portapapeles\" data-clipboard-success-label=\"\u00a1Copiado!\" data-clipboard-error-label=\"No se ha podido copiar\" data-tooltip=\"Copia al portapapeles\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copia al portapapeles\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    @app.post(&quot;\/resetPassword\/&quot;)rnasync def reset_password(request: Request, email_address: str = Form(...)):rnrn    # Open and read the JSON DB filern    try:rn        with open(&quot;users.json&quot;, &quot;r&quot;) as file:rn            users = json.load(file)rn    except (FileNotFoundError, json.JSONDecodeError):rn        users = []rnrn    for user in users:rn        if user[&quot;email_address&quot;] == email_address:rnrn            email_address = user[&quot;email_address&quot;]rn            username = user[&quot;username&quot;]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[&quot;success&quot;]:rnrn                return templates.TemplateResponse(rn                    &quot;login.html&quot;,rn                    {rn                        &quot;request&quot;: request,rn                        &quot;message&quot;: &quot;Kindly check your email to reset your password.&quot;,rn                    },rn                )rnrn            else:rnrn                return templates.TemplateResponse(rn                    &quot;passwordReset.html&quot;,rn                    {rn                        &quot;request&quot;: request,rn                        &quot;message&quot;: &quot;Unfortunately, we ran into an error while trying to reset your password. Kindly try again, and if the issue persists, please contact support.&quot;,rn                    },rn                )rnrn    # If no match was found, return an error messagern    return templates.TemplateResponse(rn        &quot;passwordReset.html&quot;,rn        {rn            &quot;request&quot;: request,rn            &quot;message&quot;: &quot;Unfortunately, we do not have a record of your email. Kindly reach out to the site administrator.&quot;,rn        },rn    )rnrnasync def send_password_reset_email(username, email_address, reset_link):rnrn    API_KEY = os.getenv(&quot;API_KEY&quot;)  # Fetch API key from environmentrnrn    if not API_KEY:rn        print(&quot;Error: API_KEY is not set!&quot;)rn        return {&quot;success&quot;: False, &quot;error&quot;: &quot;API key is missing&quot;}rnrn    try:rn        response = requests.post(rn            &quot;https:\/\/api.mailgun.net\/v3\/&lt;SANDBOX_URL&gt;\/messages&quot;,rn            auth=(&quot;api&quot;, API_KEY),rn            data={rn                &quot;from&quot;: &quot;Mailgun Sandbox &lt;postmaster@&lt;SANDBOX_URL&gt;&gt;&quot;,rn                &quot;to&quot;: f&quot;{username} &lt;{email_address}&gt;&quot;,rn                &quot;subject&quot;: f&quot;Hello {username}&quot;,rn                &quot;template&quot;: &quot;&lt;EMAIL_TEMPLATE_NAME&gt;&quot;,rn                &quot;h:X-Mailgun-Variables&quot;: json.dumps(rn                    {&quot;reset_link&quot;: reset_link, &quot;username&quot;: username}rn                ),rn            },rn        )rnrn        if response.status_code == 200:rn            print(f&quot;Password reset email sent successfully to {email_address}&quot;)rn            return {&quot;success&quot;: True, &quot;message&quot;: &quot;Email sent successfully&quot;}rn        else:rn            print(rn                f&quot;Failed to send email. Status Code: {response.status_code}, Response: {response.text}&quot;rn            )rn            return {&quot;success&quot;: False, &quot;error&quot;: response.text}rnrn    except requests.exceptions.RequestException as e:rn        print(f&quot;Request failed: {str(e)}&quot;)rn        return {&quot;success&quot;: False, &quot;error&quot;: str(e)}rnrnasync def generate_password_reset_link(rn    email_address, base_url=&quot;https:\/\/mailgunny.com\/reset-password&quot;rn):rn    token = uuid.uuid4()rn    encoded_email = urllib.parse.quote(email_address)rn    return f&quot;{base_url}?email={encoded_email}&amp;token={token}&quot;rn\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">En este c\u00f3digo, la funci\u00f3n <code>reset_password<\/code> (<code>@app.post(\"\/resetPassword\/\")<\/code>) procesa las solicitudes para restablecer contrase\u00f1as comprobando si el email enviado figura en la base de datos de <code>users.json<\/code>. Si es as\u00ed, genera un enlace de restablecimiento \u00fanico mediante <code>generate_password_reset_link(email_address) <\/code> y env\u00eda el email para restablecer la contrase\u00f1a a trav\u00e9s de <code>send_password_reset_email(username, email_address, reset_link)<\/code>. A continuaci\u00f3n, la funci\u00f3n devuelve un mensaje de \u00e9xito si el email se ha enviado o bien muestra un mensaje de error si no es as\u00ed. Si no se encuentra ning\u00fan email coincidente, se devuelve la respuesta de error correspondiente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><b>Nota:<\/b> Sustituye la variable <code>API_KEY<\/code> por la clave de tu cuenta de Mailgun.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para probar la implementaci\u00f3n, ejecuta <code>uvicorn main:app<\/code> &#8211;reload y abre <a href=\"http:\/\/localhost:8000\/login\" target=\"_tabs\" rel=\"noopener noreferrer\">http:\/\/localhost:8000\/login<\/a>. Haz clic en el enlace <b>Forgot Password?<\/b> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4013\" width=\"1538\" height=\"628\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/14.png\" alt=\"Forgot Password Link Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/14.png 1538w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/14-300x122.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/14-768x314.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/14-1024x418.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/14-1536x627.png 1536w\" sizes=\"(max-width: 1538px) 100vw, 1538px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Introduce un email que se encuentre en tu archivo <code>users.json<\/code> y haz clic en <b>Reset Password<\/b>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4017\" width=\"1538\" height=\"628\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/15.png\" alt=\"Forgot Password Reset Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/15.png 1538w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/15-300x122.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/15-768x314.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/15-1024x418.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/15-1536x627.png 1536w\" sizes=\"(max-width: 1538px) 100vw, 1538px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Si va bien, volver\u00e1s a la p\u00e1gina de inicio de sesi\u00f3n, donde ver\u00e1s las instrucciones para revisar tu email. Deber\u00edas ver el siguiente email en la bandeja de entrada del destinatario:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4022\" width=\"1544\" height=\"906\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/16.png\" alt=\"Reset Password Request Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/16.png 1544w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/16-300x176.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/16-768x451.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/16-1024x601.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/16-1536x901.png 1536w\" sizes=\"(max-width: 1544px) 100vw, 1544px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><b>Integraci\u00f3n con eventos de aplicaciones<\/b><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La integraci\u00f3n con los eventos de la aplicaci\u00f3n mediante <a href=\"https:\/\/hookdeck.com\/webhooks\/guides\/what-are-webhooks-how-they-work\" target=\"_tabs\" rel=\"noopener noreferrer\">webhooks<\/a> permite que tu sistema responda de forma autom\u00e1tica a las actualizaciones en tiempo real de servicios externos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En esencia, un webhook es una petici\u00f3n HTTP de  <a href=\"https:\/\/www.adjust.com\/glossary\/callback\/\" target=\"_tabs\" rel=\"noopener noreferrer\">devoluci\u00f3n de llamada<\/a>. Siempre que se produce un evento espec\u00edfico en una aplicaci\u00f3n externa (como la confirmaci\u00f3n de un pago, el registro de un usuario o una solicitud para restablecer contrase\u00f1as), el servicio env\u00eda una petici\u00f3n a tu URL de webhook predefinida. De este modo se logra una automatizaci\u00f3n sin fisuras que reduce la necesidad de intervenci\u00f3n manual o de sondeos peri\u00f3dicos. Al configurar tu aplicaci\u00f3n para que intercepte estos eventos de webhook, puedes activar acciones pertinentes como actualizar una base de datos, enviar notificaciones o procesar transacciones en el instante en que se produzca el evento.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para integrar los webhooks con Mailgun, tienes que crear un punto de conexi\u00f3n. Para ello, abre el archivo main.py y pega el c\u00f3digo siguiente al final:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copia al portapapeles\" data-clipboard-success-label=\"\u00a1Copiado!\" data-clipboard-error-label=\"No se ha podido copiar\" data-tooltip=\"Copia al portapapeles\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copia al portapapeles\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    @app.post(&quot;\/webhooks\/password-reset&quot;)rnasync def handle_webhook(request: Request):rn    data = await request.json()rn    print(f&quot;Password reset email clicked: {data}&quot;)rn    return {&quot;status&quot;: &quot;received&quot;, &quot;status_code&quot;: 200}rn\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Vuelve al panel de control y dir\u00edgete a <b>Send &gt; Sending &gt; Webhooks<\/b>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4029\" width=\"1546\" height=\"692\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/17.png\" alt=\"Add Webhooks Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/17.png 1546w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/17-300x134.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/17-768x344.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/17-1024x458.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/17-1536x688.png 1536w\" sizes=\"(max-width: 1546px) 100vw, 1546px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Haz clic en <b>Add webhook<\/b> en la esquina superior derecha. En la lista desplegable de tipos de eventos, selecciona <b>Delivered Messages<\/b>, y en el campo <b>URL<\/b>, introduce la ruta a tu URL del webhook. En este caso, se trata de https:\/\/\/webhooks\/password-reset. Al terminar, haz clic en <b>Create webhook<\/b>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4031\" width=\"1538\" height=\"682\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/18.png\" alt=\"New Webhook Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/18.png 1538w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/18-300x133.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/18-768x341.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/18-1024x454.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/18-1536x681.png 1536w\" sizes=\"(max-width: 1538px) 100vw, 1538px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Prueba el webhook. El resultado deber\u00eda tener este aspecto:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4032\" width=\"1554\" height=\"1064\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/19.png\" alt=\"Test webhook Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/19.png 1554w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/19-300x205.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/19-768x526.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/19-1024x701.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/19-1536x1052.png 1536w\" sizes=\"(max-width: 1554px) 100vw, 1554px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">En el lado del servidor, tendr\u00edas que recibir el siguiente mensaje:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>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'}}}<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Esto puede variar en funci\u00f3n del email que se env\u00ede.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Seguimiento y gesti\u00f3n de emails<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/drucker.institute\/about-peter-drucker\/\" target=\"_tabs\" rel=\"noopener noreferrer\">Peter Drucker<\/a>, un famoso consultor de gesti\u00f3n, dijo una vez:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo que no se puede medir, no se puede mejorar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En este sentido, Mailgun ofrece herramientas para comprobar el rendimiento de los emails enviados. Por ejemplo, la p\u00e1gina <b>Send &gt; Sending &gt; Analytics<\/b> ayuda a medir qu\u00e9 porcentaje de emails se est\u00e1n entregando, abriendo y recibiendo clics:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4035\" width=\"1540\" height=\"696\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/20.png\" alt=\"Analytics Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/20.png 1540w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/20-300x136.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/20-768x347.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/20-1024x463.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/20-1536x694.png 1536w\" sizes=\"(max-width: 1540px) 100vw, 1540px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">En la p\u00e1gina <b>Send &gt; Reporting &gt; Metrics<\/b>, puedes consultar informaci\u00f3n detallada sobre el rendimiento de tus emails:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4038\" width=\"1550\" height=\"428\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/21.png\" alt=\"Metrics image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/21.png 1550w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/21-300x83.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/21-768x212.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/21-1024x283.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/21-1536x424.png 1536w\" sizes=\"(max-width: 1550px) 100vw, 1550px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Tambi\u00e9n puedes elegir las m\u00e9tricas que te interesa ver a lo largo de un per\u00edodo determinado:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4040\" width=\"1554\" height=\"802\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/22.png\" alt=\"Customized Metrics Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/22.png 1554w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/22-300x155.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/22-768x396.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/22-1024x528.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/22-1536x793.png 1536w\" sizes=\"(max-width: 1554px) 100vw, 1554px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Mailgun tambi\u00e9n te proporciona registros por si quieres investigar a fondo los eventos entregados y analizar los errores cuando se produzcan:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4041\" width=\"1554\" height=\"430\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/23.png\" alt=\"Logs Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/23.png 1554w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/23-300x83.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/23-768x213.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/23-1024x283.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/23-1536x425.png 1536w\" sizes=\"(max-width: 1554px) 100vw, 1554px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Por \u00faltimo, Mailgun ofrece una clasificaci\u00f3n de los rebotes para que puedas comprobar cu\u00e1ntos de tus emails no llegan a su destino. Tambi\u00e9n te permite saber cu\u00e1ntos de esos rebotes son cr\u00edticos:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4043\" width=\"1550\" height=\"462\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/24.png\" alt=\"Bounce Classification Image\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/24.png 1550w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/24-300x89.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/24-768x229.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/24-1024x305.png 1024w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/24-1536x458.png 1536w\" sizes=\"(max-width: 1550px) 100vw, 1550px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">En resumen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">En este tutorial, has aprendido a crear un flujo de trabajo completo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun. Tras configurar una cuenta de Mailgun y obtener una clave de API, has creado la interfaz de una aplicaci\u00f3n mediante FastAPI. Despu\u00e9s, has dise\u00f1ado y configurado una plantilla de email, has implementado la funci\u00f3n de enviar emails y has integrado webhooks para hacer un seguimiento de los eventos en tiempo real.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Las operaciones de los emails transaccionales son de suma importancia a la hora de proporcionar una experiencia de usuario fluida y segura, sobre todo para restablecer contrase\u00f1as. <u>Mailgun<\/u> puede ayudarte a automatizar este proceso, mejorando la seguridad y la productividad, y acabando con la intervenci\u00f3n manual. La adopci\u00f3n de este enfoque en tus proyectos no solo incrementar\u00e1 la satisfacci\u00f3n de la clientela, sino que tambi\u00e9n contribuir\u00e1 a conservar un sistema de autenticaci\u00f3n fiable.<\/p>\n\n\n\r\n    <aside data-content-type=\"longform\"  class=\"banner-block longform-spacings rounded-lg shadow-lg px-5 py-6 px-md-6 py-md-7 p-lg-7 bg-light\" data-theme=\"dark\" aria-labelledby=\"banner-block-block_c25f6f319690610e1d2aa664c94c3fdd\">\r\n                    <p class=\"text-uppercase section-caption text-body-color\">\r\n                Reg\u00edstrate            <\/p>\r\n                            <p class=\"h4 text-accent fw-bold\" id=\"banner-block-block_c25f6f319690610e1d2aa664c94c3fdd\">\r\n                Empezar es facil\u00edsimo. Y gratis.            <\/p>\r\n                            <div class=\"mb-0 text-body-color\">\r\n                                    <div class=\"content-body mb-0 text-body-color\">Descubre todo lo que puedes lograr con la mejor plataforma de entrega de emails del mundo.<\/div>\r\n                            <\/div>\r\n        \r\n        <div class=\"text-start mt-5\"><a href=\"https:\/\/signup.mailgun.com\/new\/signup\"  class=\"btn btn-secondary\" >Get started<\/a><\/div>\r\n    <\/aside>\r\n\r\n","protected":false},"excerpt":{"rendered":"<p>\u00bfTienes problemas para enviar emails seguros para restablecer contrase\u00f1as? Esta gu\u00eda pr\u00e1ctica te explica paso a paso c\u00f3mo crear un flujo de trabajo de emails fiable y automatizado con la API de Mailgun y FastAPI.\u2026<\/p>\n","protected":false},"author":9,"featured_media":3952,"menu_order":0,"template":"","meta":{"_acf_changed":true,"footnotes":""},"blog_category":[19],"class_list":["post-19934","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog_category-dev-life"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Descubre c\u00f3mo crear un flujo de trabajo de emails para restablecer contrase\u00f1as con la API de Mailgun - Transactional Email API Service For Developers | Mailgun<\/title>\n<meta name=\"description\" content=\"Descubre c\u00f3mo crear un flujo de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun y FastAPI para agilizar la autenticaci\u00f3n y mejorar la experiencia de usuario.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Descubre c\u00f3mo crear un flujo de trabajo de emails para restablecer contrase\u00f1as con la API de Mailgun - Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"og:description\" content=\"Descubre c\u00f3mo crear un flujo de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun y FastAPI para agilizar la autenticaci\u00f3n y mejorar la experiencia de usuario.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/\" \/>\n<meta property=\"og:site_name\" content=\"Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-14T18:33:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png\" \/>\n\t<meta property=\"og:image:width\" content=\"720\" \/>\n\t<meta property=\"og:image:height\" content=\"448\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"12 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\\\/\",\"name\":\"Descubre c\u00f3mo crear un flujo de trabajo de emails para restablecer contrase\u00f1as con la API de Mailgun - Transactional Email API Service For Developers | Mailgun\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-Dev-Life.png\",\"datePublished\":\"2026-09-14T18:33:05+00:00\",\"dateModified\":\"2026-09-14T18:33:06+00:00\",\"description\":\"Descubre c\u00f3mo crear un flujo de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun y FastAPI para agilizar la autenticaci\u00f3n y mejorar la experiencia de usuario.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-Dev-Life.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-Dev-Life.png\",\"width\":720,\"height\":448},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Creaci\u00f3n de flujos de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#website\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"description\":\"Potentes API de email transaccional que te permiten enviar, recibir y hacer seguimiento de emails, creadas pensando en los desarrolladores. \u00a1Descubre m\u00e1s!\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#organization\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"width\":512,\"height\":512,\"caption\":\"Transactional Email API Service For Developers | Mailgun\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Descubre c\u00f3mo crear un flujo de trabajo de emails para restablecer contrase\u00f1as con la API de Mailgun - Transactional Email API Service For Developers | Mailgun","description":"Descubre c\u00f3mo crear un flujo de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun y FastAPI para agilizar la autenticaci\u00f3n y mejorar la experiencia de usuario.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/","og_locale":"es_ES","og_type":"article","og_title":"Descubre c\u00f3mo crear un flujo de trabajo de emails para restablecer contrase\u00f1as con la API de Mailgun - Transactional Email API Service For Developers | Mailgun","og_description":"Descubre c\u00f3mo crear un flujo de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun y FastAPI para agilizar la autenticaci\u00f3n y mejorar la experiencia de usuario.","og_url":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/","og_site_name":"Transactional Email API Service For Developers | Mailgun","article_modified_time":"2026-09-14T18:33:06+00:00","og_image":[{"width":720,"height":448,"url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"12 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/","url":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/","name":"Descubre c\u00f3mo crear un flujo de trabajo de emails para restablecer contrase\u00f1as con la API de Mailgun - Transactional Email API Service For Developers | Mailgun","isPartOf":{"@id":"https:\/\/www.mailgun.com\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/#primaryimage"},"image":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png","datePublished":"2026-09-14T18:33:05+00:00","dateModified":"2026-09-14T18:33:06+00:00","description":"Descubre c\u00f3mo crear un flujo de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun y FastAPI para agilizar la autenticaci\u00f3n y mejorar la experiencia de usuario.","breadcrumb":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/#primaryimage","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png","width":720,"height":448},{"@type":"BreadcrumbList","@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/como-crear-flujos-de-trabajo-de-emails-transaccionales-para-restablecer-contrasenas\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.mailgun.com\/es\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/www.mailgun.com\/es\/blog\/"},{"@type":"ListItem","position":3,"name":"Creaci\u00f3n de flujos de trabajo de emails transaccionales para restablecer contrase\u00f1as con la API de Mailgun"}]},{"@type":"WebSite","@id":"https:\/\/www.mailgun.com\/es\/#website","url":"https:\/\/www.mailgun.com\/es\/","name":"Transactional Email API Service For Developers | Mailgun","description":"Potentes API de email transaccional que te permiten enviar, recibir y hacer seguimiento de emails, creadas pensando en los desarrolladores. \u00a1Descubre m\u00e1s!","publisher":{"@id":"https:\/\/www.mailgun.com\/es\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.mailgun.com\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.mailgun.com\/es\/#organization","name":"Transactional Email API Service For Developers | Mailgun","url":"https:\/\/www.mailgun.com\/es\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.mailgun.com\/es\/#\/schema\/logo\/image\/","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","width":512,"height":512,"caption":"Transactional Email API Service For Developers | Mailgun"},"image":{"@id":"https:\/\/www.mailgun.com\/es\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/19934","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/users\/9"}],"version-history":[{"count":1,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/19934\/revisions"}],"predecessor-version":[{"id":19935,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/19934\/revisions\/19935"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/media\/3952"}],"wp:attachment":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/media?parent=19934"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog_category?post=19934"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}