2017-10-08 03:31:32 +03:00
|
|
|
import smtplib
|
|
|
|
from email.mime.multipart import MIMEMultipart
|
|
|
|
from email.mime.text import MIMEText
|
|
|
|
|
|
|
|
from flask import current_app as app
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
from nyaa import models
|
|
|
|
|
|
|
|
|
|
|
|
class EmailHolder(object):
|
|
|
|
''' Holds email subject, recipient and content, so we have a general class for
|
|
|
|
all mail backends. '''
|
2017-10-08 04:34:40 +03:00
|
|
|
|
2017-10-08 03:31:32 +03:00
|
|
|
def __init__(self, subject=None, recipient=None, text=None, html=None):
|
|
|
|
self.subject = subject
|
|
|
|
self.recipient = recipient # models.User or string
|
|
|
|
self.text = text
|
|
|
|
self.html = html
|
|
|
|
|
|
|
|
def format_recipient(self):
|
|
|
|
if isinstance(self.recipient, models.User):
|
|
|
|
return '{} <{}>'.format(self.recipient.username, self.recipient.email)
|
|
|
|
else:
|
|
|
|
return self.recipient
|
|
|
|
|
|
|
|
def recipient_email(self):
|
|
|
|
if isinstance(self.recipient, models.User):
|
|
|
|
return self.recipient.email
|
|
|
|
else:
|
|
|
|
return self.recipient.email
|
|
|
|
|
|
|
|
def as_mimemultipart(self):
|
|
|
|
msg = MIMEMultipart()
|
|
|
|
msg['Subject'] = self.subject
|
|
|
|
msg['From'] = app.config['MAIL_FROM_ADDRESS']
|
|
|
|
msg['To'] = self.format_recipient()
|
|
|
|
|
|
|
|
msg.attach(MIMEText(self.text, 'plain'))
|
|
|
|
if self.html:
|
|
|
|
msg.attach(MIMEText(self.html, 'html'))
|
|
|
|
|
|
|
|
return msg
|
|
|
|
|
|
|
|
|
|
|
|
def send_email(email_holder):
|
2025-03-02 15:08:58 +02:00
|
|
|
"""Send an email using the configured mail backend."""
|
2017-10-08 03:31:32 +03:00
|
|
|
mail_backend = app.config.get('MAIL_BACKEND')
|
2025-03-02 15:08:58 +02:00
|
|
|
|
|
|
|
if not mail_backend:
|
|
|
|
app.logger.warning('No mail backend configured, skipping email send')
|
|
|
|
return False
|
|
|
|
|
|
|
|
try:
|
|
|
|
if mail_backend == 'mailgun':
|
|
|
|
success = _send_mailgun(email_holder)
|
|
|
|
elif mail_backend == 'smtp':
|
|
|
|
success = _send_smtp(email_holder)
|
|
|
|
else:
|
|
|
|
app.logger.error(f'Unknown mail backend: {mail_backend}')
|
|
|
|
return False
|
|
|
|
|
|
|
|
if not success:
|
|
|
|
app.logger.error(f'Failed to send email using {mail_backend} backend')
|
|
|
|
return False
|
|
|
|
|
|
|
|
app.logger.info(f'Email successfully sent using {mail_backend} backend')
|
|
|
|
return True
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
app.logger.error(f'Error sending email: {str(e)}')
|
|
|
|
return False
|
2017-10-08 03:31:32 +03:00
|
|
|
|
|
|
|
|
|
|
|
def _send_mailgun(email_holder):
|
2025-03-02 15:08:58 +02:00
|
|
|
"""Send an email using Mailgun API with proper error handling."""
|
|
|
|
try:
|
|
|
|
mailgun_endpoint = app.config['MAILGUN_API_BASE'] + '/messages'
|
|
|
|
auth = ('api', app.config['MAILGUN_API_KEY'])
|
|
|
|
data = {
|
|
|
|
'from': app.config['MAIL_FROM_ADDRESS'],
|
|
|
|
'to': email_holder.format_recipient(),
|
|
|
|
'subject': email_holder.subject,
|
|
|
|
'text': email_holder.text,
|
|
|
|
'html': email_holder.html
|
|
|
|
}
|
|
|
|
|
|
|
|
r = requests.post(mailgun_endpoint, data=data, auth=auth)
|
|
|
|
|
|
|
|
if r.status_code != 200:
|
|
|
|
app.logger.error(f'Mailgun API error: {r.status_code} - {r.text}')
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
app.logger.error(f'Error sending email via Mailgun: {str(e)}')
|
|
|
|
return False
|
2017-10-08 03:31:32 +03:00
|
|
|
|
|
|
|
|
|
|
|
def _send_smtp(email_holder):
|
|
|
|
# NOTE: Unused, most likely untested! Should work, however.
|
|
|
|
msg = email_holder.as_mimemultipart()
|
|
|
|
|
|
|
|
server = smtplib.SMTP(app.config['SMTP_SERVER'], app.config['SMTP_PORT'])
|
|
|
|
server.set_debuglevel(1)
|
|
|
|
server.ehlo()
|
|
|
|
server.starttls()
|
|
|
|
server.ehlo()
|
|
|
|
server.login(app.config['SMTP_USERNAME'], app.config['SMTP_PASSWORD'])
|
|
|
|
server.sendmail(app.config['SMTP_USERNAME'], email_holder.recipient_email(), msg.as_string())
|
|
|
|
server.quit()
|