8
\$\begingroup\$
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', '[email protected]')):
 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.

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jul 21, 2016 at 6:24
\$\endgroup\$
2
  • \$\begingroup\$ What "mail utility class"? All I see is a bunch of related functions. \$\endgroup\$ Commented Jul 21, 2016 at 7:11
  • \$\begingroup\$ In my application, i have a utils folder separate from my models and views. You're right though, this is not a class. I'm not sure what the appropriate name is for a group of function desgined to provide related functionality is. A package? \$\endgroup\$ Commented Jul 21, 2016 at 7:13

1 Answer 1

2
\$\begingroup\$

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 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 it 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.

answered Sep 7, 2016 at 20:45
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.