1. 程式人生 > >python3讀取解析郵件內容

python3讀取解析郵件內容

SMTP用於傳送郵件,如果要收取郵件呢?

收取郵件就是編寫一個MUA作為客戶端,從MDA把郵件獲取到使用者的電腦或者手機上。收取郵件最常用的協議是POP協議,目前版本號是3,俗稱POP3

Python內建一個poplib模組,實現了POP3協議,可以直接用來收郵件。

注意到POP3協議收取的不是一個已經可以閱讀的郵件本身,而是郵件的原始文字,這和SMTP協議很像,SMTP傳送的也是經過編碼後的一大段文字。

要把POP3收取的文字變成可以閱讀的郵件,還需要用email模組提供的各種類來解析原始文字,變成可閱讀的郵件物件。

所以,收取郵件分兩步:

第一步:用poplib把郵件的原始文字下載到本地;

第二部:用email解析原始文字,還原為郵件物件。

通過POP3下載郵件

POP3協議本身很簡單,以下面的程式碼為例,我們來獲取最新的一封郵件內容:

import poplib

# 輸入郵件地址, 口令和POP3伺服器地址:
email = input('Email: ')
password = input('Password: ')
pop3_server = input('POP3 server: ')

# 連線到POP3伺服器:
server = poplib.POP3(pop3_server)
# 可以開啟或關閉除錯資訊:
server.set_debuglevel(1)
# 可選:列印POP3伺服器的歡迎文字:
print(server.getwelcome().decode('utf-8')) # 身份認證: server.user(email) server.pass_(password) # stat()返回郵件數量和佔用空間: print('Messages: %s. Size: %s' % server.stat()) # list()返回所有郵件的編號: resp, mails, octets = server.list() # 可以檢視返回的列表類似[b'1 82923', b'2 2184', ...] print(mails) # 獲取最新一封郵件, 注意索引號從1開始: index = len(mails) resp, lines, octets = server.retr(index) # lines儲存了郵件的原始文字的每一行,
# 可以獲得整個郵件的原始文字: msg_content = b'\r\n'.join(lines).decode('utf-8') # 稍後解析出郵件: msg = Parser().parsestr(msg_content) # 可以根據郵件索引號直接從伺服器刪除郵件: # server.dele(index) # 關閉連線: server.quit()

用POP3獲取郵件其實很簡單,要獲取所有郵件,只需要迴圈使用retr()把每一封郵件內容拿到即可。真正麻煩的是把郵件的原始內容解析為可以閱讀的郵件物件。

解析郵件

解析郵件的過程和上一節構造郵件正好相反,因此,先匯入必要的模組:

from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

import poplib

只需要一行程式碼就可以把郵件內容解析為Message物件:

msg = Parser().parsestr(msg_content)

但是這個Message物件本身可能是一個MIMEMultipart物件,即包含巢狀的其他MIMEBase物件,巢狀可能還不止一層。

所以我們要遞迴地打印出Message物件的層次結構:

# indent用於縮排顯示:
def print_info(msg, indent=0):
    if indent == 0:
        for header in ['From', 'To', 'Subject']:
            value = msg.get(header, '')
            if value:
                if header=='Subject':
                    value = decode_str(value)
                else:
                    hdr, addr = parseaddr(value)
                    name = decode_str(hdr)
                    value = u'%s <%s>' % (name, addr)
            print('%s%s: %s' % ('  ' * indent, header, value))
    if (msg.is_multipart()):
        parts = msg.get_payload()
        for n, part in enumerate(parts):
            print('%spart %s' % ('  ' * indent, n))
            print('%s--------------------' % ('  ' * indent))
            print_info(part, indent + 1)
    else:
        content_type = msg.get_content_type()
        if content_type=='text/plain' or content_type=='text/html':
            content = msg.get_payload(decode=True)
            charset = guess_charset(msg)
            if charset:
                content = content.decode(charset)
            print('%sText: %s' % ('  ' * indent, content + '...'))
        else:
            print('%sAttachment: %s' % ('  ' * indent, content_type))

郵件的Subject或者Email中包含的名字都是經過編碼後的str,要正常顯示,就必須decode:

def decode_str(s):
    value, charset = decode_header(s)[0]
    if charset:
        value = value.decode(charset)
    return value

decode_header()返回一個list,因為像CcBcc這樣的欄位可能包含多個郵件地址,所以解析出來的會有多個元素。上面的程式碼我們偷了個懶,只取了第一個元素。

文字郵件的內容也是str,還需要檢測編碼,否則,非UTF-8編碼的郵件都無法正常顯示:

def guess_charset(msg):
    charset = msg.get_charset()
    if charset is None:
        content_type = msg.get('Content-Type', '').lower()
        pos = content_type.find('charset=')
        if pos >= 0:
            charset = content_type[pos + 8:].strip()
    return charset

把上面的程式碼整理好,我們就可以來試試收取一封郵件。先往自己的郵箱發一封郵件,然後用瀏覽器登入郵箱,看看郵件收到沒,如果收到了,我們就來用Python程式把它收到本地:

2015-06-25/558b9f66bbd13

執行程式,結果如下:

+OK Welcome to coremail Mail Pop3 Server (163coms[...])
Messages: 126\. Size: 27228317

From: Test <[email protected]>
To: Python愛好者 <[email protected]>
Subject: 用POP3收取郵件
part 0
--------------------
  part 0
  --------------------
    Text: Python可以使用POP3收取郵件……...
  part 1
  --------------------
    Text: Python可以<a href="...">使用POP3</a>收取郵件……...
part 1
--------------------
  Attachment: application/octet-stream

我們從列印的結構可以看出,這封郵件是一個MIMEMultipart,它包含兩部分:第一部分又是一個MIMEMultipart,第二部分是一個附件。而內嵌的MIMEMultipart是一個alternative型別,它包含一個純文字格式的MIMEText和一個HTML格式的MIMEText

小結

用Python的poplib模組收取郵件分兩步:第一步是用POP3協議把郵件獲取到本地,第二步是用email模組把原始郵件解析為Message物件,然後,用適當的形式把郵件內容展示給使用者即可。

轉載至https://www.kancloud.cn/thinkphp/python-guide/39542

相關推薦

python3讀取解析郵件內容

SMTP用於傳送郵件,如果要收取郵件呢? 收取郵件就是編寫一個MUA作為客戶端,從MDA把郵件獲取到使用者的電腦或者手機上。收取郵件最常用的協議是POP協議,目前版本號是3,俗稱POP3。 Python內建一個poplib模組,實現了POP3協議,可以直接用來收郵件。 注意到POP3協議收取的不是一個已經可

JavaMail解析郵件內容(經典收藏)

import java.io.*; import java.text.*; import java.util.*; import javax.mail.*; import javax.mail.internet.*; /**

javaMail解析郵件內容和下載附件

介紹一下JavaMail的Message 它對應JavaMail的Message物件,一個Message物件又會有多個子物件如MultiPart物件,更特殊的是整個郵件內容為一個大的 MultiPart,然而郵件的正文則在巢狀的一個子MultiPart中,如果不瞭解這種組織

java讀取txt檔案並解析內容

package readtext;/* @author wb @great forever i think,therefor i am */ import java.io.BufferedReader; import java.io.FileInputStream; import java

python3讀取日誌檔案的最後一行內容

(1)模擬建立一個日誌檔案.txt 關鍵字 日期和時間 來源 事件ID 任務類別 稽核成功 2018/9/11 12:17:15 Security-Auditing 4672 Special Logon 稽核成功

python3 讀取檔案跳過檔案第一行內容

Python程式設計時,經常需要跳過第一行讀取檔案內容。比較容易想到是為每行設定一個line_num,然後判斷line_num是否為1,如果不等於1,則進行讀取操作。相應的Python程式碼如下: #input_file = open("C:\\Pytho

python3接收、解析郵件

郵件接收 python3可以使用poplib.POP3進行郵件接收,具體如下: import poplib from email.parser import Parser def get_email(email,password,host="mail.djicorp.com"): # conne

讀檔案 —— WEB前端讀取本地檔案內容哪些事(前臺解析txt檔案)……

強制讓瀏覽器允許JS讀寫本地檔案……的操作!問題描述:讓自己的瀏覽器允許js讀寫本地檔案,儘可能多的相容各種瀏覽器。(即本機的js檔案讀寫本機的檔案)問題回覆——1:您的意思是不需要瀏覽器與使用者互動直接操作使用者機上的檔案?不符合瀏覽器的安全標準,屬於瀏覽器的設計缺陷所以瀏

php讀取郵件內容含附件

一,控制器檔案<?php @header('Content-type: text/html;charset=UTF-8'); error_reporting(0); ignore_user_abort(); // run script in background set

Python3讀取載入並執行JS後的內容

使用PyQt5.9,由於H5才用延遲載入技術,所以如果直接用urlopen開啟網頁再用read讀,讀到的時JS未執行時的內容。 import sys from PyQt5.QtCore import QEventLoop,QUrl from PyQt5.QtWebEngi

深入學習python解析讀取PDF檔案內容的方法

這篇文章主要學習了python解析並讀取PDF檔案內容的方法,包括對學習庫的應用,python2.7和python3.6中python解析PDF檔案內容庫的更新,包括對pdfminer庫的詳細解釋和應用。主要參考了一些已有的部落格內容,程式碼。   主要思路是首先利用一個做

fsockopen用feof讀取http響應內容的一些問題

content 錯誤 www http響應 pragma control 代碼 write warn 在前面三個例子中,都有這麽一段代碼: while (!feof($fp)) { // 讀取文件/數據 //$content .= fgets($fp, 1

Java程序設計---io流讀取文件內容並將其逆值輸出到控制臺

java 格式 ext buffered import write [] back style import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import ja

BufferedReader 讀取文件內容,原樣輸出

nec ati java buffered system har 運行 寫入 讀取文件 1.新建目標類: package com.xuzhiwen.io; public class TargetFile { public static void main(Str

python3獲取指定目錄內容的詳細信息

logs python3 技術分享 1.3 join getc creat rsize 命令 不同平臺獲取指定目錄內容的詳細信息命令各不相同: Linux中可以通過ls -al獲取獲取 windows中可以通過dir命令獲取

PHP讀取文件內容的五種方式

ria feof function word man val toolbar article str php讀取文件內容的五種方式 分享下php讀取文件內容的五種方法:好吧,寫完後發現文件全部沒有關閉。實際應用當中,請註意關閉 fclose($fp);-- php讀取文件內

[Python3]JSON解析

pri left json tin code log ber obj testin 概述 本章節將為大家介紹如何使用Python來編碼和解碼json對象。 json是javascript object notation的簡寫,是一種輕量級的數據交換格式,易於閱讀和編寫,

讀取文件內容

clas import exceptio ati adf java readfile con app package bianchengti; import java.io.BufferedReader; import java.io.FileInputStream;

Java中使用字節流類讀取文本內容

length inpu pre puts output 寫入 log oid cnblogs package cn.jbit.inputstream; import java.io.File; import java.io.FileInputStream; import

Go -- 讀取文件內容

簡單的 std func 速查 all pen port 平衡 write Golang 的文件讀取方法很多,剛上手時不知道怎麽選擇,所以貼在此處便後速查。 一次性讀取 小文件推薦一次性讀取,這樣程序更簡單,而且速度最快。 代碼如下: func ReadAl