31.2企業級開發進階3.2:接收電子郵件

大牧莫邪發表於2017-06-01

上一節內容中,我們通過Python進行了電子郵件傳送功能的處理 本節內容內容主要講解接收郵件功能的處理

通過SMTP協議傳送郵件,我們通過POP3協議接收郵件

回顧一下郵件傳送的過程 電子郵件 -> MUA -> MTA -> ...MTA -> MDA <- MUA <- 電子郵件

我們傳送郵件主要實現的是MUA->M他的過程

使用的模組如下 email smtplib email.header.Header email.utils.parseaddr/formataddr email.mime.mutipart.MIMEMultipart email.mime.base.MMEBase email.mime.text.MIMEText

本節內容

  • POP3協議簡介
  • 收取郵件

1. POP3協議簡介

1.1簡介

POP3協議,全名為Post Office Protocol - Vesion 3,郵局協議 版本3 POP3協議是TCP/IP協議族中的一種,由RFC1939定義 協議主要用於支援使用客戶端遠端管理在伺服器上的電子郵件 提供了SSL加密的POP3協議被稱為POP3S

POP協議主持離線有限處理,通常情況下郵件傳送到伺服器上,電子郵件客戶端將郵件從郵件伺服器獲取到個人終PC上,郵件伺服器上的郵件會被刪除;目前POP3郵件伺服器大部分可以獲取郵件的同時不刪除伺服器上的郵件

1.2特性

預設埠:110 預設傳輸協議:TCP 使用的軟體結構:C/S 訪問模式:離線訪問

1.3 POP3常見命令碼

POP3常見命令碼

1.4 python中使用POP3

python中提供了poplib模組用於進行POP3協議的支援 核心的處理過程主要是如下兩個步驟 * 使用poplib模組接收郵件 * 使用email模組解析郵件

2. POP3讀取郵箱資訊

常規操作步驟: * 定義連線pop3伺服器的資訊 * 連線pop3伺服器 * 登入pop3伺服器 * 獲取郵件伺服器中郵件的資訊【數量、大小、列表等等】

```

import poplib

# 伺服器連線資訊
pop_user = "xxxxxxxxx@qq.com"
pop_pass = "這裡請使用您的授權碼"
pop_server = "pop.qq.com"

# 連線到pop3伺服器
print("開始連線pop3伺服器")
server = poplib.POP3_SSL(pop_server)
print("連線伺服器成功")
# 設定列印除錯資訊
server.set_debuglevel(1)
# 設定列印pop3服務歡迎文字
print(server.getwelcome().decode("utf-8"))

# 登入伺服器
print("準備登入POP伺服器")
server.user(pop_user)
server.pass_(pop_pass)
print("登入身份驗證成功,準備獲取郵件資訊")

# stat()返回郵件數量和佔用空間
print("郵件數量:%s, 大小:%s" % server.stat())
print("~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~")
# 返回郵件詳細列表資訊mails
resp, mails, octets = server.list()
print(resp)
print(mails)
print(octets)

# 退出伺服器
server.quit()

``` 上述程式碼執行完成後,會出現如下結果: 注意:下面出現*cmd*字樣的是除錯資訊,其中出現的類似USER/PASS等都是POP3的命令碼,可以參考前面的命令碼部分了解一下

開始連線pop3伺服器 連線伺服器成功 +OK QQMail POP3 Server v1.0 Service Ready(QQMail v2.0) 準備登入POP伺服器 cmd 'USER 1007821300@qq.com' cmd 'PASS kyecgawxkkupbegh' 登入身份驗證成功,準備獲取郵件資訊 cmd 'STAT' stat [b'+OK', b'105', b'3796095'] 郵件數量:105, 大小:3796095 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ cmd 'LIST' b'+OK' [b'1 36817', b'2 27060', b'3 1860', b'4 63794', b'5 73282', b'6 5360', b'7 35188', b'8 19933', b'82 7118',·······b'100 2329', b'101 36325', b'102 28107', b'103 28090', b'104 29170', b'105 28088'] 984 cmd 'QUIT'

3. POP3讀取最新的一封普通文字郵件

我們使用上一節中的傳送郵件的程式碼傳送一份純文字的或者帶了HTML標籤的郵件,然後在下面的程式碼中接收一下這份郵件

```

# 引入需要的模組
import email, poplib
from email.parser import Parser
from email.utils import parseaddr
from email.header import decode_header

# 伺服器連線資訊
pop_server = "pop.qq.com"
pop_user = "xxxxxxxx@qq.com"
pop_pass = "此處請使用授權碼"

# 連線pop伺服器
server = pop.POP3_SSL(pop_server)
# 登入pop伺服器,進行身份驗證
server.user(pop_user)
server.pass_(pop_pass)

# 獲取郵件伺服器上的郵件的資訊
email_msg = server.stat()

# 獲取最新的一份郵件
# 注意:接收的郵件是按照索引進行排序的,這裡的索引是1開始的
resp, lines, octets = server.retr(email_msg[0])

# 拼接完整郵件
email_content = b"\r\n".join(lines).decode("UTF-8")

# 解析郵件標題
title = email_content.get("Subject")
if title :
    value, charset = decode_header(title)[0]
    if charset:
        title = value.decode(charset)

# 解析發件人資訊
sender = email_content.get("From")
if sender:
    value, addr = parseaddr(sender)
    name, charset = decode_header(value)
    if charset:
        name = ame.decode(charset)
        sender = u"%s <%s>" % (name, addr)

# 解析收件人資訊
receiver = email_content.get("To")
if receiver:
    value, addr  = parseaddr(receiver)
    name, charset = decode_header(value)
    if charset:
        name = name.decode(charset)
        receiver = u"%s <%s>" % (name, addr)

# 解析郵件內容
content = email_content.get_payload(decode=True)
content = content.decode("UTF-8")

# 列印郵件內容
print("郵件標題:%s" % title)
print("發件人:%s" % sender)
print("收件人:%s" % receiver)
print("郵件內容:%s" % content)

# 退出郵件伺服器
server.quit()

``` 執行上述程式碼,執行結果如下:

郵件標題:來自大牧莫邪的問候 發件人: 大牧莫邪 收件人:木木 郵件內容:Hello 你好,這是一封自動傳送的測試郵件

我們針對上面的程式碼最一下簡單的瞭解

郵件的標題、發件人、收件人,對應的是郵件內容中的Subject,From,To,這三個資料我們在學習完傳送郵件部分之後已經瞭解到,是通過編碼進行處理過的,所以我們要對這樣的編碼進行解碼,解碼的過程比較簡單,通過如下的程式碼就可以進行解碼的處理: ```

# 引入解碼需要的模組
>from email.header import decode_header
from email.utils import parseaddr

> # 定義一個函式,用於解析郵件內容
>def decode_msg(msg)
    # 解析郵件標題、發件人、收件人
>     for info in ["Subject", "From", "To"]:
        value = msg.get(info)
        # 解析郵件標題
        if info == "Subject":
            # 標題不含特殊格式,直接解碼
            name, charset = decode_header(value)[0] 
            value = name.decode(charset)
        else:
            # 發件人、收件人格式特殊,使用parseaddr解析之後再進行解碼
            value, addr = parseaddr(msg)
            name, charset = decode_header(value)[0]
            value = name.decode_header(charset)

接下來就是內容的解析了,關於郵件內容的處理,我們從前面的傳送郵件就知道,郵件內容主要是普通文字郵件包裝的服務類MIMEText或者是帶了附件的混合服務類MIMEMultipart,針對郵件的處理,只需要將郵件內容解析為Message物件,在後續處理過程中就可以方便的進行格式化,解析非常簡單

# 引入解析需要的模組
from email.parser import Parser
# 解析郵件內容
content = Parse().parsestr(email_content)

```

4. POP3讀取最新的帶附件的郵件

某些情況下,我們的郵件內容是帶附件的,是通過MIMEMultipart物件包含的郵件內容和附件,我們通常情況下,需要對MIMEMultipart物件進行遍歷,對其中的MIMEText物件表示的郵件內容和MIMEBase物件表示的附件內容進行分別解析。

廢話不多說,上乾貨: 第一步:分清楚什麼是郵件標題、發件人、收件人;什麼是郵件內容;什麼是郵件附件 通過is_multipart()函式來區分郵件是否是混合郵件 通過get_content_type()函式來區分郵件是否是內容/附件 ```

# 引入需要的模組
import email, poplib
from email.parser import Parser
from email.utils import parseaddr
from email.header import decode_header


# 定義解析郵件內容的函式
def decode_mail(msg):
    # 解析郵件標題、發件人、收件人資訊
    for info in ["Subject", "From", "To"]:
        value = msg.get(info)

        if info == "Subject":# 解析郵件標題
            title = decode_info(value)
        else:# 解析發件人、收件人資訊
            name, addr = parseaddr(value)
            sender = decode_info(name)
            sender = "%s <%s>" % (name, addr)

    # 如果郵件是MIMEMultipart混合內容,執行遞迴處理
    if(msg.is_multipart()):
        parts = msg.get_payload()
        for n, part in enumerate(parts):
            print(n, part)
            # 遞迴解析郵件
            decode_mail(part)
    else:
        # 獲取郵件編碼格式
        content_type = msg.get_content_type();
        # 判斷編碼並解碼
        if content_type == "text/plain" or content_type == "text/html":
            content = "這是郵件內容"
        else:
            content = "這是郵件附件"

# decode_header解碼操作函式
def decode_info(info):
    name, charset = decode_header(info)
    if charset:
        name = name.decode(charset)
    return name

```

上面的程式碼中,我們定義了函式decode_mail(msg)來進行郵件內容的解析處理 主要包含三部分內容 1.首先解析郵件標題、發件人、收件人這樣的特殊的資訊 2.根據is_multipart()函式區分是否混合郵件 3.根據msg.get_content_type()函式進行郵件內容和附件的區分處理


未完待續,敬請期待~~

大牧莫邪.png

相關文章