收取郵件有兩種方式,一種是POP3, 另外一種是IMAP,它們都是收取郵件服務器支持的協議,咱們用foxmail進行郵件的收發,感受不到收發的流程,而實際上收和發是做用在不一樣的服務器上,發郵件有專門的發郵件服務器,收郵件也有專門的收郵件服務器,發郵件只負責發送無論收取,同時收取郵件也無論如何發郵件,所以在測試時收和發郵件是分開進行的,雖然大多數時候收發郵件服務是裝在一個服務器上,但測試測的是協議,如SMTP, 如POP3, IMAP,python中的poplib收取郵件仍是很是簡單的,重點是收來的郵件須要解析,由於SMTP是進行編碼過的,收來的郵件須要進行處理後才能被咱們閱讀,所以又要用到email模塊,SMTP用email來傳遞內容,POP3用email來解析內容html
poplibpython
#返回全部郵件的編號 list(self,which=None): ['response',['message_count, octets'],octets]/[scan listing for the message] ----------------------------- ('+OK 7 messages:', ['1 1080', '2 1080', '3 1079', '4 675265', '5 675506', '6 675534', '7 597'], 61) #收取整封郵件,索引號必需從1開始 retr(self,which): return whole message of number which #身份認證 user(self,user) pass_(self.pwd) #顯示調試信息 set_debuglevel(self,level) #返回郵件數量和郵件大小 stat(self) get mailbox size return(mail_counter, mailbox_size) ------------------------------------------- (7, 2030141) #顯示郵件的頭信息,以及定製正文數據 top(self,which,howmuch) return head of message of which, and how much lines of body message
原郵件以下:服務器
26169 From hding@hding.com Tue Aug 16 20:06:02 2016 26170 Return-Path: <hding@hding.com> 26171 Received: from hding.com ([192.168.10.3]) 26172 by ding.com (8.13.8/8.13.8) with ESMTP id u7GC623I002429 26173 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) 26174 for <qa@ding.com>; Tue, 16 Aug 2016 20:06:02 +0800 26175 Received: from 10.8.116.6 ([10.8.116.6]) 26176 (authenticated bits=0) 26177 by hding.com (8.13.8/8.13.8) with ESMTP id u7GC0v9x027721 26178 for qa@ding.com; Tue, 16 Aug 2016 20:05:13 +0800 26179 Date: Tue, 16 Aug 2016 20:00:57 +0800 26180 From: hding@hding.com 26181 Message-Id: <201608161205.u7GC0v9x027721@hding.com> 26182 X-UID: 71 26183 Status: O 26184 26185 "hello world" 26186 I am terry 26187 please welcome me
top(7,1)函數返回的第7封郵件的頭信息,1行正文,是一個元組函數
('+OK', ['Return-Path: <hding@hding.com>', 'Received: from hding.com ([192.168.10.3])', '\tby ding.com (8.13.8/8.13.8) with ESMTP id u7GC623I002429', '\t(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)', '\tfor <qa@ding.com>; Tue, 16 Aug 2016 20:06:02 +0800', 'Received: from 10.8.116.6 ([10.8.116.6])', '\t(authenticated bits=0)', '\tby hding.com (8.13.8/8.13.8) with ESMTP id u7GC0v9x027721', '\tfor qa@ding.com; Tue, 16 Aug 2016 20:05:13 +0800', 'Date: Tue, 16 Aug 2016 20:00:57 +0800', 'From: hding@hding.com', 'Message-Id: <201608161205.u7GC0v9x027721@hding.com>', '', '"hello world"'], 566)
retr(7) 函數返回整封郵件,是一元組,內容在retr(7)[1]測試
('+OK 597 octets', ['Return-Path: <hding@hding.com>', 'Received: from hding.com ([192.168.10.3])', '\tby ding.com (8.13.8/8.13.8) with ESMTP id u7GC623I002429', '\t(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)', '\tfor <qa@ding.com>; Tue, 16 Aug 2016 20:06:02 +0800', 'Received: from 10.8.116.6 ([10.8.116.6])', '\t(authenticated bits=0)', '\tby hding.com (8.13.8/8.13.8) with ESMTP id u7GC0v9x027721', '\tfor qa@ding.com; Tue, 16 Aug 2016 20:05:13 +0800', 'Date: Tue, 16 Aug 2016 20:00:57 +0800', 'From: hding@hding.com', 'Message-Id: <201608161205.u7GC0v9x027721@hding.com>', '', '"hello world"', 'I am terry', 'please welcome me'], 597)
只取正文信息只須要把retr獲得的所有信息減掉頭信息便可編碼
head = pop.top(7,0) message = pop.retr(7) body = [line for line in message[1] if line not in head[1]]
若是郵件有附件如何處理debug
retr()收到的郵件是一個多字段的列表,還談不上是郵件,須要經過mail.parser去解析,解析出來的郵件將符合郵件的格式,如Mail From, Mail To, 等調試
獲取第7封開始的郵件 messages = [pop_conn.retr(i) for i in range(7, pop_conn.stat()[0]+1)] -------------------------------------------------------------------------- [('+OK 597 octets', ['Return-Path: <hding@hding.com>', 'Received: from hding.com ([192.168.10.3])', '\tby ding.com (8.13.8/8.13.8) with ESMTP id u7GC623I002429', '\t(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)', '\tfor <qa@ding.com>; Tue, 16 Aug 2016 20:06:02 +0800', 'Received: from 10.8.116.6 ([10.8.116.6])', '\t(authenticated bits=0)', '\tby hding.com (8.13.8/8.13.8) with ESMTP id u7GC0v9x027721', '\tfor qa@ding.com; Tue, 16 Aug 2016 20:05:13 +0800', 'Date: Tue, 16 Aug 2016 20:00:57 +0800', 'From: hding@hding.com', 'Message-Id: <201608161205.u7GC0v9x027721@hding.com>', '', '"hello world"', 'I am terry', 'please welcome me'], 597)] 給每封郵件中的內容以'\n'字符做爲鏈接符造成字符串 messages = ["\n".join(msg[1]) for msg in messages] --------------------------------------------------------------------------- ['Return-Path: <hding@hding.com>\nReceived: from hding.com ([192.168.10.3])\n\tby ding.com (8.13.8/8.13.8) with ESMTP id u7GC623I002429\n\t(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)\n\tfor <qa@ding.com>; Tue, 16 Aug 2016 20:06:02 +0800\nReceived: from 10.8.116.6 ([10.8.116.6])\n\t(authenticated bits=0)\n\tby hding.com (8.13.8/8.13.8) with ESMTP id u7GC0v9x027721\n\tfor qa@ding.com; Tue, 16 Aug 2016 20:05:13 +0800\nDate: Tue, 16 Aug 2016 20:00:57 +0800\nFrom: hding@hding.com\nMessage-Id: <201608161205.u7GC0v9x027721@hding.com>\n\n"hello world"\nI am terry\nplease welcome me'] 解析文件內容 messages = [parser.Parser().parsestr(msg) for msg in messages] ------------------------------------------------------------------------------ [<email.message.Message instance at 0x02C1C9B8>] 返回了一個message的實例 獲取單封郵件message內容 for message in messages: print message -------------------------------------------------------------------------------- From nobody Wed Aug 17 19:04:31 2016 Return-Path: <hding@hding.com> Received: from hding.com ([192.168.10.3]) by ding.com (8.13.8/8.13.8) with ESMTP id u7GC623I002429 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for <qa@ding.com>; Tue, 16 Aug 2016 20:06:02 +0800 Received: from 10.8.116.6 ([10.8.116.6]) (authenticated bits=0) by hding.com (8.13.8/8.13.8) with ESMTP id u7GC0v9x027721 for qa@ding.com; Tue, 16 Aug 2016 20:05:13 +0800 Date: Tue, 16 Aug 2016 20:00:57 +0800 From: hding@hding.com Message-Id: <201608161205.u7GC0v9x027721@hding.com> "hello world" I am terry please welcome me ---------------------------------------------------------------------------------- 從上文能夠看出解析的很是好,如何區別附件和正文 for part in message.walk(): #遍歷郵件內容 fileName = part.get_filename() #獲得附件名 contentType = part.get_content_type() #獲得附件類型 # 保存附件 if fileName: #若是有附件則必定會有文件名 #附件從新寫到新的文件中 data = part.get_payload(decode=True) f_attach = open(fileName, 'wb') f_attach.write(data) f_attach.close() elif contentType == 'text/plain' or contentType == 'text/html': #正文照抄到正文中 #保存正文 data = part.get_payload(decode=True) print data ---------------------------------------------------------------------------------- "hello world" I am terry please welcome me
帶附件的郵件code
26229 From hding@hding.com Wed Aug 17 19:21:08 2016 fist part 26230 Return-Path: <hding@hding.com> 26231 Received: from hding.com ([192.168.10.3]) 26232 by ding.com (8.13.8/8.13.8) with ESMTP id u7HBL8rW015601 26233 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) 26234 for <qa@ding.com>; Wed, 17 Aug 2016 19:21:08 +0800 26235 Received: from ding.com ([10.10.10.3]) 26236 (authenticated bits=0) 26237 by hding.com (8.13.8/8.13.8) with ESMTP id u7HBL7sl008349 26238 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) 26239 for <qa@ding.com>; Wed, 17 Aug 2016 19:21:07 +0800 26240 Date: Wed, 17 Aug 2016 19:21:07 +0800 26241 Message-Id: <201608171121.u7HBL7sl008349@hding.com> 26242 Content-Type: multipart/mixed; boundary="===============4712348666551551578==" 26243 MIME-Version: 1.0 26244 From: hding@hding.com 26245 To: qa@ding.com 26246 Subject: test_mail 26247 X-UID: 73 26248 Status: RO 26249 26250 --===============4712348666551551578== second part 26251 Content-Type: doc/test_file 26252 MIME-Version: 1.0 26253 Content-Disposition: attachment; filename="test_file" 26254 Content-Transfer-Encoding: base64 26255 26256 aGVsbG8gd29ybGQKCkkgYW0gYSB0ZXN0IGZpbGUsIGNhbiB5b3UgcmVhZCBpdCAKCmFuZCBnaXZl 26257 IG1lIGEgcmVzcG9uc2UK 26258 26259 --===============4712348666551551578== third part 26260 Content-Type: text/plain; charset="utf-8" 26261 MIME-Version: 1.0 26262 Content-Transfer-Encoding: base64 26263 26264 aGVsbG8gd29ybGQKCkkgYW0gYSB0ZXN0IGZpbGUsIGNhbiB5b3UgcmVhZCBpdCAKCmFuZCBnaXZl 26265 IG1lIGEgcmVzcG9uc2UKPGltYWdlIHNyYz0nY2lkOjEnPg== 26266 26267 --===============4712348666551551578==--
在工做中,因爲我只須要在pop3上進行收文件便可,無需真實下載下來,所以只須要retr函數就完成任務server
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 from poplib import POP3_SSL 5 6 class DPI_SSL_POP3(object): 7 8 def __init__(self,username='username',password='password',host='192.168.10.3'): 9 self.pop = POP3_SSL(host) 10 self.pop.user(username) 11 self.pop.pass_(password) 12 13 def get_message_from_pop3s(self): 14 self.pop.retr(self.pop.stat()[0]) #最新一封郵件 15 16 17 if __name__ == '__main__': 18 19 pops = DPI_SSL_POP3() 20 pops.get_message_from_pop3s()
pop3 server在WAN側, 我在LAN側執行腳本,收取帶有病毒的附件,病毒通過Firewall,進行檢測