feat: Add SMTP support for self-hosted Postal mail server
Some checks are pending
Deploy Elmeg / deploy (push) Waiting to run
Some checks are pending
Deploy Elmeg / deploy (push) Waiting to run
This commit is contained in:
parent
0af64f5862
commit
9c92eb7953
1 changed files with 50 additions and 5 deletions
|
|
@ -1,9 +1,12 @@
|
|||
"""
|
||||
Email Service - Mailgun (primary) with AWS SES fallback
|
||||
Email Service - Postal SMTP (primary), Mailgun, or AWS SES fallback
|
||||
"""
|
||||
import os
|
||||
import httpx
|
||||
import secrets
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Optional
|
||||
|
||||
|
|
@ -18,7 +21,14 @@ except ImportError:
|
|||
|
||||
class EmailService:
|
||||
def __init__(self):
|
||||
# Mailgun settings (primary)
|
||||
# Postal SMTP settings (primary - self-hosted)
|
||||
self.smtp_host = os.getenv("SMTP_HOST")
|
||||
self.smtp_port = int(os.getenv("SMTP_PORT", "25"))
|
||||
self.smtp_username = os.getenv("SMTP_USERNAME")
|
||||
self.smtp_password = os.getenv("SMTP_PASSWORD")
|
||||
self.smtp_use_tls = os.getenv("SMTP_USE_TLS", "true").lower() == "true"
|
||||
|
||||
# Mailgun settings (alternative)
|
||||
self.mailgun_api_key = os.getenv("MAILGUN_API_KEY")
|
||||
self.mailgun_domain = os.getenv("MAILGUN_DOMAIN")
|
||||
self.mailgun_api_base = os.getenv("MAILGUN_API_BASE", "https://api.mailgun.net/v3")
|
||||
|
|
@ -32,8 +42,11 @@ class EmailService:
|
|||
self.email_from = os.getenv("EMAIL_FROM", "noreply@elmeg.xyz")
|
||||
self.frontend_url = os.getenv("FRONTEND_URL", "https://elmeg.xyz")
|
||||
|
||||
# Determine which provider to use
|
||||
if self.mailgun_api_key and self.mailgun_domain:
|
||||
# Determine which provider to use (priority: SMTP -> Mailgun -> SES -> Dummy)
|
||||
if self.smtp_host and self.smtp_username and self.smtp_password:
|
||||
self.provider = "smtp"
|
||||
print(f"Email service: Using SMTP ({self.smtp_host}:{self.smtp_port})")
|
||||
elif self.mailgun_api_key and self.mailgun_domain:
|
||||
self.provider = "mailgun"
|
||||
print(f"Email service: Using Mailgun ({self.mailgun_domain})")
|
||||
elif BOTO3_AVAILABLE and self.aws_access_key_id and self.aws_secret_access_key:
|
||||
|
|
@ -51,13 +64,45 @@ class EmailService:
|
|||
|
||||
def send_email(self, to_email: str, subject: str, html_content: str, text_content: str):
|
||||
"""Send an email using configured provider"""
|
||||
if self.provider == "mailgun":
|
||||
if self.provider == "smtp":
|
||||
return self._send_smtp(to_email, subject, html_content, text_content)
|
||||
elif self.provider == "mailgun":
|
||||
return self._send_mailgun(to_email, subject, html_content, text_content)
|
||||
elif self.provider == "ses":
|
||||
return self._send_ses(to_email, subject, html_content, text_content)
|
||||
else:
|
||||
return self._send_dummy(to_email, subject, text_content)
|
||||
|
||||
def _send_smtp(self, to_email: str, subject: str, html_content: str, text_content: str):
|
||||
"""Send email via SMTP (Postal or any SMTP server)"""
|
||||
try:
|
||||
# Create message
|
||||
msg = MIMEMultipart("alternative")
|
||||
msg["Subject"] = subject
|
||||
msg["From"] = f"Elmeg <{self.email_from}>"
|
||||
msg["To"] = to_email
|
||||
|
||||
# Attach text and HTML parts
|
||||
msg.attach(MIMEText(text_content, "plain"))
|
||||
msg.attach(MIMEText(html_content, "html"))
|
||||
|
||||
# Connect and send
|
||||
if self.smtp_use_tls:
|
||||
server = smtplib.SMTP(self.smtp_host, self.smtp_port)
|
||||
server.starttls()
|
||||
else:
|
||||
server = smtplib.SMTP(self.smtp_host, self.smtp_port)
|
||||
|
||||
server.login(self.smtp_username, self.smtp_password)
|
||||
server.sendmail(self.email_from, to_email, msg.as_string())
|
||||
server.quit()
|
||||
|
||||
print(f"Email sent via SMTP to {to_email}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error sending email via SMTP: {e}")
|
||||
return False
|
||||
|
||||
def _send_mailgun(self, to_email: str, subject: str, html_content: str, text_content: str):
|
||||
"""Send email via Mailgun API"""
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue