patternpythonflaskMinor
Mail utility class for use with Flask
Viewed 0 times
flaskwithutilitymailforuseclass
Problem
from application import app, mail
from threading import Thread
from flask.ext.mail import Message
__all__ = ['send_email', 'send_bulk_email', 'create_email']
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
def send_bulk_async_email(app, emails):
with app.app_context():
with mail.connect() as conn:
for email in emails:
conn.send(email)
def create_email(subject, recipients, text_body, html_body, sender=('My Company', 'info@mycompany.com.au')):
email = Message(subject, sender=sender, recipients=recipients)
email.body = text_body
email.html = html_body
return email
def send_email(email):
thr = Thread(target=send_async_email, args=[app, email])
thr.start()
def send_bulk_email(emails):
thr = Thread(target=send_bulk_async_email, args=[app, emails])
thr.start()The first two functions are used internally as the threaded function calls. The create_email function is used to generate Message objects, which are then passed back to the send_email or send_bulk_email function dependent on whether there is a singular or multiple emails, respectively.
I currently think merging the singular and multiple send functions would be overkill, and remove some of the readability, however I am also open to feedback on that opinion.
Solution
I'd unify both functions and only have the bulk/multiple-emails version
because the single case is basically a specialisation of the general
case and the slight bit more work is unlikely to be noticeable (unless I
missed some other technical reason why this isn't feasible).
Btw. the
The default value for the sender on
doesn't belong there and should rather be passed in like the rest,
perhaps store it in a configuration file anyway.
For spawning the threads also consider making it a bit more flexible by
allowing an optional parameter for the thread creation, e.g. to use a
thread pool instead of spawning an unlimited number of threads like done
here.
because the single case is basically a specialisation of the general
case and the slight bit more work is unlikely to be noticeable (unless I
missed some other technical reason why this isn't feasible).
Btw. the
with can be nested on a single line, i.e.:def send_bulk_async_email(app, emails):
with app.app_context(), mail.connect() as conn:
for email in emails:
conn.send(email)The default value for the sender on
create_email sounds like itdoesn't belong there and should rather be passed in like the rest,
perhaps store it in a configuration file anyway.
For spawning the threads also consider making it a bit more flexible by
allowing an optional parameter for the thread creation, e.g. to use a
thread pool instead of spawning an unlimited number of threads like done
here.
Code Snippets
def send_bulk_async_email(app, emails):
with app.app_context(), mail.connect() as conn:
for email in emails:
conn.send(email)Context
StackExchange Code Review Q#135460, answer score: 2
Revisions (0)
No revisions yet.