-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Feature: Implement Mailgun Email Service via Kafka
Problem
The FluentMeet application needs to send transactional emails for user account verification, password reset, and other notifications. Currently, no email service is integrated. Directly calling a third-party email API synchronously inside request handlers would increase latency and couple the request lifecycle to an external service, creating a poor user experience if the provider is slow or unavailable.
Proposed Solution
Integrate Mailgun as the email provider and decouple email sending from the HTTP request lifecycle using Apache Kafka. When an email needs to be sent, the application will publish a structured message to a Kafka topic (notifications.email). A dedicated consumer worker will pick up the message and dispatch it via the Mailgun REST API. This approach makes email sending asynchronous, resilient, and independently scalable.
User Stories
- As a new user, I want to receive a verification email immediately after signing up, so I can activate my account without experiencing delays in the registration response.
- As a user, I want to receive a password reset email when I request one, so I can regain access to my account.
- As a developer, I want a reusable, Kafka-backed email service so that any part of the system can trigger an email without being blocked by the Mailgun API call.
- As a DevOps engineer, I want email failures to be retried automatically and logged clearly, so transient Mailgun outages don't result in silently dropped emails.
Acceptance Criteria
- A
Mailgunconfiguration block (API key, domain, sender address) is defined inapp/core/config.pyand sourced from environment variables — never hardcoded. - A Kafka topic
notifications.emailis created and documented in the infrastructure setup. - An
EmailProducerServiceis implemented with asend_email(to, subject, html_body, template_data)method that publishes a structured JSON message to thenotifications.emailKafka topic. - An
EmailConsumerWorkeris implemented to:- Consume messages from the
notifications.emailtopic. - Call the Mailgun REST API (
/messages) to deliver the email. - Log success and failure outcomes.
- Handle retries on transient failures using Kafka consumer group offsets.
- Consume messages from the
- Email templates are implemented for:
- Account Verification: Contains the verification link.
- Password Reset: Contains the time-limited reset link.
- The
EmailProducerServiceis injected into and called from the user registration and password reset flows. - Unit tests verify that the producer publishes the correct message payload to the Kafka topic.
- Integration tests verify the full flow: producer publishes → consumer dispatches → Mailgun API is called.
Proposed Technical Details
- Mailgun SDK: Use the
mailgun2library (already inrequirements.txt) or directhttpxcalls to the Mailgun/messagesendpoint. - Kafka Topic:
notifications.email— messages follow a standard envelope:{ "to": "user@example.com", "subject": "Verify your FluentMeet account", "template": "verification", "data": { "verification_link": "https://..." } } - Producer:
app/services/email_producer.py— usesaiokafka.AIOKafkaProducerto publish messages asynchronously. - Consumer Worker:
app/services/email_consumer.py— long-runningaiokafka.AIOKafkaConsumerin a background task, started via FastAPIlifespanevents. - Templates: Jinja2 HTML templates stored in
app/templates/email/(e.g.,verification.html,password_reset.html). - Config: New fields in
app/core/config.py:MAILGUN_API_KEY: str MAILGUN_DOMAIN: str MAILGUN_FROM_ADDRESS: str = "no-reply@fluentmeet.com"
Tasks
- Add
MAILGUN_API_KEY,MAILGUN_DOMAIN, andMAILGUN_FROM_ADDRESSto.env.exampleandapp/core/config.py. - Create the
notifications.emailKafka topic and document it ininfra/. - Implement
EmailProducerServiceinapp/services/email_producer.py. - Implement
EmailConsumerWorkerinapp/services/email_consumer.py. - Register the consumer as a background task in the FastAPI
lifespancontext manager inapp/main.py. - Create Jinja2 HTML templates for verification and password reset emails.
- Integrate the email producer into the user registration endpoint (
POST /api/v1/auth/signup). - Integrate the email producer into the password reset endpoint (
POST /api/v1/auth/forgot-password). - Write unit tests for the
EmailProducerService(mock the Kafka producer). - Write integration tests for the full consumer → Mailgun dispatch flow (mock the Mailgun API).
Open Questions/Considerations
- What is the retry strategy for failed Mailgun deliveries — dead-letter queue or fixed retry count?
- Should email sending failures be surfaced to the user (e.g., "email failed to send, please try again") or handled silently with a background retry?
- What is the Kafka consumer group ID for the email worker, and how should it be managed across deployments?
- Should we implement a resend-verification endpoint for users whose verification tokens have expired?