Files
gh-christianlouis-quizzical…/musicround/helpers/email_helper.py
T
Christian Krakau-Louis 03b982e7c2 Initial clean commit
2025-05-13 08:59:02 +00:00

103 lines
4.3 KiB
Python

"""
Email helper functions for Quizzical Beats
"""
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from flask import current_app
def send_email(recipient, subject, body_text, attachments=None):
"""
Sends an email with optional attachments.
Args:
recipient (str): Email address of the recipient
subject (str): Email subject
body_text (str): Plain text email body
attachments (list): Optional list of attachment dictionaries with keys:
- 'data': The binary data of the attachment
- 'filename': Filename for the attachment
- 'mimetype': Mimetype string like 'application/pdf'
Returns:
tuple: (success, message) where success is a boolean and message contains
details about the result
"""
# Get mail configuration from environment variables
mail_host = current_app.config.get('MAIL_HOST')
mail_port = current_app.config.get('MAIL_PORT')
mail_username = current_app.config.get('MAIL_USERNAME')
mail_password = current_app.config.get('MAIL_PASSWORD')
mail_sender = current_app.config.get('MAIL_SENDER')
# Check if all email configuration parameters are available
missing_config = []
if not mail_host:
missing_config.append("MAIL_HOST")
if not mail_port:
missing_config.append("MAIL_PORT")
if not mail_username:
missing_config.append("MAIL_USERNAME")
if not mail_password:
missing_config.append("MAIL_PASSWORD")
if not mail_sender:
missing_config.append("MAIL_SENDER")
if missing_config:
missing_params = ", ".join(missing_config)
error_msg = f"Email server configuration is incomplete. Missing parameters: {missing_params}."
current_app.logger.error(f"Email configuration error: {error_msg}")
current_app.logger.error(f"Current config values - MAIL_HOST: {'set' if mail_host else 'missing'}, "
f"MAIL_PORT: {'set' if mail_port else 'missing'}, "
f"MAIL_USERNAME: {'set' if mail_username else 'missing'}, "
f"MAIL_PASSWORD: {'set' if mail_password else 'missing'}, "
f"MAIL_SENDER: {'set' if mail_sender else 'missing'}")
return False, error_msg
# Create message object
msg = MIMEMultipart()
msg['From'] = mail_sender
msg['To'] = recipient
msg['Subject'] = subject
# Attach text body
msg.attach(MIMEText(body_text, 'plain'))
# Attach files if provided
if attachments:
for attachment in attachments:
part = MIMEBase(
attachment.get('mimetype', 'application/octet-stream').split('/')[0],
attachment.get('mimetype', 'application/octet-stream').split('/')[1]
)
part.set_payload(attachment['data'])
encoders.encode_base64(part)
part.add_header(
'Content-Disposition',
f'attachment; filename={attachment["filename"]}'
)
msg.attach(part)
try:
current_app.logger.info(f"Attempting to send email to {recipient} via {mail_host}:{mail_port}")
with smtplib.SMTP(mail_host, mail_port) as server:
server.starttls()
current_app.logger.debug("STARTTLS established")
server.login(mail_username, mail_password)
current_app.logger.debug(f"Login successful for {mail_username}")
server.sendmail(mail_sender, recipient, msg.as_string())
current_app.logger.info(f"Email sent successfully from {mail_sender} to {recipient}")
return True, f'Email sent successfully to {recipient}!'
except smtplib.SMTPException as e:
error_msg = str(e)
current_app.logger.error(f"SMTP Error: {error_msg}")
current_app.logger.error(f"Failed to send email from {mail_sender} to {recipient} via {mail_host}:{mail_port}")
return False, error_msg
except Exception as e:
error_msg = f"Unexpected error: {str(e)}"
current_app.logger.error(error_msg)
return False, error_msg