SSL used even when explicitly set to False
Hi,
I just encountered a problem which took me some time to figure out what happens. I developed a small application using Flask-Mail to send emails. Hosting ist done on Heroku. I use environment variables to configure my mailhost and so here's my configuration (read via heroku config):
MAIL_USERNAME: my_username
MAIL_PASSWORD: my_secret
MAIL_HOST: smtp.example.com
MAIL_USE_SSL: False
MAIL_PORT: 25
As you can see, SSL is explicitly set to false, the standard port 25 is used. But for some reason smtplib still goes for using an SSL connection:
2019-08-07T08:51:16.582041+00:00 app[web.1]: Exception in thread Thread-1:
2019-08-07T08:51:16.582044+00:00 app[web.1]: Traceback (most recent call last):
2019-08-07T08:51:16.582046+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/threading.py", line 916, in _bootstrap_inner
2019-08-07T08:51:16.582047+00:00 app[web.1]: self.run()
2019-08-07T08:51:16.582049+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/threading.py", line 864, in run
2019-08-07T08:51:16.582050+00:00 app[web.1]: self._target(*self._args, **self._kwargs)
2019-08-07T08:51:16.582052+00:00 app[web.1]: File "/app/stocksportevents/helper.py", line 125, in send_async_mail
2019-08-07T08:51:16.582053+00:00 app[web.1]: mail.send(msg)
2019-08-07T08:51:16.582055+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask_mail.py", line 491, in send
2019-08-07T08:51:16.582056+00:00 app[web.1]: with self.connect() as connection:
2019-08-07T08:51:16.582057+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask_mail.py", line 144, in __enter__
2019-08-07T08:51:16.582059+00:00 app[web.1]: self.host = self.configure_host()
2019-08-07T08:51:16.582060+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask_mail.py", line 156, in configure_host
2019-08-07T08:51:16.582062+00:00 app[web.1]: host = smtplib.SMTP_SSL(self.mail.server, self.mail.port)
2019-08-07T08:51:16.582063+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/smtplib.py", line 1031, in __init__
2019-08-07T08:51:16.582065+00:00 app[web.1]: source_address)
2019-08-07T08:51:16.582066+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/smtplib.py", line 251, in __init__
2019-08-07T08:51:16.582067+00:00 app[web.1]: (code, msg) = self.connect(host, port)
2019-08-07T08:51:16.582069+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/smtplib.py", line 336, in connect
2019-08-07T08:51:16.582070+00:00 app[web.1]: self.sock = self._get_socket(host, port, self.timeout)
2019-08-07T08:51:16.582071+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/smtplib.py", line 1039, in _get_socket
2019-08-07T08:51:16.582073+00:00 app[web.1]: server_hostname=self._host)
2019-08-07T08:51:16.582074+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/ssl.py", line 407, in wrap_socket
2019-08-07T08:51:16.582075+00:00 app[web.1]: _context=self, _session=session)
2019-08-07T08:51:16.582077+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/ssl.py", line 817, in __init__
2019-08-07T08:51:16.582078+00:00 app[web.1]: self.do_handshake()
2019-08-07T08:51:16.582080+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/ssl.py", line 1077, in do_handshake
2019-08-07T08:51:16.582081+00:00 app[web.1]: self._sslobj.do_handshake()
2019-08-07T08:51:16.582082+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/ssl.py", line 689, in do_handshake
2019-08-07T08:51:16.582084+00:00 app[web.1]: self._sslobj.do_handshake()
2019-08-07T08:51:16.582085+00:00 app[web.1]: ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:852)
After several tries and reloads I came across the idea to simply unset MAIL_USE_SSL on Heroku - and it was working! I tried to retrace the variable in your code, but I would say there's nothing which would point to this problem. You're just reading MAIL_USE_SSL from app.config and set self.use_ssl accordingly, that's it.
Any ideas why this happens?
Regads, Thomas
I can confirm this. I set MAIL_USE_SSL to False and tracked that value into flask_mail.py. It seems like it's lost at this point in _MailMixin.connect()
app = getattr(self, "app", None) or current_app
try:
return Connection(app.extensions['mail'])
except KeyError:
...
It seems that "class Mail" is not being registered as an app.extension as it should in Mail.init_app(self, app). Which is to say when calling
mail = Mail(app)
that the app is None, because Mail.init will call self.init_app(app).
Also in your app config (like settings.py if you use that), be sure not to have a comma like this:
MAIL_USE_SSL = False,
That will make this setting a tuple, not a boolean.
Also in your app config (like settings.py if you use that), be sure not to have a comma like this:
MAIL_USE_SSL = False,That will make this setting a tuple, not a boolean.
great,I made this mistake.Thank you.