在 Python 中实现传输层安全性 - 简单邮件客户端 [英] Implementing Transport Layer Security in Python - Simple Mail Client

查看:41
本文介绍了在 Python 中实现传输层安全性 - 简单邮件客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的任务是编写一个简单的邮件客户端,并使用套接字(不使用 smtp lib)连接到 google smtp 服务器.但是,向 google smtp 服务器发出 MAIL FROM 命令需要 ssl 或 tls,这是我无法弄清楚的部分.我正在尝试使用 Python 的 ssl.wrap_socket() 方法....

#创建一个名为clientSocket的socket并与mailserver建立TCP连接clientSocket = socket(AF_INET, SOCK_STREAM)ssl_clientSocket = ssl.wrap_socket(clientSocket)ssl_clientSocket.connect((邮件服务器,端口))

...这不起作用.我很确定我需要包含 ca_certs 和 ca_reqs 参数,但我不确定.如果是这样,我该如何获得这些证书?我必须下载 openssl 并生成一个吗?任何有这方面经验的人?为了安全起见,这里是整个代码.

from socket import *导入 sslmsg = "\r\n 我喜欢计算机网络!"endmsg = "\r\n.\r\n"# 选择一个邮件服务器(例如 Google 邮件服务器)并将其命名为 mailserver邮件服务器 = "smtp.gmail.com"端口 = 587# 创建名为clientSocket的socket并与mailserver建立TCP连接clientSocket = socket(AF_INET, SOCK_STREAM)ssl_clientSocket = ssl.wrap_socket(clientSocket)ssl_clientSocket.connect((邮件服务器,端口))recv = ssl_clientSocket.recv(1024)打印打印接收# 如果我们从 SMTP 服务器收到的前三个数字不是# '220',我们有问题如果 recv[:3] != '220':打印 '220 未从服务器收到回复.# 发送 HELO 命令和打印服务器响应.heloCommand = '你好爱丽丝\r\n'ssl_clientSocket.send(heloCommand)recv1 = ssl_clientSocket.recv(1024)打印recv1# 如果来自服务器的响应的前三个数字不是# '250',我们有问题如果 recv1[:3] != '250':打印未从服务器收到 250 回复."# 发送 MAIL FROM 命令和打印服务器响应.mailFromCommand = '邮件发件人:wgimson@gmail.com\r\n'ssl_clientSocket.send(mailFromCommand)recv2 = ssl_clientSocket.recv(1024)打印recv2# 如果来自服务器的响应的前三个数字不是# '250',我们有问题如果 recv2[:3] != '250':打印未从服务器收到 250 回复."# 发送 RCPT TO 命令和打印服务器响应.rcptToCommand = 'RCPT 收件人:macyali@gmail.com\r\n'ssl_clientSocket.send(rcptToCommand)recv3 = ssl_clientSocket.recv(1024)打印 recv3# 如果来自服务器的响应的前三个数字不是# '250',我们有问题如果 recv3[:3] != '250':打印未从服务器收到 250 回复."# 发送 DATA 命令和打印服务器响应.dataCommand = '数据\r\n'ssl_clientSocket.send(dataCommand)recv4 = ssl_clientSocket.recv(1024)打印recv4# 如果来自服务器的响应的前三个数字不是# '250',我们有问题如果 recv4[:3] != '250':打印 '250 未从服务器收到回复.# 发送消息数据.ssl_clientSocket.send(msg)# 消息以一个句点结束.ssl_clientSocket.send(endmsg)# 发送 QUIT 命令并获得服务器响应.退出命令 = '退出\r\n'ssl_clientSocket.send(quitCommand)recv5 = ssl_clientSocket.recv(I1024)打印 recv5# 如果来自服务器的响应的前三个数字不是# '250',我们有问题如果 recv5[:3] != '221':打印未从服务器收到 221 回复."

解决方案

您正在连接到端口 587,这是 STARTTLS 的端口.使用 SMTPS 时(即在任何其他通信之前包装套接字),您需要连接到端口 465 而不是端口 587.如果您使用 STARTTLS,则在使用 STARTTLS 命令后稍后包装套接字并收到一个 220 响应.执行完STARTTLS 之后,您应该再次执行HELO,因为服务器应该忘记在STARTTLS 之前发生的任何事情.>

在任何一种情况下,smtp.google.com 端口 465 和 587 上的服务器仍然不会向 MAIL 命令返回 250 响应,因为它们需要您在发送邮件之前已通过身份验证.您将收到 530 响应.您需要使用 AUTH 命令和您的 gmail.com 凭据进行身份验证,然后才能在这些服务器上成功使用 MAIL.

如果您不想进行身份验证,并且根据您需要执行的操作的详细信息,您可以尝试使用在 gmail.com 的 MX 记录中找到的服务器的端口 25.目前,服务器为 gmail-smtp-in.l.google.com 并支持 STARTTLS.

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 = "\r\n I love computer networks!"
endmsg = "\r\n.\r\n"

# 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\r\n'
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: wgimson@gmail.com\r\n'
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: macyali@gmail.com\r\n'
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\r\n'
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\r\n'
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.'

解决方案

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.

这篇关于在 Python 中实现传输层安全性 - 简单邮件客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆