1

So I have a simple (needing work still!) python/twisted mail server, that supports plain text / TLS mails. I've also just written a simple client program, using smtplib.

If I connect to my server using telnet, ESMTP is advertised, then after I issue my EHLO, STARTTLS is advertised, as follows:

# telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 localhost.localdomain NO UCE NO UBE NO RELAY PROBES ESMTP
ehlo me
250-localhost.localdomain Hello 127.0.0.1, nice to meet you
250 STARTTLS

All good so far. However, I've read online of a bug related to smtplib's smtp_ssl class (see: http://bugs.python.org/issue4066 and Failing to send email with the Python example), and so people are suggesting solutions such as I have now tried, as below:

server = smtplib.SMTP('localhost', 5000) # my server is running on port 5000. Don't ask ;)
server.ehlo()
server.starttls('/opt/tesa/etc/certs/client/client.key', '/opt/tesa/etc/certs/client/client.crt')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()

This successfully sends my message - but by the looks of it, over plain text. Output from the client looks like it is only seeing the first line of the server's EHLO 250 response (the "nice to meet you") - and NOT seeing the STARTTLS. I assume therefore, that it is not issuing it's own STARTTLS (since it would only do this if the server advertised it?) - and therefore stays as a plain text mail?

# python smtplib_client.py
From: me@home.com
To: you@work.com
Enter message, end with ^D (Unix) or ^Z (Windows):
fsdfds
Message length is 45
**send: 'ehlo localhost.localdomain\r\n'
reply: '250 localhost.localdomain Hello 127.0.0.1, nice to meet you\r\n'
reply: retcode (250); Msg: localhost.localdomain Hello 127.0.0.1, nice to meet you
send: 'mail FROM:<me@home.com>\r\n'**
reply: '250 Sender address accepted\r\n'
reply: retcode (250); Msg: Sender address accepted
send: 'rcpt TO:<you@work.com>\r\n'
reply: '250 Recipient address accepted\r\n'
reply: retcode (250); Msg: Recipient address accepted
send: 'data\r\n'
reply: '354 Continue\r\n'
reply: retcode (354); Msg: Continue
data: (354, 'Continue')
send: 'From: me@home.com\r\nTo: you@work.com\r\n\r\nfsdfds\r\n.\r\n'
reply: '250 Delivery in progress\r\n'
reply: retcode (250); Msg: Delivery in progress
data: (250, 'Delivery in progress')
send: 'quit\r\n'
reply: '221 See you later\r\n'
reply: retcode (221); Msg: See you later

Can anyone switch the lights on for me? I seem to be in the dark here!

(Using Python 2.6.6)

Thanks as ever...

Community
  • 1
  • 1
Steve Hall
  • 469
  • 1
  • 5
  • 23

2 Answers2

0

The response you claim to send:

250-localhost.localdomain Hello 127.0.0.1, nice to meet you
250 STARTTLS

and the one received by the client

reply: '250 localhost.localdomain Hello 127.0.0.1, nice to meet you\r\n'

look different: There is no "-" between the response code 250 and the hostname, which means that the response is only this single line. I've checked the code for smtplib.py in python 2.7 and 3.3 and it only prints to debug the line it has read, without doing any modifications like replacing the '-' with ' '.

That's why I assume that the versions of your server in the telnet example and the smtplib example are different and that in the latter example the server really only sends the line as shown in debug and not the STARTTLS.

Apart from that it would be helpful if you would add a reference to "I've read online of a bug in smtplib's smtp_ssl class" so one could check how this relates to your problem. And please add the version of python you are using.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
0

So I'm not sure if I've tweaked something to make this happen, or I just missed it before (don't think I would have, but hey!)... SMTPLIB client is still not showuing anything in log output relating to STARTTLS. But server side:

2014-10-23 09:14:34+0000 [__builtin__.ConsoleSMTPFactory] Sending: 220: localhost.localdomain NO UCE NO UBE NO RELAY PROBES ESMTP
2014-10-23 09:14:34+0000 [mySMTP,5,127.0.0.1] Sending: 250: localhost.localdomain Hello 127.0.0.1, nice to meet you
2014-10-23 09:14:34+0000 [mySMTP,5,127.0.0.1] STARTTLS
2014-10-23 09:14:34+0000 [mySMTP,5,127.0.0.1] Sending: 220: Begin TLS negotiation now
2014-10-23 09:14:34+0000 [mySMTP,5,127.0.0.1] Sending: 250: localhost.localdomain Hello 127.0.0.1, nice to meet you
2014-10-23 09:14:34+0000 [mySMTP,5,127.0.0.1]
2014-10-23 09:14:34+0000 [mySMTP,5,127.0.0.1] Sending: 250: Sender address accepted
2014-10-23 09:14:34+0000 [mySMTP,5,127.0.0.1] Sending: 250: Recipient address accepted

To the best of my knowledge, a server would only send a "Begin TLS negotiation now" on receipt of a STARTTLS from the client. And the acceptance of sender / recipient as shown above suggests TLS negotiation successful?

Looking at the python / twisted code for the server (in twisted's smtp.py module) - messages such as the "250 - Hello 127.0.0.1" - are sent via a "self.sendCode" function. but the server sent STARTTLS uses "self.sendLine". No idea why - that would need a twisted expert I guess.

Speaking of which, I now need to find a way of verifying the server accepts the msg over TLS - ie, it has indeed secured the channel .... :)

Steve Hall
  • 469
  • 1
  • 5
  • 23