So verwenden Sie die Module email, smtplib, poplib und imaplib zum Senden und Empfangen von E-Mails in Python

PHPz
Freigeben: 2023-05-16 23:44:26
nach vorne
1703 Leute haben es durchsucht

Der Weg einer E-Mail ist:

  • Mail User Agent (MUA) bezieht sich auf einen E-Mail-Client oder eine Software, mit der ein Benutzer auf sein E-Mail-Konto zugreift. (d. h. E-Mail-Software ähnlich wie Outlook)

  • MTA: Mail Transfer Agent – ​​Mail Transfer Agent sind E-Mail-Dienstanbieter wie NetEase, Sina usw.

  • MDA: Mail Delivery Agent – ​​Postzusteller. Ein Server des E-Mail-Dienstleisters

Sender-> MTA -> E-Mails sind im Wesentlichen:

    MUA schreiben, um E-Mails an MTA zu senden;
  • MUA schreiben, um E-Mails von MDA zu empfangen.
  • Beim Versenden von E-Mails ist das von MUA und MTA verwendete Protokoll SMTP: Simple Mail Transfer Protocol. Das SMTP-Protokoll wird auch vom nachfolgenden MTA zu einem anderen MTA verwendet.

Beim Empfang von E-Mails verwenden MUA und MDA zwei Protokolle: POP: Post Office Protocol, die aktuelle Version ist 3, allgemein bekannt als POP3: Internet Message Access Protocol, die aktuelle Version ist 4, der Vorteil ist, dass dies nicht möglich ist Sie können nicht nur E-Mails abrufen, sondern auch auf MDA gespeicherte E-Mails direkt bearbeiten, z. B. aus dem Posteingang in den Papierkorb verschieben usw.

1. SMTP (Simple Mail Transfer Protocol)

ist ein Regelwerk für die Übertragung von E-Mails von der Quelladresse zur Zieladresse, das die Übertragungsmethode von Briefen steuert.

Pythons smtplib bietet eine sehr bequeme Möglichkeit, E-Mails zu versenden. Es kapselt einfach das SMTP-Protokoll.

Python unterstützt SMTP mit zwei Modulen: smtplib und email ist für die Erstellung von E-Mails verantwortlich, und smtplib ist für den Postversand verantwortlich.

1. E-Mail erstellen: email.mime-Typ

Das Erstellen eines E-Mail-Objekts ist ein Message-Objekt ein Text-Mail-Objekt. Wenn Sie ein MIMEImage-Objekt erstellen, stellt es ein Bild als Anhang dar. Um mehrere Objekte zu kombinieren, verwenden Sie das MIMEMultipart-Objekt und MIMEBase kann jedes Objekt darstellen. Ihre Vererbungsbeziehung ist wie folgt: <code>smtplibemail两个模块,email负责构造邮件,smtplib负责发送邮件。

1、构造邮件:email.mime类型

构造一个邮件对象就是一个Messag对象,如果构造一个MIMEText对象,就表示一个文本邮件对象,如果构造一个MIMEImage对象,就表示一个作为附件的图片,要把多个对象组合起来,就用MIMEMultipart对象,而MIMEBase可以表示任何对象。它们的继承关系如下:

Message
+- MIMEBase
   +- MIMEMultipart
   +- MIMENonMultipart
      +- MIMEMessage
      +- MIMEText
      +- MIMEImage
Nach dem Login kopieren

首先,我们来构造一个最简单的纯文本邮件,然后,通过SMTP发出去。

from email.mime.text import MIMEText
msg = MIMEText(&#39;hello, send by Python...&#39;, &#39;plain&#39;, &#39;utf-8&#39;)
Nach dem Login kopieren

注意到构造MIMEText对象时,第一个参数就是邮件正文,第二个参数是MIME的subtype,传入&#39;plain&#39;,最终的MIME就是&#39;text/plain&#39;,最后一定要用utf-8编码保证多语言兼容性。

2、创建 SMTP 对象

语法如下:

import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
Nach dem Login kopieren

参数说明:

  • host: SMTP 服务器主机。这个参数可选,你可以根据需要指定主机的IP地址或者域名,例如:runoob.com。

  • port: 如果你提供了 host 参数, 你需要指定 SMTP 服务使用的端口号,一般情况下 SMTP 端口号为25。

  • local_hostname: 如果 SMTP 在你的本机上,你只需要指定服务器地址为 localhost 即可。

3、Python SMTP 对象使用 sendmail 方法发送邮件

语法如下:

SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])
Nach dem Login kopieren

参数说明:

  • from_addr: 邮件发送者地址。

  • to_addrs: 字符串列表,邮件发送地址。

  • msg: 发送消息

这里要注意一下第三个参数,msg 是字符串,表示邮件。要发送邮件,就必须注意信息的格式,因为邮件通常包括标题、发件人、收件人、邮件内容和附件等。这个格式就是 smtp 协议中定义的格式。

二、实例

2:本机已安装支持 SMTP 的服务

以下执行实例需要你本机已安装了支持 SMTP 的服务。

sendmail()方法就是发邮件,由于可以一次发给多个人,所以传入一个list,邮件正文是一个stras_string()MIMEText对象变成str

经过Header对象编码的文本,包含utf-8编码信息和Base64编码的文本。

以下是一个使用 Python 发送邮件简单的实例:

import smtplib
from email.mime.text import MIMEText
from email.header import Header
 
sender = &#39;from@runoob.com&#39;
receivers = [&#39;429240967@qq.com&#39;]  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
 
# 三个参数:第一个为文本内容,第二个 plain 设置文本格式,第三个 utf-8 设置编码
message = MIMEText(&#39;Python 邮件发送测试内容...&#39;, &#39;plain&#39;, &#39;utf-8&#39;)
message[&#39;From&#39;] = Header("菜鸟教程", &#39;utf-8&#39;)   # 发送者
message[&#39;To&#39;] =  Header("测试", &#39;utf-8&#39;)        # 接收者
message[&#39;Subject&#39;] = Header(&#39;Python SMTP 邮件测试主题&#39;, &#39;utf-8&#39;)
 
try:
    smtpObj = smtplib.SMTP(&#39;localhost&#39;)
    smtpObj.sendmail(sender, receivers, message.as_string())
    print "邮件发送成功"
except smtplib.SMTPException:
    print "Error: 无法发送邮件"
Nach dem Login kopieren

2、使用第三方 SMTP 服务

如果我们本机没有 sendmail 访问,也可以使用其他邮件服务商的 SMTP 访问(QQ、网易、Google等)。

login()方法用来登录SMTP服务器

发收件件人的名字没有显示为友好的名字,比如Mr Green

使用 formataddr方法来格式化一个邮件地址。如果包含中文,需要通过Header对象进行编码。

msg[&#39;To&#39;]接收的是字符串而不是list,如果有多个邮件地址,用,

import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

# 第三方 SMTP 服务
mail_host = "mail.sss.com"  # 设置服务器
mail_user = "it_system@sss.com"  # 用户名
mail_pass = "Ssss201709#"  # 口令

sender = &#39;it_system@tcl.com&#39;
receivers = &#39;sss.yang@tcsssl.com&#39;  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱

message = MIMEText(&#39;Python 邮件内容测试...&#39;, &#39;plain&#39;, &#39;utf-8&#39;)
message[&#39;From&#39;] = formataddr((&#39;SCBC-啊iT&#39;,   sender))
message[&#39;To&#39;] = formataddr((&#39;杨生&#39;, receivers))
message[&#39;Subject&#39;] = &#39;Python SMTP 邮件测试&#39;

try:
    smtpObj = smtplib.SMTP()
    smtpObj.connect(mail_host, 25)  # 25 为 SMTP 端口号
    smtpObj.login(mail_user, mail_pass)
    smtpObj.sendmail(sender, receivers, message.as_string())
    print("邮件发送成功")
except smtplib.SMTPException:
    print("Error: 无法发送邮件")
Nach dem Login kopieren
Nach dem Login kopieren

Zuerst erstellen wir die einfachste Nur-Text-E-Mail und senden sie dann über SMTP. 🎜
mail_msg = """
Python 邮件内容测试...


这是一个链接


"""
message = MIMEText(mail_msg, &#39;html&#39;, &#39;utf-8&#39;)
Nach dem Login kopieren
Nach dem Login kopieren
🎜 bemerkte, dass beim Erstellen des MIMEText-Objekts der erste Parameter der E-Mail-Text und der zweite Parameter der Untertyp von MIME ist. Geben Sie 'plain' ein final MIME Es ist 'text/plain'. Schließlich müssen Sie die utf-8-Codierung verwenden, um die Kompatibilität mit mehreren Sprachen sicherzustellen. 🎜

2. SMTP-Objekt erstellen

🎜Die Syntax lautet wie folgt: 🎜
from email.mime.multipart import MIMEMultipart

# 创建一个带附件的实例
message = MIMEMultipart()

message[&#39;From&#39;] = formataddr((&#39;SCBC-啊iT&#39;, sender))
message[&#39;To&#39;] = formataddr((&#39;杨生&#39;, receivers))
message[&#39;Subject&#39;] = &#39;Python SMTP 邮件测试&#39;

mail_msg = """
Python 邮件内容测试...


这是一个链接


"""
# 邮件正文内容
message.attach(MIMEText(mail_msg, &#39;html&#39;, &#39;utf-8&#39;))

# 构造附件1,传送当前目录下的 test.txt 文件
att = MIMEText(open(&#39;32.txt&#39;, &#39;rb&#39;).read(), &#39;base64&#39;, &#39;utf-8&#39;)
att["Content-Type"] = &#39;application/octet-stream&#39;
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att["Content-Disposition"] = &#39;attachment; filename="32.txt"&#39;
message.attach(att)
Nach dem Login kopieren
Nach dem Login kopieren
🎜Parameterbeschreibung: 🎜🎜🎜🎜Host: SMTP-Server-Host. Dieser Parameter ist optional. Sie können nach Bedarf die IP-Adresse oder den Domänennamen des Hosts angeben, zum Beispiel: runoob.com. 🎜🎜🎜🎜Port: Wenn Sie den Host-Parameter angeben, müssen Sie die vom SMTP-Dienst verwendete Portnummer angeben. Im Allgemeinen ist die SMTP-Portnummer 25. 🎜🎜🎜🎜local_hostname: Wenn sich SMTP auf Ihrem lokalen Computer befindet, müssen Sie nur die Serveradresse als localhost angeben. 🎜🎜🎜

3. Das Python-SMTP-Objekt verwendet die sendmail-Methode zum Senden von E-Mails

🎜Die Syntax lautet wie folgt: 🎜
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage

# 创建一个带附件的实例
message = MIMEMultipart()

message[&#39;From&#39;] = formataddr((&#39;SCBC-啊iT&#39;, sender))
message[&#39;To&#39;] = formataddr((&#39;杨生&#39;, receivers))
message[&#39;Subject&#39;] = &#39;Python SMTP 邮件测试&#39;

mail_msg = """
Python 邮件内容测试...


这是一个链接


图片演示:





"""
# 邮件正文内容
message.attach(MIMEText(mail_msg, &#39;html&#39;, &#39;utf-8&#39;))

# 指定图片为当前目录
with  open(&#39;a.jpg&#39;, &#39;rb&#39;) as fp:
    msgImage = MIMEImage(fp.read())

# 定义图片 ID,在 HTML 文本中引用
msgImage.add_header(&#39;Content-ID&#39;, &#39;&#39;)
message.attach(msgImage)
Nach dem Login kopieren
Nach dem Login kopieren
🎜Parameterbeschreibung: 🎜🎜🎜🎜from_addr: E-Mail-Absenderadresse. 🎜🎜🎜🎜to_addrs: String-Liste, E-Mail-Sendeadresse. 🎜🎜🎜🎜msg: Senden Sie eine Nachricht 🎜🎜🎜🎜 Bitte beachten Sie den dritten Parameter hier, msg ist eine Zeichenfolge, die eine E-Mail darstellt. Um eine E-Mail zu versenden, müssen Sie auf das Format der Informationen achten, da die E-Mail normalerweise einen Titel, Absender, Empfänger, E-Mail-Inhalt, Anhänge usw. enthält. Dieses Format ist das im SMTP-Protokoll definierte Format. 🎜🎜2. Beispiel🎜

2: Auf diesem Computer wurde ein Dienst installiert, der SMTP unterstützt

🎜Das folgende Ausführungsbeispiel erfordert, dass auf Ihrem Computer ein Dienst installiert ist, der SMTP unterstützt. 🎜🎜Die Methode sendmail() dient zum Senden einer E-Mail. Da diese an mehrere Personen gleichzeitig gesendet werden kann, wird eine Liste übergeben, und der E-Mail-Text wird übergeben a str , as_string() wandelt das MIMEText-Objekt in str um. 🎜🎜Vom Header-Objekt kodierter Text, einschließlich UTF-8-Kodierungsinformationen und Base64-kodiertem Text. 🎜🎜Das Folgende ist ein einfaches Beispiel für die Verwendung von Python zum Senden von E-Mails: 🎜
# 指定图片为当前目录
with  open(&#39;a.jpg&#39;, &#39;rb&#39;) as fp:
    # 设置附件的MIME和文件名,这里是png类型:
    mime = MIMEBase(&#39;image&#39;, &#39;jpg&#39;, filename=&#39;a.jpg&#39;)
    # 加上必要的头信息:
    mime.add_header(&#39;Content-Disposition&#39;, &#39;attachment&#39;, filename=&#39;附件显示名称.jpg&#39;)
    mime.add_header(&#39;Content-ID&#39;, &#39;&#39;)  # 如果有多个文件需要使用.format(index)
    mime.add_header(&#39;X-Attachment-Id&#39;, &#39;0&#39;)  # 如果有多个文件需要使用.format(index)
    # 把附件的内容读进来:
    mime.set_payload(fp.read())
    # 用Base64编码:
    encoders.encode_base64(mime)
    # 添加到MIMEMultipart:
    message.attach(mime)
Nach dem Login kopieren
Nach dem Login kopieren

2. Verwenden Sie einen SMTP-Dienst eines Drittanbieters

🎜Wenn wir lokal keinen Sendmail-Zugriff haben, können wir auch den SMTP-Zugriff von verwenden andere E-Mail-Dienstanbieter (QQ, NetEase, Google usw.). 🎜🎜login()-Methode wird zum Anmelden beim SMTP-Server verwendet 🎜🎜Der Name des Empfängers wird nicht als Anzeigename angezeigt, wie z. B. Mr Green ; 🎜🎜Verwenden Sie die formataddr-Methode zum Formatieren einer E-Mail-Adresse. Wenn es Chinesisch enthält, muss es über das Header-Objekt codiert werden. 🎜🎜msg['To'] empfängt eine Zeichenfolge anstelle einer Liste. Wenn mehrere E-Mail-Adressen vorhanden sind, verwenden Sie einfach , , um sie zu trennen. 🎜
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

# 第三方 SMTP 服务
mail_host = "mail.sss.com"  # 设置服务器
mail_user = "it_system@sss.com"  # 用户名
mail_pass = "Ssss201709#"  # 口令

sender = &#39;it_system@tcl.com&#39;
receivers = &#39;sss.yang@tcsssl.com&#39;  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱

message = MIMEText(&#39;Python 邮件内容测试...&#39;, &#39;plain&#39;, &#39;utf-8&#39;)
message[&#39;From&#39;] = formataddr((&#39;SCBC-啊iT&#39;,   sender))
message[&#39;To&#39;] = formataddr((&#39;杨生&#39;, receivers))
message[&#39;Subject&#39;] = &#39;Python SMTP 邮件测试&#39;

try:
    smtpObj = smtplib.SMTP()
    smtpObj.connect(mail_host, 25)  # 25 为 SMTP 端口号
    smtpObj.login(mail_user, mail_pass)
    smtpObj.sendmail(sender, receivers, message.as_string())
    print("邮件发送成功")
except smtplib.SMTPException:
    print("Error: 无法发送邮件")
Nach dem Login kopieren
Nach dem Login kopieren

3、使用Python发送HTML格式的邮件

Python在构造MIMEText对象时,把HTML字符串传进去,再把第二个参数由plain变为html就可以了:

具体代码如下:

mail_msg = """
Python 邮件内容测试...


这是一个链接


"""
message = MIMEText(mail_msg, &#39;html&#39;, &#39;utf-8&#39;)
Nach dem Login kopieren
Nach dem Login kopieren

4、Python 发送带附件的邮件

带附件的邮件可以看做包含若干部分的邮件:文本和各个附件本身,所以,可以构造一个MIMEMultipart对象代表邮件本身,然后往里面加上一个MIMEText作为邮件正文,再继续往里面加上表示附件的MIMEBase对象即可。

发送带附件的邮件,首先要创建MIMEMultipart()实例,然后构造附件,如果有多个附件,可依次构造,最后利用smtplib.smtp发送。

from email.mime.multipart import MIMEMultipart

# 创建一个带附件的实例
message = MIMEMultipart()

message[&#39;From&#39;] = formataddr((&#39;SCBC-啊iT&#39;, sender))
message[&#39;To&#39;] = formataddr((&#39;杨生&#39;, receivers))
message[&#39;Subject&#39;] = &#39;Python SMTP 邮件测试&#39;

mail_msg = """
Python 邮件内容测试...


这是一个链接


"""
# 邮件正文内容
message.attach(MIMEText(mail_msg, &#39;html&#39;, &#39;utf-8&#39;))

# 构造附件1,传送当前目录下的 test.txt 文件
att = MIMEText(open(&#39;32.txt&#39;, &#39;rb&#39;).read(), &#39;base64&#39;, &#39;utf-8&#39;)
att["Content-Type"] = &#39;application/octet-stream&#39;
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att["Content-Disposition"] = &#39;attachment; filename="32.txt"&#39;
message.attach(att)
Nach dem Login kopieren
Nach dem Login kopieren

5、在 HTML 文本中添加图片

要把图片嵌入到邮件正文中,我们只需按照发送附件的方式,先把邮件作为附件添加进去,然后,在HTML中通过引用src="cid:0"就可以把附件作为图片嵌入了。如果有多个图片,给它们依次编号,然后引用不同的cid:x即可。

邮件的 HTML 文本中一般邮件服务商添加外链是无效的,正确添加图片的实例如下所示:

from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage

# 创建一个带附件的实例
message = MIMEMultipart()

message[&#39;From&#39;] = formataddr((&#39;SCBC-啊iT&#39;, sender))
message[&#39;To&#39;] = formataddr((&#39;杨生&#39;, receivers))
message[&#39;Subject&#39;] = &#39;Python SMTP 邮件测试&#39;

mail_msg = """
Python 邮件内容测试...


这是一个链接


图片演示:





"""
# 邮件正文内容
message.attach(MIMEText(mail_msg, &#39;html&#39;, &#39;utf-8&#39;))

# 指定图片为当前目录
with  open(&#39;a.jpg&#39;, &#39;rb&#39;) as fp:
    msgImage = MIMEImage(fp.read())

# 定义图片 ID,在 HTML 文本中引用
msgImage.add_header(&#39;Content-ID&#39;, &#39;&#39;)
message.attach(msgImage)
Nach dem Login kopieren
Nach dem Login kopieren

或者通过MIMEBase来添加图片

# 指定图片为当前目录
with  open(&#39;a.jpg&#39;, &#39;rb&#39;) as fp:
    # 设置附件的MIME和文件名,这里是png类型:
    mime = MIMEBase(&#39;image&#39;, &#39;jpg&#39;, filename=&#39;a.jpg&#39;)
    # 加上必要的头信息:
    mime.add_header(&#39;Content-Disposition&#39;, &#39;attachment&#39;, filename=&#39;附件显示名称.jpg&#39;)
    mime.add_header(&#39;Content-ID&#39;, &#39;&#39;)  # 如果有多个文件需要使用.format(index)
    mime.add_header(&#39;X-Attachment-Id&#39;, &#39;0&#39;)  # 如果有多个文件需要使用.format(index)
    # 把附件的内容读进来:
    mime.set_payload(fp.read())
    # 用Base64编码:
    encoders.encode_base64(mime)
    # 添加到MIMEMultipart:
    message.attach(mime)
Nach dem Login kopieren
Nach dem Login kopieren

6、同时支持HTML和Plain格式

如果我们发送HTML邮件,收件人通过浏览器或者Outlook之类的软件是可以正常浏览邮件内容的,但是,如果收件人使用的设备太古老,查看不了HTML邮件怎么办?

办法是在发送HTML的同时再附加一个纯文本,如果收件人无法查看HTML格式的邮件,就可以自动降级查看纯文本邮件。

利用MIMEMultipart就可以组合一个HTML和Plain,要注意指定subtype是alternative

msg = MIMEMultipart(&#39;alternative&#39;)
msg[&#39;From&#39;] = ...
msg[&#39;To&#39;] = ...
msg[&#39;Subject&#39;] = ...

msg.attach(MIMEText(&#39;hello&#39;, &#39;plain&#39;, &#39;utf-8&#39;))
msg.attach(MIMEText(&#39;Hello&#39;, &#39;html&#39;, &#39;utf-8&#39;))
# 正常发送msg对象...
Nach dem Login kopieren

7、加密SMTP

如果使用标准的25端口连接SMTP服务器发送邮件,即使身份验证成功,因为明文传输的缘故,整个邮件发送过程都有可能被窃听。要更安全地发送邮件,可以加密SMTP会话,实际上就是先创建SSL安全连接,然后再使用SMTP协议发送邮件。

在某些邮件服务提供商(例如Gmail)中,SMTP服务必须使用加密传输。我们来看看如何通过Gmail提供的安全SMTP发送邮件。

只需要在创建SMTP对象后,立刻调用starttls()方法,就创建了安全连接。后面的代码和前面的发送邮件代码完全一样。

必须知道,Gmail的SMTP端口是587,因此,修改代码如下:

smtp_server = &#39;smtp.gmail.com&#39;
smtp_port = 587
server = smtplib.SMTP(smtp_server, smtp_port)
server.starttls()
# 剩下的代码和前面的一模一样:
server.set_debuglevel(1)
Nach dem Login kopieren

三、使用poplib接收邮件

收取邮件就是编写一个MUA作为客户端,从MDA把邮件获取到用户的电脑或者手机上。收取邮件最常用的协议是POP协议,目前版本号是3,俗称POP3

Python内置一个poplib模块,实现了POP3协议,可以直接用来收邮件。

POP3 的命令和响应数据都是基于 ASCII 文本的,并以 CR 和 LF(/r/n) 作为行结束符,响应数据包括一个表示返回状态的符号(+/)和描述信息。

请求和响应的标准格式如下:

请求标准格式:命令 [参数] CRLF
响应标准格式:+OK /[-ERR] description CRLF

POP3 协议客户端的命令和服务器端对应的响应数据如下:

  • user name:向 POP 服务器发送登录的用户名。

  • pass string:向 POP 服务器发送登录的密码。

  • quit:退出 POP 服务器。

  • stat:统计邮件服务器状态,包括邮件数和总大小。

  • list [msg_no]:列出全部邮件或指定邮件。返回邮件编号和对应大小。

  • retr msg_no:获取指定邮件的内容(根据邮件编号来获取,编号从 1 开始)。

  • dele msg_no:删除指定邮件(根据邮件编号来删除,编号从 1 开始)。

  • noop:空操作。仅用于与服务器保持连接。

  • rset:用于撤销 dele 命令。

poplib 模块完全模拟了上面命令,poplib.POP3 或 poplib.POP3_SSL 为上面命令提供了相应的方法,开发者只要依次使用上面命令即可从服务器端下载对应的邮件

注意到POP3协议收取的不是一个已经可以阅读的邮件本身,而是邮件的原始文本,这和SMTP协议很像,SMTP发送的也是经过编码后的一大段文本。

要把POP3收取的文本变成可以阅读的邮件,还需要用email模块提供的各种类来解析原始文本,变成可阅读的邮件对象。

所以,收取邮件分两步:

第一步:使用poplib.POP3 或 poplib.POP3_SSL 按 POP3 协议把邮件的原始文本下载到本地;

用POP3获取邮件其实很简单,要获取所有邮件,只需要循环使用retr()把每一封邮件内容拿到即可。真正麻烦的是把邮件的原始内容解析为可以阅读的邮件对象。

import poplib
from email.parser import Parser
# email.parser 解析电子邮件,返回这个对象的email.message.Message实例
from email.header import decode_header
from email.utils import parseaddr

# 服务器及用户信息
host = &#39;mail.tcl.com&#39;
username = &#39;bobin.yang@tcl.com&#39;
password = &#39;Ybb7654321&#39;

# 连接到POP3服务器
conn = poplib.POP3_SSL(host)
# 注意qq邮箱使用SSL连接
# 设置调试模式,可以看到与服务器的交互信息
conn.set_debuglevel(1)

# 打印POP3服务器的欢迎文字
print(conn.getwelcome().decode("utf-8"))

# 身份认证
conn.user(username)
conn.pass_(password)

# 获取服务器上信件信息,返回一个列表,第一项是一共有多少封邮件,第二项是共有多少字节
# stat()返回邮件数量和占用空间
mail_total, total_size = conn.stat()
print(&#39;message: %s.Size:%s&#39; % (mail_total, total_size))

# list()返回(response, [&#39;mesg_num octets&#39;, ...], octets),第二项是编号
resp, mails, octets = conn.list()
print(mails)
# 返回的列表类似[b&#39;1 82923&#39;, b&#39;2 2184&#39;, ...]

# 获取最新一封邮件,注意索引号从1开始
# POP3.retr(which) 检索序号which的这个邮件,然后设置他的出现标志 返回(response, [&#39;line&#39;, ...], octets)这个三元组
resp, lines, ocetes = conn.retr(len(mails))
print(&#39;lines:&#39;, len(lines))
# lines 存储了邮件的原始文本的每一行
# 可以获得整个邮件的原始文本
print("-------------------")
Nach dem Login kopieren

第二步:使用 email.parser.Parser或BytesParser 解析邮件内容为消息对象,然后,用适当的形式把邮件内容展示给用户即可。

解析邮件的过程和上一节构造邮件正好相反。

程序在创建 BytesParser(解析字节串格式的邮件数据)或 Parser(解析字符串格式的邮件数据)时,必须指定 policy=default;否则,BytesParse 或 Parser 解析邮件数据得到的就是过时的 Message 对象,,不是新的 EmailMessage,处理起来非常不方便。

1、使用 email.parser.Parser解析邮件内容为 email.message.Message(过时,不推荐)
msg = b&#39;\r\n&#39;.join(lines).decode(&#39;utf-8&#39;)
# 解析出邮件
msg = Parser().parsestr(msg)


# email.Parser.parsestr(text, headersonly=False)
# 与parser()方法类似,不同的是他接受一个字符串对象而不是一个类似文件的对象
# 可选的headersonly表示是否在解析玩标题后停止解析,默认为否
# 返回根消息对象

# 编码处理,文本邮件的内容也是str,还需要检测编码,否则,非UTF-8编码的邮件都无法正常显示
def guess_charset(msg):
    charset = msg.get_charset()  # 从msg对象获取编码
    if charset is None:
        content_type = msg.get(&#39;Content-Type&#39;, &#39;&#39;).lower()  # 如果获取不到,再从content—type字段获取
        if &#39;charset&#39; in content_type:
            charset = content_type.split(&#39;charset=&#39;)[1].strip()
            return charset
    return charset


# 数据解码,邮件的Subject或者Email中包含的名字都是经过编码后的str,要正常显示,就必须decode
def decode_str(s):
    value, charset = decode_header(s)[0]  # 数据,数据编码方式,from email.header import decode_header
    # decode_header()返回一个list,因为像Cc、Bcc这样的字段可能包含多个邮件地址,所以解析出来的会有多个元素。上面的代码我们偷了个懒,只取了第一个元素。
    if charset:
        value = value.decode(charset)
    return value


# print_ingo函数:解析邮件与构造邮件的步骤正好相反
def print_info(msg, indent=0):  # indent用于缩进显示
    if indent == 0:
        for header in [&#39;From&#39;, &#39;To&#39;, &#39;Subject&#39;]:  # 邮件的from、to、subject存在于根对象上
            value = msg.get(header, &#39;&#39;)
            if value:
                if header == &#39;Subject&#39;:
                    value = decode_str(value)  # 需要解码subject字符串
                else:
                    # 解码mail地址
                    hdr, addr = parseaddr(value)
                    name = decode_str(hdr)
                    value = &#39;%s&#39; % addr
            print(&#39;%s:  %s  %s&#39; % (header, value, name))
            print(&#39;-*-&#39; * 20)
    if msg.is_multipart():
        # 如果邮件对象是一个is_multipart,get_payload()返回一个list,包含所有子对象
        parts = msg.get_payload()  # 循环获得列表项
        for n, part in enumerate(parts):
            # print(&#39;%spart %s&#39; % (&#39;  &#39; * indent, n))
            # print(&#39;%s------------&#39; % (&#39;  &#39; * indent))
            # 递归打印没一个子对象
            print_info(part, indent + 1)
    else:
        # 邮件对象不是一个is_multipart,就根据content_type判断
        content_type = msg.get_content_type()  # 数据类型
        if content_type == &#39;text/plain&#39; or content_type == &#39;text/html&#39;:  # 纯文本 html文本
            # 纯文本或html内容
            content = msg.get_payload(decode=True)  # 获得文本对象的字符串而非对象本身
            charset = guess_charset(msg)  # 要检测文本编码
            if charset: content = content.decode(charset)
            content = &#39;%s&#39; % (content)
            print(content)  # 获取邮件文本内容,如果只有文本,打印显示的结果和邮件中看的效果一模一样
        else:
            print(content_type+&#39;不是文本&#39;)


print_info(msg, 0)

# 退出
conn.quit()
Nach dem Login kopieren
2、使用email.parser.BytesParser 解析成email.message.EmailMessage对象

如果程序要获取邮件的发件人、收件人和主题,直接通过 EmailMessage 的相应属性来获取即可,与前面为 EmailMessage 设置发件人、收件人和主题的方式是对应的。
如果程序要读取 EmailMessage 的各部分,则需要调用该对象的 walk() 方法,该方法返回一个可迭代对象,程序使用 for 循环遍历 walk() 方法的返回值,对邮件内容进行逐项处理:

  • 如果邮件某项的 maintype 是 'multipart',则说明这一项是容器,用于包含邮件内容、附件等其他项。

  • 如果邮件某项的 maintype 是 'text',则说明这一项的内容是文本,通常就是邮件正文或文本附件。对于这种文本内容,程序直接将其输出到控制台中。

  • 如果邮件中某个项的 maintype 属性是“其他”,那么这一项的内容就是作为附件的,程序会将附件内容保存到本地文件中。

import os
import poplib
import mimetypes
from email.parser import Parser, BytesParser
from email.policy import default

msg_data = b&#39;\r\n&#39;.join(lines)
# 将字符串内容解析成邮件,此处一定要指定policy=default
msg = BytesParser(policy=default).parsebytes(msg_data)
print(type(msg))

print(&#39;发件人:&#39; + msg[&#39;from&#39;])
print(&#39;收件人:&#39; + msg[&#39;to&#39;])
print(&#39;主题:&#39; + msg[&#39;subject&#39;])
print(&#39;第一个收件人名字:&#39; + msg[&#39;to&#39;].addresses[0].username)
print(&#39;第一个发件人名字:&#39; + msg[&#39;from&#39;].addresses[0].username)
for part in msg.walk():
    counter = 1
    # 如果maintype是multipart,说明是容器(用于包含正文、附件等)
    if part.get_content_maintype() == &#39;multipart&#39;:
        continue
    # 如果maintype是multipart,说明是邮件正文部分
    elif part.get_content_maintype() == &#39;text&#39;:
        print(part.get_content())
    # 处理附件
    else:
        # 获取附件的文件名
        filename = part.get_filename()
        # 如果没有文件名,程序要负责为附件生成文件名
        if not filename:
            # 根据附件的contnet_type来推测它的后缀名
            ext = mimetypes.guess_extension(part.get_content_type())
            # 如果推测不出后缀名
            if not ext:
                # 使用.bin作为后缀名
                ext = &#39;.bin&#39;
            # 程序为附件来生成文件名
            filename = &#39;part-%03d%s&#39; % (counter, ext)
        counter += 1
        # 将附件写入的本地文件
        with open(os.path.join(&#39;.&#39;, filename), &#39;wb&#39;) as fp:
            fp.write(part.get_payload(decode=True))
# 退出服务器,相当于发送POP 3的quit命令
conn.quit()
Nach dem Login kopieren

四、利用imaplib读取邮件文本内容及附件内容

通过IMAP协议来管理邮箱用的,称作交互邮件访问协议。

! encoding:utf8
&#39;&#39;&#39;
环境:
    Win10 64位 Python 2.7.5
参考:
    http://www.pythonclub.org/python-network-application/email-format
    http://blog.sina.com.cn/s/blog_4deeda2501016eyf.html
&#39;&#39;&#39;


import imaplib
import email


def parseHeader(message):
    """ 解析邮件首部 """
    subject = message.get(&#39;subject&#39;)  
    h = email.Header.Header(subject)
    dh = email.Header.decode_header(h)
    subject = unicode(dh[0][0], dh[0][1]).encode(&#39;gb2312&#39;)
    # 主题
    print subject
    print &#39;
&#39;
    # 发件人
    print &#39;From:&#39;, email.utils.parseaddr(message.get(&#39;from&#39;))[1]
    print &#39;
&#39;
    # 收件人
    print &#39;To:&#39;, email.utils.parseaddr(message.get(&#39;to&#39;))[1]
    print &#39;
&#39;
    # 抄送人
    print &#39;Cc:&#39;,email.utils.parseaddr(message.get_all(&#39;cc&#39;))[1]



def parseBody(message):
    """ 解析邮件/信体 """
    # 循环信件中的每一个mime的数据块
    for part in message.walk():
        # 这里要判断是否是multipart,是的话,里面的数据是一个message 列表
        if not part.is_multipart():
            charset = part.get_charset()
            # print &#39;charset: &#39;, charset
            contenttype = part.get_content_type()
            # print &#39;content-type&#39;, contenttype
            name = part.get_param("name") #如果是附件,这里就会取出附件的文件名
            if name:
                # 有附件
                # 下面的三行代码只是为了解码象=?gbk?Q?=CF=E0=C6=AC.rar?=这样的文件名
                fh = email.Header.Header(name)
                fdh = email.Header.decode_header(fh)
                fname = dh[0][0]
                print &#39;附件名:&#39;, fname
                # attach_data = par.get_payload(decode=True) # 解码出附件数据,然后存储到文件中

                # try:
                #     f = open(fname, &#39;wb&#39;) #注意一定要用wb来打开文件,因为附件一般都是二进制文件
                # except:
                #     print &#39;附件名有非法字符,自动换一个&#39;
                #     f = open(&#39;aaaa&#39;, &#39;wb&#39;)
                # f.write(attach_data)
                # f.close()
            else:
                #不是附件,是文本内容
                print part.get_payload(decode=True) # 解码出文本内容,直接输出来就可以了。
                # pass
            # print &#39;+&#39;*60 # 用来区别各个部分的输出


def getMail(host, username, password, port=993):
    try:
        serv = imaplib.IMAP4_SSL(host, port)
    except Exception, e:
        serv = imaplib.IMAP4(host, port)

    serv.login(username, password)
    serv.select()
    # 搜索邮件内容
    typ, data = serv.search(None, &#39;(FROM "xx@xxx.com")&#39;)

    count = 1
    pcount = 1
    for num in data[0].split()[::-1]:
        typ, data = serv.fetch(num, &#39;(RFC822)&#39;)
        text = data[0][1]
        message = email.message_from_string(text)   # 转换为email.message对象
        parseHeader(message)
        print &#39;
&#39;
        parseBody(message)   
        pcount += 1
        if pcount > count:
            break

    serv.close()
    serv.logout()


if __name__ == &#39;__main__&#39;:
    host = "imap.mail_serv.com" # "pop.mail_serv.com"
    username = "Trevor@mail_serv.com"
    password = "your_password"
    getMail(host, username, password)
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonSo verwenden Sie die Module email, smtplib, poplib und imaplib zum Senden und Empfangen von E-Mails in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage