smtplib and TLS

M

Matthias Kluwe

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('(e-mail address removed)', password)
server.sendmail("(e-mail address removed)", 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
 
P

Paul Rubin

Matthias Kluwe said:
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.
 
M

Matthias Kluwe

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.

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
 
P

Paul Rubin

Matthias Kluwe said:
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.
 
T

Tim Williams

----- Original Message -----
From: "Paul Rubin" "http://phr.cx"@NOSPAM.invalid

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.

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('(e-mail address removed)', password)
server.sendmail("(e-mail address removed)", toaddress, message)
server.quit()

HTH :)
 
M

Matthias Kluwe

From: "Paul Rubin" "http://phr.cx"@NOSPAM.invalid
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
 
T

Tim Williams

----- Original Message -----
From: "Matthias Kluwe said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top