Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
505 views
in Technique[技术] by (71.8m points)

sockets - Implementing Transport Layer Security in Python - Simple Mail Client

I have an assignment to write a simple mail client, and to connect to a google smtp server using sockets (without using smtp lib). However, issuing a MAIL FROM command to a google smtp server requires ssl or tls, and this is the part I can't figure out. I'm trying to use Python's ssl.wrap_socket() method thusly....

# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket(AF_INET, SOCK_STREAM)
ssl_clientSocket = ssl.wrap_socket(clientSocket) 
ssl_clientSocket.connect((mailserver, port))

...which isn't working. I'm pretty sure I need to include the ca_certs and ca_reqs parameters, but I'm not sure. And if this is so, how do I go about obtaining these certificates? Do I have to download openssl and generate one? Anyone with experience with this? Here's the entire code just to be on the safe side.

from socket import *
import ssl

msg = "
 I love computer networks!"
endmsg = "
.
"

# Choose a mail server (e.g. Google mail server) and call it mailserver
mailserver = "smtp.gmail.com"
port = 587

# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket(AF_INET, SOCK_STREAM)
ssl_clientSocket = ssl.wrap_socket(clientSocket) 
ssl_clientSocket.connect((mailserver, port))

recv = ssl_clientSocket.recv(1024)
print
print recv

# If the first three numbers of what we receive from the SMTP server are not
# '220', we have a problem
if recv[:3] != '220':
    print '220 reply not received from server.'

# Send HELO command and print server response.
heloCommand = 'HELO Alice
'
ssl_clientSocket.send(heloCommand)
recv1 = ssl_clientSocket.recv(1024)
print recv1

# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv1[:3] != '250':
    print '250 reply not received from server.'

# Send MAIL FROM command and print server response.
mailFromCommand = 'MAIL From: [email protected]
'
ssl_clientSocket.send(mailFromCommand)
recv2 = ssl_clientSocket.recv(1024)
print recv2

# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv2[:3] != '250':
    print '250 reply not received from server.'

# Send RCPT TO command and print server response.
rcptToCommand = 'RCPT To: [email protected]
'
ssl_clientSocket.send(rcptToCommand)
recv3 = ssl_clientSocket.recv(1024)
print recv3

# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv3[:3] != '250':
    print '250 reply not received from server.'

# Send DATA command and print server response.
dataCommand = 'DATA
'
ssl_clientSocket.send(dataCommand)
recv4 = ssl_clientSocket.recv(1024)
print recv4

# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv4[:3] != '250':
    print '250 reply not received from server.'

# Send message data.
ssl_clientSocket.send(msg)

# Message ends with a single period.
ssl_clientSocket.send(endmsg)

# Send QUIT command and get server response.
quitCommand = 'QUIT
'
ssl_clientSocket.send(quitCommand)
recv5 = ssl_clientSocket.recv(I1024)
print recv5

# If the first three numbers of the response from the server are not
# '250', we have a problem
if recv5[:3] != '221':
    print '221 reply not received from server.'
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You're connecting to port 587, which is the port for STARTTLS. When using SMTPS (ie. wrapping the socket before any other communication), you need to connect to port 465 instead of port 587. If you use STARTTLS, you wrap the socket later, after using the STARTTLS command and receiving a 220 response to it. After doing STARTTLS, you're supposed to do HELO again, since the server is supposed to forget anything that happened before the STARTTLS.

In either case, the servers at smtp.google.com ports 465 and 587 still won't return a 250 response to the MAIL command, since they require that you are authenticated before you send mail. You'll get a 530 response instead. You'll need to use the AUTH command with your gmail.com credentials to authenticate before you can use MAIL successfully on those servers.

If you don't want to authenticate, and depending on the details of what you need to do, you could try using port 25 of the server found in gmail.com's MX record. At the moment, the server is gmail-smtp-in.l.google.com and supports STARTTLS.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...