I have a very strange problem. When an internal server error happens, Django 1.6 attempts to send an email to the admins, and apparently it agrees with the mail server to use TLS, but subsequently fails to use it. Here is the sniffed traffic:
T 2a00:1450:400c:c0c::6d:587 -> 2001:648:2ffc:1014:a800:ff:fe6b:e499:49271 [AP]
220 smtp.gmail.com ESMTP lh1sm2677557wjb.20 - gsmtp..
##
T 2001:648:2ffc:1014:a800:ff:fe6b:e499:49271 -> 2a00:1450:400c:c0c::6d:587 [AP]
ehlo peneios.cressendo.org..
##
T 2a00:1450:400c:c0c::6d:587 -> 2001:648:2ffc:1014:a800:ff:fe6b:e499:49271 [AP]
250-smtp.gmail.com at your service, [2001:648:2ffc:1014:a800:ff:fe6b:e499].
.250-SIZE 35882577..250-8BITMIME..250-STARTTLS..250-ENHANCEDSTATUSCODES..25
0-PIPELINING..250-CHUNKING..250 SMTPUTF8..
#
T 2001:648:2ffc:1014:a800:ff:fe6b:e499:49271 -> 2a00:1450:400c:c0c::6d:587 [AP]
STARTTLS..
#
T 2a00:1450:400c:c0c::6d:587 -> 2001:648:2ffc:1014:a800:ff:fe6b:e499:49271 [AP]
220 2.0.0 Ready to start TLS..
#
T 2001:648:2ffc:1014:a800:ff:fe6b:e499:49271 -> 2a00:1450:400c:c0c::6d:587 [AP]
mail FROM:<noreply@hydroscope.gr> size=6578..
#
T 2a00:1450:400c:c0c::6d:587 -> 2001:648:2ffc:1014:a800:ff:fe6b:e499:49271 [AP]
......F
As you can see, although the mail server agreed to start TLS, Django subsequently sent an unencrypted mail FROM:
directive.
But if I connect to Django with ./manage.py shell
and run this:
from django.core.mail import mail_admins
mail_admins('hello', 'hello world')
the email is sent correctly:
T 2a00:1450:400c:c09::6c:587 -> 2001:648:2ffc:1014:a800:ff:fe6b:e499:53565 [AP]
220 smtp.gmail.com ESMTP i2sm2684051wjx.42 - gsmtp..
##
T 2001:648:2ffc:1014:a800:ff:fe6b:e499:53565 -> 2a00:1450:400c:c09::6c:587 [AP]
ehlo peneios.cressendo.org..
##
T 2a00:1450:400c:c09::6c:587 -> 2001:648:2ffc:1014:a800:ff:fe6b:e499:53565 [AP]
250-smtp.gmail.com at your service, [2001:648:2ffc:1014:a800:ff:fe6b:e499].
.250-SIZE 35882577..250-8BITMIME..250-STARTTLS..250-ENHANCEDSTATUSCODES..25
0-PIPELINING..250-CHUNKING..250 SMTPUTF8..
#
T 2001:648:2ffc:1014:a800:ff:fe6b:e499:53565 -> 2a00:1450:400c:c09::6c:587 [AP]
STARTTLS..
#
T 2a00:1450:400c:c09::6c:587 -> 2001:648:2ffc:1014:a800:ff:fe6b:e499:53565 [AP]
220 2.0.0 Ready to start TLS..
#
T 2001:648:2ffc:1014:a800:ff:fe6b:e499:53565 -> 2a00:1450:400c:c09::6c:587 [AP]
...........z/x....%....y.F.F..i..8.._w...S...z.0.,.2.../.+.1.-.........(.$.
....*.&.....k.j.9.8.'.#.....).%.....g.@.3.2.............E.D.........=.5.<./
[practically nothing readable from this point on]
I found the problem.
The difference between running the system with ./manage.py shell
and running it through the web server is that in the latter case gevent
is being used. The system was running Debian's gevent
1.0.1, which has a bug in SSL code. This raised an exception while Django was starting TLS.
Instead of stopping right at the error, Django pretended that the error hadn't occurred and continued to attempt to send the email, which resulted in the strange behavior shown in the sniff. This is a Django bug.