Flask-Mail breaks Celery
Question: I've got a Flask app where celery works fine and Flask-Mail on its own works
fine as well.

    
    
    from celery import Celery
    from flask_mail import Mail, Message
    app = Flask(__name__)
    mail = Mail(app)
    
    celery = Celery('main_app', 
                     broker='mongodb://localhost',
                     backend='mongodb://localhost')
    @celery.task
    def cel_test():
         return 'cel_test'
    
    @app.route('/works_maybe')
    def works_maybe():
        return cel_test.delay()
    

# SO FAR, SO GOOD

cel_test works fine with the celery worker; everything shows up in mongo.

But here's where it gets weird. The "signup" plus mail method works 100%
without `@celery.task`, but blows up when it becomes a task.

    
    
    @celery.task
    def send_email(some_arg, name, email):
        msg = Message(…message details..)
        return mail.send(msg)
    
    @app.route("/signup", methods=['POST'])
    def signup():
        return send_email.delay(...stuff for the message…)
    

# THE TRACE

    
    
    R = retval = fun(*args, **kwargs)
    File "/Users/username/pymods/virtualenvs/directory/lib/python2.7/site-packages/celery-3.0.15-py2.7.egg/celery/task/trace.py", line 415, in __protected_call__
    return self.run(*args, **kwargs)
    File "/Users/username/pymods/directory/directory/main_app/main_app.py", line 43, in send_email
    something = 'a string in the Message'),
    File "/Users/username/pymods/virtualenvs/directory/lib/python2.7/site-packages/flask/templating.py", line 123, in render_template
    ctx.app.update_template_context(context)  
    AttributeError: 'NoneType' object has no attribute 'app'
    

Could someone explain why in one case celery works great but when I involve
mail.send(msg) it breaks?

Perhaps there is something I need to learn with python more generally?

Any thoughts, if at least as to approach to this type of issue would be
greatly appreciated.


Answer: # Update

The bug is in the render_template portion of the `send_email` task.

    
    
    @celery.task
    def send_email(some_arg, name, email):
        msg = Message(
                      subject='hello', 
                      body=render_template('email.txt',
                      name=name, 
                      some_arg=some_arg),
                      recipients=[email]
                     )
        return mail.send(msg)
    

When I remove `body=render_template`, _kablaam_ , it works.

I've got `from flask import render_template`. Perhaps `render_template` can't
work like this?

Strangely, _without_ Celery, the `send_email` plus `render_template` works
perfect.

# Hackish Success

When I force the `app_context` with another function everything works:

    
    
    def create_email(some_arg, name, email):
        with app.test_request_context('/send_email'):
            return render_template('email.txt', 
                                    name=name, 
                                    some_arg=some_arg) 
    

and then toss it in the `send_email` task so

    
    
    body = render_template('email.txt'…
    

becomes

    
    
    body= create_email(some_arg, name)
    

And we're home free.

