Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

smtplib and TLS

233 views
Skip to first unread message

Matthias Kluwe

unread,
Jun 17, 2005, 3:00:30 PM6/17/05
to
Hi!

After getting a @gmail.com address, I recognized I had to use TLS in my
python scripts using smtplib in order to get mail to the smtp.gmail.com
server.

Things work well so far, apart from an unexpected error. Here's my
sample code:

import smtplib

server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.ehlo()
server.login('mkl...@gmail.com', password)
server.sendmail("mkl...@gmail.com", toaddress, message)
server.quit()

The server accepts and delivers my messages, but the last command
raises

socket.sslerror: (8, 'EOF occurred in violation of protocol')

Did I miss something? Any hint is welcome.

Regards,
Matthias

Paul Rubin

unread,
Jun 17, 2005, 3:34:58 PM6/17/05
to
"Matthias Kluwe" <mkl...@gmail.com> writes:
> The server accepts and delivers my messages, but the last command
> raises
>
> socket.sslerror: (8, 'EOF occurred in violation of protocol')
>
> Did I miss something? Any hint is welcome.

Looks like the module didn't send an TLS Close Notify message before
closing the socket. I don't see anything in the docs about how to
send one from smtplib or socket, though.

Matthias Kluwe

unread,
Jun 18, 2005, 3:32:58 AM6/18/05
to

Hmm. I tried

server.sock.realsock.shutdown(2)

before server.quit() with the result of

SMTPServerDisconnected('Server not connected')

being raised. Quite an improvement ...

Matthias

Paul Rubin

unread,
Jun 18, 2005, 3:43:17 AM6/18/05
to
"Matthias Kluwe" <mkl...@gmail.com> writes:
> Hmm. I tried
>
> server.sock.realsock.shutdown(2)
> before server.quit() with the result of

I don't think that's exactly what you want. You need to send a
specific TLS message BEFORE shutting down the socket, to tell the
other end that the TLS connection is ending. That tells the server
that it shouldn't accept a TLS session resumption later. The close
notify message is required because if you don't send it, an attacker
could truncate one of your TLS messages by cutting your connection.

Basically the socket library's SSL implementation is pretty crude.
You might try http://trevp.net/tlslite for a pure-Python
implementation that's also still missing stuff, but is getting there.

Tim Williams

unread,
Jun 18, 2005, 9:23:13 AM6/18/05
to pytho...@python.org, mkl...@gmail.com

I have found problems with the TLS built into smtplib when you are doing
something with sock elswhere in your app.
eg for me using [something].sock.settimeout(x) or setting the default
timeout anywhere broke TLS in smtplib.

Have you verified that its your end that is broken, not gmail's, do other
servers give the same response ? The following servers accept incoming
TLS on port 25

e32.co.us.ibm.com
mail.donkeyisland.com
smtp.myrealbox.com

And for quick tests you don't need to send an email (or authenticate), just
use a NOOP after STARTTLS (and perhaps a RSET) then QUIT eg

server = smtplib.SMTP(hostname [,port])
server.set_debuglevel(1)
server.ehlo('x')
server.starttls()
server.ehlo('x')
server.noop()
server.rset()
server.quit()


Trevor's http://trevp.net/tlslite did the job nicely, solving my previous
TLS problems

(completely untested)

from tlslite.api import *
>
>
server = SMTP_TLS('smtp.gmail.com', 587)
server.set_debuglevel(1)
server.ehlo()
settings = HandshakeSettings()
server.starttls(settings=settings)


server.ehlo()
server.login('mkl...@gmail.com', password)
server.sendmail("mkl...@gmail.com", toaddress, message)
server.quit()

HTH :)


Matthias Kluwe

unread,
Jun 21, 2005, 11:39:02 AM6/21/05
to
> From: "Paul Rubin" "http://phr.cx"@NOSPAM.invalid

>> "Matthias Kluwe" <mkl...@gmail.com> writes:
>> After getting a @gmail.com address, I recognized I had to use TLS in my
>> python scripts using smtplib in order to get mail to the smtp.gmail.com
>> server.

>> [...]

>> The server accepts and delivers my messages, but the last command
>> raises

>> socket.sslerror: (8, 'EOF occurred in violation of protocol')

> [...]

> Have you verified that its your end that is broken, not gmail's, do other
> servers give the same response ?

No, I have not -- I should have, as I know now: Connecting, starttls,
login and sending mail works fine without the above mentioned error
using my previous mail provider.

Does that mean Gmail is in error here? I don't know...

Regards,
Matthias

Tim Williams

unread,
Jun 21, 2005, 12:49:25 PM6/21/05
to Matthias Kluwe, pytho...@python.org
----- Original Message -----
From: "Matthias Kluwe" <mkl...@gmail.com>

> > Have you verified that its your end that is broken, not gmail's, do
other
> > servers give the same response ?
>
> No, I have not -- I should have, as I know now: Connecting, starttls,
> login and sending mail works fine without the above mentioned error
> using my previous mail provider.
>
> Does that mean Gmail is in error here? I don't know...


Looks like it is GMAIL , (though TLS is not required to be able to send via
smtp.gmail.com:587 )

TLS using TLSlite also fails when connecting to GMAIL, but not to other
servers.

('5 send:', '(16:39:23) ehlo x\r\n')
('6 reply:', '(16:39:23) 250-mx.gmail.com at your service\r\n')
('6 reply:', '(16:39:23) 250-SIZE 20971520\r\n')
('6 reply:', '(16:39:23) 250-8BITMIME\r\n')
('6 reply:', '(16:39:23) 250-STARTTLS\r\n')
('6 reply:', '(16:39:23) 250 ENHANCEDSTATUSCODES\r\n')
('5 send:', '(16:39:23) STARTTLS\r\n')
('6 reply:', '(16:39:23) 220 2.0.0 Ready to start TLS\r\n')
('Status:', '(16:39:24) 2202.0.0 Ready to start TLS')
('5 send:', '(16:39:24) ehlo x\r\n')
('6 reply:', '(16:39:24) 250-mx.gmail.com at your service\r\n')
('6 reply:', '(16:39:24) 250-SIZE 20971520\r\n')
('6 reply:', '(16:39:24) 250-8BITMIME\r\n')
('6 reply:', '(16:39:24) 250-AUTH LOGIN PLAIN\r\n')
('6 reply:', '(16:39:24) 250 ENHANCEDSTATUSCODES\r\n')
('5 send:', '(16:39:24) noop\r\n')
('6 reply:', '(16:39:24) 250 2.0.0 OK\r\n')
('5 send:', '(16:39:24) rset\r\n')
('6 reply:', '(16:39:24) 250 2.1.0 Flushed d61sm2700367wra\r\n')
('5 send:', '(16:39:24) noop\r\n')
('6 reply:', '(16:39:24) 250 2.0.0 OK\r\n')
('5 send:', '(16:39:24) quit\r\n')
Traceback (most recent call last):
File "C:\test\tls.py", line 103, in ?
s.quit()
File "C:\test\smtplib.py", line 737, in quit
self.docmd("quit")
File "C:\test\smtplib.py", line 395, in docmd
return self.getreply()
File "C:\test\smtplib.py", line 367, in getreply
line = self.file.readline()
File "C:\Python23\Lib\site-packages\tlslite\FileObject.py", line 152, in
readline
data = self._sock.recv(self._rbufsize)
File "C:\Python23\Lib\site-packages\tlslite\TLSRecordLayer.py", line 393,
in recv
return self.read(bufsize)
File "C:\Python23\Lib\site-packages\tlslite\TLSRecordLayer.py", line 182,
in read
for result in self.readAsync(max, min):
File "C:\Python23\Lib\site-packages\tlslite\TLSRecordLayer.py", line 201,
in readAsync
for result in self._getMsg(ContentType.application_data):
File "C:\Python23\Lib\site-packages\tlslite\TLSRecordLayer.py", line 564,
in _getMsg
for result in self._getNextRecord():
File "C:\Python23\Lib\site-packages\tlslite\TLSRecordLayer.py", line 737,
in _getNextRecord
raise TLSAbruptCloseError()
tlslite.errors.TLSAbruptCloseError


Jp Calderone

unread,
Jun 21, 2005, 12:55:02 PM6/21/05
to pytho...@python.org

Most SSL servers and clients (primarily HTTP, but some SMTP as well) are broken in this regard: they do not properly negotiate TLS connection shutdown. This causes one end or the other to notice an SSL protocol error. Most of the time, the only thing left to do after the TLS connection shutdown is normal TCP connection shutdown, so the error doesn't lead to any problems (which is probably why so much software generates this problem). Of course, there's no way to *tell* if this is the case or not, at least programmatically. If you receive an OK response to your DATA, you probably don't need to worry, since you have gotten what you wanted out of the conversation.

It's entirely possible that the fault here lies on gmail's end, but it is also possible that the fault is in your code or the standard library ssl support. Unless you want to dive into Python's OpenSSL bindings or start examining network traces of SSL traffic, you probably won't be able to figure out who's to blame in this particular case. The simplest thing to do is probably just capture and discard that particular error (again, assuming you are getting an OK resposne to your DATA command).

Jp

0 new messages