使用 Python 连接到 SMTP(SSL 或 TLS)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12854572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Connect to SMTP (SSL or TLS) using Python
提问by user1287523
I am attempting to connect to the Gmail SMTP mail server and perform tasks as outlined by the skeleton code given to me. Only the use of sockets is allowed (so not the smtplib). I need to: send HELOcommand, MAIL FROM, RCPT TO, and DATA.
我正在尝试连接到 Gmail SMTP 邮件服务器并执行给我的骨架代码所概述的任务。只socket允许使用s (所以不允许使用smtplib)。我需要:发送HELO命令MAIL FROM、RCPT TO、 和DATA。
There are many cases of similar problems posted, but they haven't received the proper answer. For example: Implementing Transport Layer Security in Python - Simple Mail Client
类似问题的案例已经发布了很多,但都没有得到正确的答案。例如: 在 Python 中实现传输层安全性 - 简单邮件客户端
The program is required to connect to smtp.gmail.comover port 587. I've taken two different approaches:
该程序需要smtp.gmail.com通过端口连接587。我采取了两种不同的方法:
Using STARTTLS:
mailserver = 'smtp.gmail.com' clientSocket = socket(AF_INET, SOCK_STREAM) clientSocket.connect((mailserver, 587)) recv = clientSocket.recv(1024) print recv if recv[:3] != '220': print '220 reply not received from server.' #Send HELO command and print server response heloCommand = 'HELO Alice\r\n' clientSocket.send(heloCommand) recv1 = clientSocket.recv(1024) print recv1 if recv1[:3] != '250': print '250 reply not received from server.' #Send MAIL FROM command and print server response. command = "STARTTLS\r\n" clientSocket.send(command) recvdiscard = clientSocket.recv(1024) print recvdiscard clientSocket.send("MAIL From: email\r\n") recv2 = clientSocket.recv(1024) print recv2 if recv2[:3] != '250': print '250 reply not received from server.'Using SSL:
clientSocketSSL = ssl.wrap_socket(clientSocket)Then
clientSocketSSLreplaces all instances ofclientSocket. The STARTTLS lines are also removed andimport sslis added to the top.
使用 STARTTLS:
mailserver = 'smtp.gmail.com' clientSocket = socket(AF_INET, SOCK_STREAM) clientSocket.connect((mailserver, 587)) recv = clientSocket.recv(1024) print recv if recv[:3] != '220': print '220 reply not received from server.' #Send HELO command and print server response heloCommand = 'HELO Alice\r\n' clientSocket.send(heloCommand) recv1 = clientSocket.recv(1024) print recv1 if recv1[:3] != '250': print '250 reply not received from server.' #Send MAIL FROM command and print server response. command = "STARTTLS\r\n" clientSocket.send(command) recvdiscard = clientSocket.recv(1024) print recvdiscard clientSocket.send("MAIL From: email\r\n") recv2 = clientSocket.recv(1024) print recv2 if recv2[:3] != '250': print '250 reply not received from server.'使用 SSL:
clientSocketSSL = ssl.wrap_socket(clientSocket)然后
clientSocketSSL替换 的所有实例clientSocket。STARTTLS 行也被删除并import ssl添加到顶部。
When using the first method, the MAIL FROM:command isn't returning anything. I'm getting the following output:
使用第一种方法时,该MAIL FROM:命令不返回任何内容。我得到以下输出:
250 mx.google.com at your service
220 2.0.0 Ready to start TLS
250 reply not received from server.
When using SSL, I'm getting the same as the linked post:
使用 SSL 时,我得到的与链接的帖子相同:
ssl.SSLError: [Errno 1] _ssl.c:504: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
Am I missing something here? I guess my best option is to use TLS but I have no idea how to go about that... is there something wrong with my MAIL FROMcommand?
我在这里错过了什么吗?我想我最好的选择是使用 TLS,但我不知道该怎么做……我的MAIL FROM命令有问题吗?
采纳答案by Aleksi Torhamo
When using SSL, you need to connect to port 465 instead of port 587. If you use STARTTLS, you still need to use ssl.wrap_socket, you just do it later - specifically, after receiving the 220response to the STARTTLScommand. After doing STARTTLS, you're supposed to do HELOagain, since the server is supposed to forget anything that happened before the STARTTLS.
使用SSL时,需要连接465端口而不是587端口。如果使用STARTTLS,仍然需要使用ssl.wrap_socket,以后再做——特别是在收到命令的220响应后STARTTLS。做完之后STARTTLS,你应该再做HELO一次,因为服务器应该忘记在STARTTLS.
In either case, the servers at smtp.google.com ports 465 and 587 still won't return a 250response to the MAILcommand, since they require that you are authenticated before you send mail. You'll get a 530response instead. You'll need to use the AUTHcommand with your gmail.com credentials to authenticate before you can use MAILsuccessfully on those servers.
在任何一种情况下,smtp.google.com 端口 465 和 587 上的服务器仍然不会返回250对MAIL命令的响应,因为它们要求您在发送邮件之前进行身份验证。您会收到530回复。您需要使用AUTH带有 gmail.com 凭据的命令进行身份验证,然后才能MAIL在这些服务器上成功使用。
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.
如果您不想进行身份验证,并且根据您需要执行的操作的详细信息,您可以尝试使用在 gmail.com 的 MX 记录中找到的服务器的端口 25。目前,服务器为 gmail-smtp-in.l.google.com 并支持 STARTTLS。
回答by ChadJiang
After STARTTLS, call
之后STARTTLS,调用
clientSocket = ssl.wrap_socket(clientSocket)

