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

93 lines
3.2 KiB
Python
Raw Normal View History

"""SMTP email provider implementation."""
import logging
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from flask import current_app
from gatehouse_app.services.email_provider import EmailMessage, EmailProvider
logger = logging.getLogger(__name__)
class SmtpEmailProvider(EmailProvider):
"""SMTP-based email provider implementation."""
# Configuration keys
EMAIL_ENABLED_KEY = "EMAIL_ENABLED"
SMTP_HOST_KEY = "SMTP_HOST"
SMTP_PORT_KEY = "SMTP_PORT"
SMTP_USERNAME_KEY = "SMTP_USERNAME"
SMTP_PASSWORD_KEY = "SMTP_PASSWORD"
SMTP_USE_TLS_KEY = "SMTP_USE_TLS"
FROM_ADDRESS_KEY = "FROM_ADDRESS"
def send(self, message: EmailMessage) -> bool:
"""Send an email via SMTP.
Args:
message: EmailMessage instance containing email details
Returns:
bool: True if email was sent successfully, False otherwise
"""
email_enabled = current_app.config.get(self.EMAIL_ENABLED_KEY, False)
if not email_enabled:
logger.info(
f"[EMAIL DISABLED] Would have sent to: {message.to} | "
f"Subject: {message.subject}"
)
return False
smtp_host = current_app.config.get(self.SMTP_HOST_KEY, "")
from_address = message.from_address or current_app.config.get(self.FROM_ADDRESS_KEY, "")
missing = [k for k, v in [("SMTP_HOST", smtp_host), ("FROM_ADDRESS", from_address)] if not v]
if missing:
logger.error(
f"[EMAIL] Cannot send — missing config: {', '.join(missing)}. "
f"Would have sent to: {message.to} | Subject: {message.subject}"
)
return False
smtp_port_raw = current_app.config.get(self.SMTP_PORT_KEY, 587)
try:
smtp_port = int(smtp_port_raw)
except (TypeError, ValueError):
logger.error(f"[EMAIL] Invalid SMTP_PORT value: {smtp_port_raw!r}")
return False
smtp_username = current_app.config.get(self.SMTP_USERNAME_KEY)
smtp_password = current_app.config.get(self.SMTP_PASSWORD_KEY)
smtp_use_tls = current_app.config.get(
self.SMTP_USE_TLS_KEY,
smtp_port not in (25, 1025),
)
try:
msg = MIMEMultipart("alternative")
msg["Subject"] = message.subject
msg["From"] = from_address
msg["To"] = message.to
msg.attach(MIMEText(message.body, "plain"))
if message.html_body:
msg.attach(MIMEText(message.html_body, "html"))
with smtplib.SMTP(smtp_host, smtp_port) as server:
server.ehlo()
if smtp_use_tls:
server.starttls()
server.ehlo()
if smtp_username and smtp_password:
server.login(smtp_username, smtp_password)
server.send_message(msg)
logger.info(f"[EMAIL] Sent to {message.to} | Subject: {message.subject}")
return True
except Exception as e:
logger.error(f"[EMAIL] Failed to send to {message.to}: {e}")
return False