miguelgrinberg / flasky

Companion code to my O'Reilly book "Flask Web Development", second edition.
MIT License
8.54k stars 4.21k forks source link

sending of email not working with uWSGI #512

Closed wolferikg closed 3 years ago

wolferikg commented 3 years ago

Hello,

I have copied your auth system code 1:1 into a little project of mine and when i run it locally or on my remote server with the built in werkzeug application server the sending of emails works like a charm. but once i deploy it with uWSGI (also just tried briefly with gunicorn... same issue) the emails are no longer sent.

i ran the uWSGI process with strace and it appears to me, that the thread that should be created by send_email() never runs.

I've spent the better part of a night and a day fiddling around and trying all sorts of things (--enable-threads, threads = 2, --lazy, --single-interpreter and whatnot) but i just can't seem to get it to work. would you have an idea what i'm doing wrong here?

at this point my uwsgi config looks like this:

   module = wsgi:app

   master = true
   processes = 5
   threads = 5

   socket = app.sock
   chmod-socket = 660
   vacuum = true

   ; mount apps
   mount = /mustard=wsgi:app
   callable: app

   ; rewrite SCRIPT_NAME and PATH_INFO accordingly
   manage-script-name = true

   die-on-term = true

   env = MAIL_USERNAME=myUser
   env = MAIL_PASSWORD=myPass
   env = MAIL_SERVER=smtp.domain.tld
   env = MUSTARD_CONFIG=unix
   env = DATABASE_URL=sqlite:////home/app/app/db/data-dev.sqlite

and i start it like so:

uwsgi --uwsgi-socket app.sock -w wsgi:app --honour-stdin --ini app.ini --lazy --enable-threads
miguelgrinberg commented 3 years ago

The thread that is used for sending the email has nothing to do with the thread support in uWSGI, which is specifically for handling requests. You do not need to change the uWSGI configuration in any way.

Did you look at the uWSGI logs to see if there are any errors? Did you add print statements in the request handler right before the thread is launched, and then another print in the thread itself to make sure it started? There isn't really much to this, it is just a standard thread, there is no reason for this to not work unless something else changed and you are not aware of it.

wolferikg commented 3 years ago

wow - thanks for the quick reply! i tried adding some prints but never got to see them on the STDOUT

email.py:

from threading import Thread
from flask import current_app, render_template
from flask_mail import Message
from . import mail

def send_async_email(app, msg):
    print('Inside Thread Function')
    with app.app_context():
        print('About to send email')
        mail.send(msg)

def send_email(to, subject, template, **kwargs):
    print('Entered send_email')
    app = current_app._get_current_object()
    msg = Message(app.config['MUSTARD_MAIL_SUBJECT_PREFIX'] + ' ' + subject,
                  sender=app.config['MUSTARD_MAIL_SENDER'], recipients=[to])
    msg.body = render_template(template + '.txt', **kwargs)
    msg.html = render_template(template + '.html', **kwargs)
    thr = Thread(target=send_async_email, args=[app, msg])
    thr.start()
    print('Thread started')
    return thr

I'll take a closer look at uWSGI logging - thanks again for the quick clarification.

wolferikg commented 3 years ago

OK it works now... after starting over the deployment. i don't even know what the issue was. i may have been too deep in the rabbit hole last night (like over whitespace in the smtp pw which i changed to make sure that's not causing an issue) thanks again for the quick reply which did set my sight straight!!