Files
gatehouse-api/gatehouse_app/services/providers/mailgun_provider.py
T

84 lines
2.7 KiB
Python
Raw Normal View History

"""Mailgun email provider implementation."""
import logging
import requests
from flask import current_app
from gatehouse_app.services.email_provider import EmailMessage, EmailProvider
logger = logging.getLogger(__name__)
class MailgunEmailProvider(EmailProvider):
"""Mailgun API-based email provider implementation."""
# Configuration keys
MAILGUN_API_KEY = "MAILGUN_API_KEY"
MAILGUN_DOMAIN = "MAILGUN_DOMAIN"
MAILGUN_API_URL = "MAILGUN_API_URL"
FROM_ADDRESS = "FROM_ADDRESS"
DEFAULT_API_URL = "https://api.mailgun.net/v3"
def send(self, message: EmailMessage) -> bool:
"""Send an email via Mailgun API.
Args:
message: EmailMessage instance containing email details
Returns:
bool: True if email was sent successfully, False otherwise
"""
api_key = current_app.config.get(self.MAILGUN_API_KEY)
domain = current_app.config.get(self.MAILGUN_DOMAIN)
api_url = current_app.config.get(self.MAILGUN_API_URL, self.DEFAULT_API_URL)
default_from = current_app.config.get(self.FROM_ADDRESS)
missing = [k for k, v in [("MAILGUN_API_KEY", api_key), ("MAILGUN_DOMAIN", domain)] if not v]
if missing:
logger.error(
f"[MAILGUN] Cannot send — missing config: {', '.join(missing)}. "
f"Would have sent to: {message.to} | Subject: {message.subject}"
)
return False
from_address = message.from_address or default_from
if not from_address:
logger.error(
f"[MAILGUN] Cannot send — missing FROM_ADDRESS. "
f"Would have sent to: {message.to} | Subject: {message.subject}"
)
return False
url = f"{api_url}/{domain}/messages"
data = {
"to": message.to,
"subject": message.subject,
"text": message.body,
"from": from_address,
}
if message.html_body:
data["html"] = message.html_body
try:
response = requests.post(
url,
auth=("api", api_key),
data=data,
)
if response.status_code == 200:
logger.info(f"[MAILGUN] Sent to {message.to} | Subject: {message.subject}")
return True
else:
logger.error(
f"[MAILGUN] Failed to send to {message.to}: from {from_address}"
f"status={response.status_code} body={response.text}"
)
return False
except Exception as e:
logger.error(f"[MAILGUN] Exception while sending to {message.to}: {e}")
return False