Open zstumgoren opened 5 years ago
It's not clear to me if you're using Gmail or the test Python mail server for dev or testing purposes, as described in docs here.
I am however getting a stacktrace when I attempt to subscribe. The primary error appears to be related to misconfiguration of mail in my case, followed by the ctx.app
error. It's not clear to me if the latter is related to and/or caused by this mail configuration issue, but will need to sort out the mail issue first. When you have a chance, please drop a note with clarification on how you're handling mail configuration on your end.
send: 'quit\r\n'
Exception in thread Thread-10:
Traceback (most recent call last):
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask_mail.py", line 492, in send
message.send(connection)
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask_mail.py", line 427, in send
connection.send(self)
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask_mail.py", line 192, in send
message.rcpt_options)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 851, in sendmail
self.ehlo_or_helo_if_needed()
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 599, in ehlo_or_helo_if_needed
if not (200 <= self.ehlo()[0] <= 299):
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 439, in ehlo
self.putcmd(self.ehlo_msg, name or self.local_hostname)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 366, in putcmd
self.send(str)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 358, in send
raise SMTPServerDisconnected('please run connect() first')
smtplib.SMTPServerDisconnected: please run connect() first
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "/Users/tumgoren/code/stanford/thesis/fabienne/observ_admin/app/emails.py", line 8, in send_async_email
mail.send(msg)
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask_mail.py", line 492, in send
message.send(connection)
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask_mail.py", line 152, in __exit__
self.host.quit()
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 982, in quit
res = self.docmd("quit")
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 419, in docmd
self.putcmd(cmd, args)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 366, in putcmd
self.send(str)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 358, in send
raise SMTPServerDisconnected('please run connect() first')
smtplib.SMTPServerDisconnected: please run connect() first
127.0.0.1 - - [15/May/2019 18:07:07] "POST /subscribe HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 18:07:07] "GET /static/subscribe.js HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 18:07:07] "GET /static/index_style.css HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 18:07:07] "GET /static/perPage.js HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 18:07:07] "GET /static/prepopulate.js HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 18:07:07] "GET /static/images/backdrop_laptops.jpg HTTP/1.1" 200 -
Job "stumgoren (trigger: interval[0:00:05], next run at: 2019-05-15 18:07:17 PDT)" raised an exception
Traceback (most recent call last):
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/apscheduler/executors/base.py", line 125, in run_job
retval = job.func(*job.args, **job.kwargs)
File "/Users/tumgoren/code/stanford/thesis/fabienne/observ_admin/app/tasks.py", line 25, in sub_job
send_results_email(user, sub, output)
File "/Users/tumgoren/code/stanford/thesis/fabienne/observ_admin/app/emails.py", line 42, in send_results_email
user=user, subscription=subscription, results=results),
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask/templating.py", line 133, in render_template
ctx.app.update_template_context(context)
Should be fixed now
I'm handling it by using my dev gmail that I created last quarter. I updated the env file with the configs that I'm using.
Can't seem to get this working with your gmail credentials or the standard mail debugger server credentials. I should've mentioned earlier, but for dev purposes, it would be better to use the mail debug server for testing, and to avoid committing your personal mail server credentials in .env
.
Anyhow, can't seem to get past this error. Don't think I'll be able to look at this again until tomorrow night or Friday. Meantime, I would try to get the stack working with the mail debug server and then verify that you're not in fact getting the same SMTP related errors that I am. It's a really long error message, and the ctx.app
error occurs downstream and keeps repeating. So I'm wondering if there's a chance you're also getting this SMTP related error but possibly only seeing the ctx.app
error because you didn't scroll up high enough in the logs.
To test, change the following configs in .env
file:
FLASK_DEBUG=0
MAIL_SERVER=localhost
MAIL_HOST=8025
Execute flask run
in your terminal (not in VSCode), so you can more easily scroll back in history to see all the server logs.
Then try triggering the error on subscribe via the app's web interface.
Once you trigger the error, immediately kill the Flask server in the terminal and then check the console for the full history of the error. This may require a fair bit of scrolling up.
Let me know if you see something like this:
Traceback (most recent call last):
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "/Users/tumgoren/code/stanford/thesis/fabienne/observ_admin/app/emails.py", line 8, in send_async_email
mail.send(msg)
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask_mail.py", line 491, in send
with self.connect() as connection:
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask_mail.py", line 144, in __enter__
self.host = self.configure_host()
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask_mail.py", line 158, in configure_host
host = smtplib.SMTP(self.mail.server, self.mail.port)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 251, in __init__
(code, msg) = self.connect(host, port)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 335, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 306, in _get_socket
self.source_address)
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/socket.py", line 722, in create_connection
raise err
File "/Users/tumgoren/.pyenv/versions/3.6.1/lib/python3.6/socket.py", line 713, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 61] Connection refused
127.0.0.1 - - [15/May/2019 19:39:45] "POST /subscribe HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 19:39:45] "GET /static/subscribe.js HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 19:39:45] "GET /static/perPage.js HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 19:39:45] "GET /static/index_style.css HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 19:39:45] "GET /static/prepopulate.js HTTP/1.1" 200 -
127.0.0.1 - - [15/May/2019 19:39:45] "GET /static/images/backdrop_laptops.jpg HTTP/1.1" 200 -
Job "stumgoren (trigger: interval[0:00:05], next run at: 2019-05-15 19:39:55 PDT)" raised an exception
Traceback (most recent call last):
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/apscheduler/executors/base.py", line 125, in run_job
retval = job.func(*job.args, **job.kwargs)
File "/Users/tumgoren/code/stanford/thesis/fabienne/observ_admin/app/tasks.py", line 22, in sub_job
send_results_email(user, sub, output)
File "/Users/tumgoren/code/stanford/thesis/fabienne/observ_admin/app/emails.py", line 42, in send_results_email
user=user, subscription=subscription, results=results),
File "/Users/tumgoren/.local/share/virtualenvs/observ_admin-g2ZsYChj/lib/python3.6/site-packages/flask/templating.py", line 133, in render_template
ctx.app.update_template_context(context)
AttributeError: 'NoneType' object has no attribute 'app'
I tried to use the mail debugger first way back when but I couldn't get that to work either, so I had to switch to gmail in order to get it to work. So I don't think I can get any further on that than you unfortunately.
But I'll give a try and see where I get stuck.
By the way, the reason you can't get it to work is very very possibly because I just got an email that Google blocked a sign in attempt for my dev email. So, that's probably a gmail thing - there's nothing wrong with the credentials themselves.
So, just to check, I ran it with the debug settings as well as my email settings.
The issue is indeed similar at the top when I'm running in the debug mail server, I did get a ConnectionError [Errno 111] << instead of Errno 61 >> but it was indeed a 'Connection Refused' at the top.
I'll have to check if it's the same when I use my own settings.
@zstumgoren Sooooo, I tried running with my original settings again - I guess I had to restart the terminal - but here's the kicker: when I use my gmail settings (and the sub email is being sent) there is no trace of a ConnectionError at the top.
Here's the full (first) error:
Job "fabienne (trigger: interval[0:00:05], next run at: 2019-05-15 20:21:53 PDT)" raised an exception
Traceback (most recent call last):
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/executors/base.py", line 125, in run_job
retval = job.func(*job.args, **job.kwargs)
File "/home/fabienne/Desktop/Observ/app/tasks.py", line 25, in sub_job
send_results_email(user, sub, output)
File "/home/fabienne/Desktop/Observ/app/emails.py", line 42, in send_results_email
user=user, subscription=subscription, results=results),
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/templating.py", line 133, in render_template
ctx.app.update_template_context(context)
AttributeError: 'NoneType' object has no attribute 'app'
Looks like the SMTP errors are only present when one uses localhost as a debug mail server. Unfortunately.
One quick addendum -- I think ctx.app
bug may be related to the use of threading in the async mail function. Likely unrelated to the mail configuration issue.
The more I think about this, the more I suspect this is thread-related.
The APScheduler BackgroundScheduler already runs in a thread.
And on top of that, you're sending mail inside another thread:
https://github.com/ducoquelicot/observ_admin/blob/master/app/emails.py#L14
So my best guess is that the application context is being lost or is simply unavailable to a thread (send_email
) nested inside another thread (the scheduler).
I know the Mega Tutorial includes a section on sending mail asynchronously using a thread, but since we're already using an asynchronous task scheduling service, this is one area we'll need to do things differently.
I would start by removing the Thread call wrapping send_email
:
Thread(target=send_async_email, args=(observ, msg)).start()
And then see what bugs crop up.
And of course, rewire the code to just send an email synchronously. For example:
10 def send_email(subject, sender, recipients, text_body, html_body):
11 msg = Message(subject, sender=sender, recipients=recipients)
12 msg.body = text_body
13 msg.html = html_body
~ 14 with observ.app_context():
+ 15 mail.send(msg)
This will still be run asynchronously by the scheduler, but it avoids creating an unnecessary thread inside of the scheduler.
Ok! I'll see if that works.
@zstumgoren Update: that unfortunately did not make any difference. Error message is still the same.
I was/am googling, tried this: https://stackoverflow.com/questions/31156091/attributeerror-nonetype-object-has-no-attribute-app-when-trying-to-send-mai
Didn't work either, unfortunately. Error message is still the same.
edit: sub email is still working, though, it's really only the email that is inside the job.
I think this is the problem: https://stackoverflow.com/questions/24579091/flask-periodically-rendering-html-without-context
I checked and all the other emails are being sent from within a route, so it makes sense. Unfortunately I have no idea how to use this solution on my use case. I'm sure you have some clever ideas, though!
Side note, I got the debug email server to work by just using defaults of localhost and port 25. I'm sure there's a way to get it to work with a custom port, but just going with the defaults for now to avoid further yak shaving.
Yep, the missing application context is indeed the key, although the nature of threading (which is notoriously hard to debug) further complicates things. As a first step, I would definitely remove the threading in the send_async_email
function (actually, you can delete it entirely) and just update the remaining send_email
function to just send the mail in the standard way. We already have a threaded async job scheduler/runner in the background, so anywhere you need an email, just use the scheduler. If the message needs to be sent immediately, just omit the trigger and time arguments when you call add_job
.
Once you've standardized things on that front, move on to solving the app context problem.
The Flask modules that are being used in sub_job
really, REALLY want that app context that you get in a normal request-response cycle. But because this work is happening asynchronously outside the context of a normal web request, the app context is not available.
At a high-level, there are two potential solutions:
__init__.py
and then importing and executing the function inside of the module where the email functions live (or perhaps inside the functions themselves). For example, something along these linesrender_template
requires an app context (which it seems to...) and reading in the mail configurations and setting up an SMTP mailer instance instead of trying to use the mailer instance you've created in __init__.py
. I began to try this approach using Jinja2 and it worked, but then Flask Mailer complained that the application context was not available, which is a clue that you'll need to set up and configure SMTP yourself if you go with this approach. It might be worth trying (1), though I'm not certain that will work. Option (2) fully decouples you from the Flask application itself, which might be "cleaner" and easier to code rather than trying to figure out the nuances of how to force a Flask app context into an async job.
Give one or both of those options a try and let me know if you run into trouble.
On second thought, you might want to keep the send_async_email
for now, until you figure out a solution to sending emails via scheduler. Otherwise, all the email functionality will be broken.
So I'd just focus on working through a solution to getting the scheduler-based emails to work. Again, I'd lean toward option (2) above.
@zstumgoren re: sending the emails via the scheduler, it' s not working. I don't know why, but when I tried to test the jobs I created, the following things happened
[I was testing the 'reset password' email here]
scheduler.add_job(send_password_reset_email, args=(user))
. That gave me an error:Traceback (most recent call last):
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/fabienne/Desktop/Observ/app/routes.py", line 135, in reset_password_request
scheduler.add_job(func=send_password_reset_email, args=(user))
TypeError: add_job() missing 1 required positional argument: 'id'
WEIRD THING HAPPENED: the email was sent nonetheless.
scheduler.add_job(send_password_reset_email(user))
. That gave me the error:Traceback (most recent call last):
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/fabienne/Desktop/Observ/app/routes.py", line 135, in reset_password_request
scheduler.add_job(send_password_reset_email(user))
TypeError: add_job() missing 1 required positional argument: 'func'
AGAIN the email was sent nonetheless
Then I tried scheduler.add_job(func=send_password_reset_email(user))
Got the following error:
Traceback (most recent call last):
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/fabienne/Desktop/Observ/app/routes.py", line 135, in reset_password_request
scheduler.add_job(func=send_password_reset_email(user))
TypeError: add_job() missing 1 required positional argument: 'id'
AGAIN the email was still being set.
Then tried scheduler.add_job(id='pass_reset', func=send_password_reset_email(user))
Got this error
Traceback (most recent call last):
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/fabienne/Desktop/Observ/app/routes.py", line 135, in reset_password_request
scheduler.add_job(id='pass_reset', func=send_password_reset_email(user))
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask_apscheduler/scheduler.py", line 160, in add_job
return self._scheduler.add_job(**job_def)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 434, in add_job
job = Job(self, **job_kwargs)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/job.py", line 49, in __init__
self._modify(id=id or uuid4().hex, **kwargs)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/job.py", line 170, in _modify
raise TypeError('func must be a callable or a textual reference to one')
TypeError: func must be a callable or a textual reference to one
AGAIN email was being sent
scheduler.add_job(id='pass_reset', func=send_password_reset_email, args=(user))
got this error:
Traceback (most recent call last):
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/fabienne/Desktop/Observ/app/routes.py", line 135, in reset_password_request
scheduler.add_job(id='pass_reset', func=send_password_reset_email, args=(user))
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask_apscheduler/scheduler.py", line 160, in add_job
return self._scheduler.add_job(**job_def)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 423, in add_job
'args': tuple(args) if args is not None else (),
TypeError: 'User' object is not iterable
No emails at this point.
I tried it without the tuple around 'user' but that gave the same error. Again, no emails. I tried it with a list around 'user' and that gave no errors, but also didn't send any emails.
When I tried a similar thing for the send_sub_email I got this error:
Traceback (most recent call last):
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask_login/utils.py", line 261, in decorated_view
return func(*args, **kwargs)
File "/home/fabienne/Desktop/Observ/app/routes.py", line 55, in subscribe
scheduler.add_job(id='sub_email', func=send_sub_email, args=(current_user, sub))
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/flask_apscheduler/scheduler.py", line 160, in add_job
return self._scheduler.add_job(**job_def)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 443, in add_job
self._real_add_job(job, jobstore, replace_existing)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 867, in _real_add_job
store.add_job(job)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/jobstores/sqlalchemy.py", line 95, in add_job
'job_state': pickle.dumps(job.__getstate__(), self.pickle_protocol)
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7f505a4771e0>: attribute lookup <lambda> on flask_login.utils failed
And so I just put everything back in its original state. Don't really know how to fix this, but will see if I can find a way to fix the email for the results and have the background thread for the async emails in there at the same time.
EDIT: I pushed to master so you can check it out for yourself
@zstumgoren so, good news and bad news. The good news is that I got the emails to work with Jinja, no comments whatsoever from Mail being angry with me so I guess we' re good? Unless you' re still stuck, in that case let me know.
New issue: when I create a subscription, everything works as expected. I get a confirmation email and then a couple of 'new results' emails (with no content, this is because I have changed the code a little bit so that it runs when there are no new results, this should of course be fixed but it's good for testing purposes)
But! When I stop the app and restart it, I get the following error:
Unable to restore job "1" -- removing it
Traceback (most recent call last):
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/jobstores/sqlalchemy.py", line 141, in _get_jobs
jobs.append(self._reconstitute_job(row.job_state))
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/jobstores/sqlalchemy.py", line 128, in _reconstitute_job
job.__setstate__(job_state)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/job.py", line 272, in __setstate__
self.func = ref_to_obj(self.func_ref)
File "/home/fabienne/.local/share/virtualenvs/Observ-r9e1nbjd/lib/python3.6/site-packages/apscheduler/util.py", line 283, in ref_to_obj
obj = __import__(modulename, fromlist=[rest])
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
KeyError: 'app'
The job is removed and as such, there is no task accompanying the subscription anymore. The other job (I mean, the scraperjob) is still active though (I checked).
What I understand from the message is that something is going wrong in the obj = __import__(modulename, fromlist=[rest])
line in the APScheduler code, and that 'rest' here is replaced with 'app' and that this is a key error because this key does not exist in the dictionary.
I, however, have no idea where this ' app' is coming from. It's not in the task, and I don't really know where else to look. You any clues?
In order to help debug the Flask
ctx.app
bug, can you update theconfig.py
and.env
files to include whatever default configurations you're using. Note that environment variables should always be in caps.See mega tutorial code below for example: