2012-09-26 59 views
7

以下是我當前用於連接到端口587上gmail的smtp服務器的代碼。發出STARTTLS命令後,我將如何完成TLS會話的協商並開始發出諸如AUTH LOGIN和MAIL FROM之類的命令?我已經省略了我的Base64編碼的gmail用戶名,並在我的代碼底部附近用xxxxxxxx取代了它。如何在Python中的活動連接上啓動TLS?

從這個程序我的輸出,因爲它是是:

220 mx.google.com ESMTP y10sm3296641yhd.6

250-mx.google.com爲您服務,[75.66.47.144 ]

250-SIZE 35882577

250-8BITMIME

250 STARTTLS

250 ENHANCEDSTATUSCODES

220 2.0.0準備啓動TLS

from socket import * 
import ssl 
msg = "\r\n smtp.." 
endmsg = "\r\n.\r\n" 

# Mailserver hostname and port to be used. 
mailserver = ("smtp.gmail.com", 587) 


# Create a socket and create an active TCP connection with the mailserver 
clientSocket = socket(AF_INET, SOCK_STREAM); 
clientSocket.connect(mailserver) 

# Read server response 
recv = clientSocket.recv(1024) 
print recv 
if recv[:3] != '220': 
    print '220 reply not received from server.' 

# Send EHLO command and print server response. 
ehloCommand = 'EHLO smtp.google.com\r\n' 
clientSocket.send(ehloCommand) 

recv1 = clientSocket.recv(1024) 
print recv1 
if recv1[:3] != '250': 
    print '250 reply not received from server.' 

# Send STARTTLS command to server and print server response 
command = "STARTTLS\r\n" 
clientSocket.send(command) 

recv1 = clientSocket.recv(1024) 
print recv1 
if recv[:3] != '220': 
    print '220 reply not received from server.' 

# SEND AUTH LOGIN command and Base64 encoded username 
command = "AUTH LOGIN xxxxxxxxxxxxx\r\n" 
clientSocket.send(command) 

recv1 = clientSocket.recv(1024) 
print recv1 
+0

爲什麼不直接使用http://docs.python.org/library/smtplib.html? –

+1

@MK。我想以手動方式做這個練習。 – ripit

+0

我明白了。如果不使用用C編寫的ssl模塊,那麼在某個地方就有一個純python ssl模塊。可能從ssl.wrap_socket開始(self.sock,keyfile,certfile) – swang

回答

10

可以包裹SSL連接的插座。這會給你的想法:

import ssl 
import base64 
from socket import * 


cc = socket(AF_INET, SOCK_STREAM) 
cc.connect(("smtp.gmail.com", 587)) 
# cc.read(..) 

cc.send('helo tester.com\r\n') 
cc.send('starttls\r\n') 
# cc.read(..) If the server responds ok to starttls 
#    tls negotiation needs to happen and all 
#    communication is then over the SSL socket 

scc = ssl.wrap_socket(cc, ssl_version=ssl.PROTOCOL_SSLv23) 
scc.send('auth login\r\n') 
# scc.read(..) 

scc.send(base64.b64encode('username')+'\r\n') 
scc.send(base64.b64encode('password')+'\r\n') 

# css.send(
# mail from: 
# rcpt to: 
# data 
# etc 

看看這個網頁的有關用戶名/密碼編碼信息的AUTH LOGIN部分:http://www.samlogic.net/articles/smtp-commands-reference-auth.htm

在此之後,AUTH LOGIN命令已被送往服務器, 服務器通過向客戶端發送BASE64編碼文本 (問題)來請求用戶名和密碼。在上面的例子中,「VXNlcm5hbWU6」是BASE64編碼文本 的單詞「用戶名」,「UGFzc3dvcmQ6」是BASE64編碼的文本 單詞「密碼」。客戶端還使用BASE64編碼發送 用戶名和密碼。在上面的 示例中,「adlxdkej」是一個BASE64編碼的用戶名,「lkujsefxlj」是一個 BASE64編碼的密碼。

+0

我想補充一點,如果你不在'cc.send('starttls \ r \ n' )',那麼SSL封裝將被服務器的「準備啓動TLS」消息弄糊塗,並給出「未知協議」錯誤。 – wecsam

相關問題