6

I am trying to send some mail asynchronously (based on the code in The Flask Mega-Tutorial, Part XI: Email Support). However, I get the following error about working outside an application context. How do I fix this problem?

Traceback (most recent call last):
  File "C:\Users\Primoz\Desktop\RecycleFlaskServer\recycleserver\helpers.py", line 17, in send_async_email
    mail.send(msg)
  File "C:\Python33\lib\site-packages\flask_mail-0.9.0-py3.3.egg\flask_mail.py", line 434, in send
    message.send(connection)
  File "C:\Python33\lib\site-packages\flask_mail-0.9.0-py3.3.egg\flask_mail.py", line 369, in send
    connection.send(self)
  File "C:\Python33\lib\site-packages\flask_mail-0.9.0-py3.3.egg\flask_mail.py", line 173, in send
    email_dispatched.send(message, app=current_app._get_current_object())
  File "C:\Python33\lib\site-packages\werkzeug-0.9.4-py3.3.egg\werkzeug\local.py", line 297, in _get_current_object
    return self.__local()
  File "C:\Python33\lib\site-packages\flask-0.10.1-py3.3.egg\flask\globals.py", line 34, in _find_app
    raise RuntimeError('working outside of application context')
RuntimeError: working outside of application context
from flask import Flask
from flask.ext.mail import Mail
app = Flask(__name__)
app.config.from_object('recycleserver.settings')
mail = Mail(app)

def async(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target = f, args = args, kwargs = kwargs)
        thr.start()
    return wrapper

@async
def send_async_email(msg):
    mail.send(msg)

def send_simple_mail(subject, sender, to_who, text_body="", html_body=""):
    msg = Message(subject=subject,sender=sender, recipients=to_who)
    msg.body = text_body
    msg.html = html_body
    send_async_email(msg)
davidism
  • 121,510
  • 29
  • 395
  • 339
zPrima
  • 727
  • 1
  • 8
  • 20

1 Answers1

18

The code should run in an app context. Add with app.app_context():

 @async
 def send_async_email(msg):
    with app.app_context():
       mail.send(msg)
davidism
  • 121,510
  • 29
  • 395
  • 339
zPrima
  • 727
  • 1
  • 8
  • 20
  • 2
    What if we used the factory pattern to create the app? This is comment from flask documentation : "When using the app factory pattern or writing reusable blueprints or extensions there won’t be an app instance to import at all." We have access to the current_app proxi variable, but only in view functions. But the problem is that if we use Thread then we don't have access to this curren_app proxi at all. This means that sending async email with the app factory pattern is not possible. – makkasi May 29 '18 at 06:57
  • 1
    if using the app factory then import your app creation function and create one: `app=create_app(*args)` and use that with the `with` statement – Attack68 Nov 18 '18 at 08:44