2013-11-02 126 views
2

我必須在Python中爲類編寫一個SMTP郵件客戶端,並且卡在作業的第一部分。經過很多麻煩我已經得到了這麼多(目前使用免費的便攜式SMTP服務器,但以後需要使用SSL或TLS的Gmail)。以下是我的代碼。當它到達代碼的RCPT TO部分時,我得到一個500語法錯誤。誰能幫忙?SMTP郵件客戶端Python

from socket import * 
msg = "\r\n I love computer networks!" 
endmsg = "\r\n.\r\n" 

# Choose a mail server 
mailServer = 'localhost' 
mailPort = 25 

# Create socket called clientSocket and establish a TCP connection with mailserver 
clientSocket = socket(AF_INET,SOCK_STREAM) 
clientSocket.connect((mailServer, mailPort)) 
recv = clientSocket.recv(1024) 
print 'test' 
print recv 
if recv[:3] != '220': 
    print '220 reply not received from server.' 

# Send HELLO command and print server response. 
helloCommand = 'HELO Alice\r\n'; 
clientSocket.send(helloCommand) 
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) 
#recva = clientSocket.recv(1024) 
#print(recva) 
mailfromCommand = 'MAIL FROM: <[email protected]>\r\n.' 
clientSocket.send(mailfromCommand) 
recv1 = clientSocket.recv(1024) 
print(recv1) 
if recv1[:3] != '250': 
    print('mail from 250 reply not received from server.') 

# Send RCPT TO command and print server response. 
rcpttoCommand = 'RCPT TO: <[email protected]>\r\n' 
clientSocket.send(rcpttoCommand) 
recv1 = clientSocket.recv(1024) 
print(recv1) 
if recv1[:3] != '250': 
    print('rcpt to 250 reply not received from server.') 

# Send DATA command and print server response 
dataCommand = 'Data' 
print(dataCommand) 
clientSocket.send(dataCommand) 
recv1 = clientSocket.recv(1024) 
print(recv1) 
if recv1[:3] != '250': 
    print('data 250 reply not received from server.') 

# Send message data. 
message = raw_input('Enter Message Here: ') 

# Fill in end# Message ends with a single period. 
mailMessageEnd = '\r\n.\r\n' 
clientSocket.send(message + mailMessageEnd) 
recv1 = clientSocket.recv(1024) 
print(recv1) 
if recv1[:3] != '250': 
    print('end msg 250 reply not received from server.') 

# Send QUIT command and get server response. 
quitCommand = 'Quit\r\n' 
print(quitCommand) 
clientSocket.send(quitCommand) 
recv1 = clientSocket.recv(1024) 
print(recv1) 
if recv1[:3] != '250': 
    print('quit 250 reply not received from server.') 

    pass 

if __name__ == '__main__': 
    main() 

結果:

test 
220 localhost 


250 Hello localhost 


250 [email protected] Address Okay 


RCPT TO: <[email protected]> 


500 Syntax Error 


rcpt to 250 reply not received from server. 
Data 
+0

您是否被禁止使用標準庫和/或第三方軟件包中的['smtplib'](http://docs.python.org/2/library/smtplib.html)? – abarnert

+0

同時,[TCP套接字是字節流,而不是消息流](http://stupidpythonideas.blogspot.com/2013/05/sockets-are-byte-streams-not-message.html)。每個'recv'可以從服務器獲得半行數據,或者七個半行;你不能假設每個人都得到一條線。你需要緩衝和解析。或者只是使用'makefile'讓Python做到這一點(它適用於像SMTP這樣的任何一行一行的協議),並且使用'sendall'而不是'send',就完成了。 – abarnert

+0

我們得到了一個基本的骨架代碼,直到MAIL FROM命令完成。之後,我們必須填寫其餘的。 – user2946832

回答

1

最可能出現的問題,這是一個:

mailfromCommand = 'MAIL FROM: <[email protected]>\r\n.' 

注意額外的.在結束了嗎?所以,您發送的服務器最終被:

MAIL FROM: <[email protected]> 
.RCPT TO: <[email protected]> 

而且.RCPT是一個語法錯誤。


但是,在代碼中還有兩個非常嚴重的問題。

第一個是不能保證send發送給你的所有數據。這就是爲什麼它返回實際發送的字節數。所以,你可能很容易把它發送給一個命令的一部分。

這一個是微不足道的解決:只使用sendall而不是send


第二個問題是,不能保證每個recv只會得到一行數據。一個recv可能會得到6個字符,然後是下一個19行。 TCP sockets are byte streams, not message streams,您可以根據協議在其上爲其構建消息流。

想象一下,如果在recv之後得到250 [email protected] Addr,接下來ess OK\r\n250 [email protected] Address OK\r\n會發生什麼情況。你要檢查第二個是否以250開頭,發現它沒有,並失敗。

這個問題在一般情況下並不像解決問題那麼簡單 - 通常您必須緩衝和解析消息,這意味着要麼編寫一個生成器,要麼完全重新組織代碼。

但是在像SMTP這樣的逐行協議的情況下,很容易:只需使用makefile,它可以讓您返回一個文件對象,您可以迭代或調用readline,它會奇蹟般地處理緩衝您。


看起來所有這三個錯誤顯然都在你老師給你的代碼中。更別說在helloCommand = 'HELO Alice\r\n'(這是一個由實際上並不知道Python的人編寫的代碼的紅色標誌)結尾的流浪分號。你可能想要閱讀Socket Programming HOWTO,或者更好的是,一個更完整的教程(Google可以爲你找到),這樣你就可以學習如何真正編寫工作程序,而不是破壞性的廢話,幾乎99%的時間在本地主機上運行當電腦的平臺不太忙時。

+0

謝謝你的收穫。我非常感謝你的幫助,但它看起來像這個骨架代碼也來自我們的教科書。我之前從未使用Python進行過編程,所以我只是試圖讓它起作用。我已經通過了這個錯誤,但現在當我回到「在這裏輸入信息:」的部分時,我在shell中得到提示並輸入消息並回車,但是程序什麼都不做。我做了一些谷歌搜索,看到了這個人的視頻,我看不出他和我的代碼之間有很多差異。 http://strantalis.wordpress.com/2012/10/14/python-assignment-3-smtp-client/ – user2946832

+0

@ user2946832:堆棧溢出不是一個很好的方式讓別人來互動地調試你的程序,修復你的每個問題一個接一個地跑。你問爲什麼你得到那500錯誤,我解釋了它,現在你的代碼的那部分工作。如果你有一個新問題,並且你認爲值得問這個問題,接受這個答案,然後問一個新問題(把每個問題鏈接到另一個問題)。 – abarnert

+0

@ user2946832:與此同時,額外的「。」在教科書裏?然後進入教科書的網站,看看他們是否有「勘誤」部分。如果他們這樣做,它應該告訴你他們發佈的代碼中的所有錯誤,以及如何修復它們。 – abarnert