在我们日常开发过程中,经常会涉及到邮件的发送、接收。一方面,邮件服务相比于短信服务会更便宜,其对接方式也更方便,不像短信的发送,需要很多东西进行审核。
在对邮件开发前,我们必须对邮件协议有一个整体了解,如使用场景、特性等。
一个邮件系统通常有四部分组成,邮件用户代理 (MUA)、邮件传递代理 (MDA)、邮件传输代理 (MTA)以及邮件检索代理(MRA)。
MUA就是邮件客户端,常用的有outlook、thunderbird、Mac Mail、网易邮件大师等软件。邮件客户端使用IMAP或POP3协议与服务器通信,Client端用户都需要通过各个操作系统提供的MUA才能够使用邮件系统。比如,Windows里的OutLook Express、Netscape里的mail功能与KDE里的Kmail都是MUA。MUA主要的功能就是接收邮件主机的电子邮件,并提供用户浏览与编写邮件的功能。
MTA是用在邮件主机上的软件,它也是主要的邮件服务器。MTA负责发送邮件,中转邮件,当然也要接收邮件。常见的有sendmail、postfix。
MDA主要的功能就是将MTA接收的信件依照信件的流向(送到哪里)将该信件放置到本机账户下的邮件文件中(收件箱),或者再经由MTA将信件送到下个MTA。如果信件的流向是到本机,这个邮件代理的功能就不只是将由MTA传来的邮件放置到每个用户的收件箱,它还可以具有邮件过滤(filtering)与其他相关功能。常见的有procmail、dropmail;
MRA负责实现IMAP与POP3协议,与MUA进行交互;相当于让你的邮件账户支持离线邮件收取,而不是电脑打开才能收取邮件,常见的有dovecot。
一封邮件包括信封、邮件头和邮件体等三个部分。
信封可以简单理解为邮件载体,即用来承载邮件头和邮件体的一个逻辑结构。
邮件头分邮件头域、Content-Type域和Content-Transfer-Encoding域三部分。其字段含义如下
字段 | 含义 | 添加者 |
---|---|---|
Received | 传输路径 | 各级邮件服务器 |
Return-Path | 回复地址 | 目标邮件服务器 |
Delivered-To | 发送地址 | 目标邮件服务器 |
Reply-To | 回复地址 | 邮件的创建者 |
From | 发件人地址 | 邮件的创建者 |
To | 收件人地址 | 邮件的创建者 |
Cc | 抄送地址 | 邮件的创建者 |
Bcc | 暗送地址 | 邮件的创建者 |
Date | 日期和时间 | 邮件的创建者 |
Subject | 主题 | 邮件的创建者 |
Message-ID | 消息ID | 邮件的创建者 |
MIME-Version | MIME版本 | 邮件的创建者 |
Content-Type | 内容的类型 | 邮件的创建者 |
Content-Transfer-Encoding | 内容的传输编码方式 | 邮件的创建者 |
邮件头包含了发件人、收件人、主题、时间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息内容构成,可以是一行,较长的也可以占用多行。域的**首行必须“顶头”**写,即左边不能有空白字符(空格和制表符);续行必须以空白字符打头,且第一个空白字符不是信息本身固有的,解码时要过滤掉。
非标准的、自定义域名都以X-开头,例如X-Mailer, X-MSMail-Priority等,通常在接收和发送邮件的是同一程序时才能理解它们的意义。
Content-Type域,即内容类型域,它用来说明传输的内容的类型。Cotent-Type域又由“主类型/子类型”构成,主类型有text, image, audio, video, application, multipart, message等,分别表示文本、图片、音频、视频、应用、分段、消息等。每个主类型都可能有多个子类型,如text类型就包含plain, html, xml, css等子类型。以X-开头的主类型和子类型,同样表示自定义的类型,未向IANA正式注册,但大多已经约定成俗了。如application/x-zip-compressed是ZIP文件类型。在Windows中,注册表的“HKEY_CLASSES_ROOT/MIME/Database/Content Type”内列举了除multipart之外大部分已知的Content-Type。各种类型一般都可以带参数。至于参数的形式,RFC里有很多补充规定,有的允许带几个参数,常见类型如下
类型 | 属性名 | 含义 |
---|---|---|
text | charset | 用于说明文本内容的字符集编码 |
image | name | 用于说明图片文件的文件名 |
application | name | 用于说明应用程序的文件名 |
multipart | boundary | 用于定义MIME消息之间的分隔符 |
Content-Transfer-Encoding域即传送编码域,它用来说明后面传输的内容的编码方式。
Content-Transfer-Encoding共有Base64, Quoted-printable, 7bit, 8bit, Binary等几种。其中7bit是缺省的编码方式。电子邮件源码最初设计为全部是可打印的ASCII码的形式。非ASCII码的文本或数据要编码成要求的格式,如上面的三个例子。Base64, Quoted-Printable是在非英语国家使用最广使的编码方式。Binary方式只具有象征意义,而没有任何实用价值。关于Base64编码和Quoted-Printable编码请参考RFC文档或另外一篇文章《SMTP协议分析》。国内多数邮件服务器已经支持8bit方式,因此只在国内传输的邮件,特别是在邮件头中,可直接使用8bit编码,对汉字不做处理。如果邮件要出国,建议按Base64或Quoted-printable编码。
邮件体的类型由邮件头的“Content-Type”域指出。常见的简单类型有text/plain(纯文本)和text/html(超文本)。源码中出现的multipart类型,是MIME邮件的精髓。邮件体被分为多个段,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative。从它们的名称,不难推知这些类型各自的含义和用处。
SMTP称为简单邮件传输协议(Simple Mail Transfer Protocal),目标是向用户提供高效、可靠的邮件传输。它的一个重要特点是它能够在传送中接力传送邮件,即邮件可以通过不同网络上的主机接力式传送。通常它工作在两种情况下:一是邮件从客户机传输到服务器;二是从某一个服务器传输到另一个服务器。SMTP是一个请求/响应协议,它监听25号端口,用于接收用户的Mail请求,并与远端Mail服务器建立SMTP连接。
SMTP通常有发送和接收两种工作模式。发送SMTP在接收到用户的邮件请求后,判断此邮件是否为本地邮件,若是直接投送到用户的邮箱,否则向DNS查询远端邮件服务器的MX记录,并建立与远端接收SMTP之间的一个双向传送通道,此后SMTP命令由发送SMTP发出,由接收SMTP接收,而应答则反方向传送。
一旦传送通道建立,SMTP发送者发送MAIL命令指明邮件发送者。如果SMTP接收者可以接收邮件则返回OK应答。SMTP发送者再发出RCPT命令确认邮件是否接收到。如果SMTP接收者接收,则返回OK应答;如果不能接收到,则发出拒绝接收应答(但不中止整个邮件操作),双方将如此反复多次。当接收者收到全部邮件后会接收到特别的序列,入伏哦接收者成功处理了邮件,则返回OK应答。
发送示例:
C: telent SMTP.163.com 25 //以telenet方式连接163邮件服务器
S: 220 163.com Anti-spam GT for Coremail System //220为响应数字,其后的为欢迎信息
C: HELO SMTP.163.com //除了HELO所具有的功能外,EHLO主要用来查询服务器支持的扩充功能
S: 250-mail
S: 250-AUTH LOGIN PLAIN
S: 250-AUTH=LOGIN PLAIN
S: 250 8BITMIME //最后一个响应数字应答码之后跟的是一个空格,而不是'-'
C: AUTH LOGIN //请求认证
S: 334 dxNlcm5hbWU6 //服务器的响应——经过base64编码了的“Username”=
C: Y29zdGFAYW1heGl0Lm5ldA== //发送经过BASE64编码了的用户名
S: 334 UGFzc3dvcmQ6 //经过BASE64编码了的"Password:"=
C: MTk4MjIxNA== //客户端发送的经过BASE64编码了的密码
S: 235 auth successfully //认证成功
C: MAIL FROM: [email protected] //发送者邮箱
S: 250 … . //“…”代表省略了一些可读信息
C: RCPT TO: [email protected] //接收者邮箱
S: 250 … . // “…”代表省略了一些可读信息
C: DATA //请求发送数据
S: 354 Enter mail, end with "." on a line by itself
C: Enjoy Protocol Studing
C: .
S: 250 Message sent
C: QUIT //退出连接
S: 221 Bye
MIME全称Multipurpose Internet Mail Extensions,即多用途网际邮件扩充协议。MIME试图在不改变SMTP协议和RFC822(邮件格式标准)的基础上,使得邮件可以传送任意二进制文件。所以MIME 的格式灵活。MIME 消息可以包含文本、图象、声音、视频及其它应用程序的特定数据。具体来说,MIME 允许邮件包括如下格式:
一封邮件包括信封、邮件头和邮件体等三个部分。信封显然可以不含有二进制信息,而其它两部分则可能包含任意二进制序列,因此需要加以改进。MIME正是抓住了这两个地方来对他们加以改进。
新增了一些邮件头信息,用来协商MIME的一些参数。
定义了许多邮件内容的格式,对多媒体电子邮件的表示方法进行了标准化。
定义了传送编码,从而可以传送任意二进制文件。
我们可以把这些改进措施,看成是在用SMTP等发送邮件前所采取的预处理。
一封MIME 邮件可以由多个不同类型的MIME消息组合而成,一个MIME消息表示邮件中的一个基本MIME资源或若干基本MIME消息的组合体。每个MIME消息的 数据格式与RFC822数据格式相似,也包括头和体两部分,分别称为MIME消息头和MIME消息体,它们之间使用空行分隔。MIME消息体中包含了资源的具体内容,MIME消息头中则包含了对资源的描述信息。多个消息,它们共同作为所形成的MIME组合消 息的MIME消息体,相互之间采用某种分隔标识符进行分隔,MIME组合消息的消息头中需要描述其中的多个MIME消息的组合类型和分隔标识符。一个 MIME组合消息还可以再与其他MIME消息共同形成一个更大的MIME组合消息,这样就形成了一种多层嵌套的组合关系,一封MIME邮件就是按这种组合 方式所形成的一个最顶层的MIME组合消息。
头字段 | 含义 |
---|---|
Content-Type | 段体的类型 |
Content-Transfer-Encoding | 段体的传输编码方式 |
Content-Disposition | 段体的安排方式 |
Content-ID | 段体的ID(cid来源) |
Content-Location | 段体的位置(路径) |
Content-Base | 段体的基位置 |
Content-Type
Content-Type是SMTP协议里原本就有的字段,MIME协议对其进行了扩充。对于MIME组合消息,它的消息头中需要指定组合关系。具体资源的数据类型和 组合消息的组合关系,都是通过消息头中的Content-Type头字段来指定的。Content-Type字段中的内容以“主类型/子类型”的形式出 现,主类型有 text、image、audio、video、application、multipart、message等,分别表示文本、图片、音频、视频、应用 程序、组合结构、消息等。每个主类型下面都有多个子类型,例如text主类型包含plain、html、xml、css等子类型。multipart主类 型用于表示MIME组合消息,它是MIME协议中最重要的一种类型。一封MIME邮件中的MIME消息可以有三种组合关系:混合、关联、选择,它们对应 MIME类型如下:
混和组合类型(multipart/mixed)
其内容可以是文本、声音和附件等不同邮件内容的混和体,如整封邮件的MIME类型就定义为multipart/mixed
关联(依赖)组合类型(multipart/related)
如邮件正文要使用HTML代码引用内嵌的图片资源,它们组合成的MIME消息的MIME类型就应 该定义为multipart/related,表示其中某些资源(HTML代码)要引用(依赖)另外的资源(图像数据),引用资源与被引用的资源必须组合成multipart/related类型的MIME组合消息。
选择组合类型( multipart/alternative)
如一封邮件的邮件正文同时采用HTML格式和普通文本格式进行表达时,就可以将它们嵌套在一个 multipart/alternative类型的MIME组合消息中。这种做法的好处在于如果邮件阅读程序不支持HTML格式时,可以采用其中的文本格 式进行替代。
要在邮件中要添加附件,就必须将整封邮件的MIME类型定义为multipart/mixed;如果要在HTML格式的正文中引用内嵌资 源,那就要定义multipart/related类型的MIME消息;如果普通文本内容与HTML文本内容共存,那就要定义multipart /alternative类型的MIME消息。如果整封邮件中只有普通文本内容与HTML文本内容,那么整封邮件的MIME类型则应定义为multipart/ alternative;如果整封邮件中包含有HTML文本内容和内嵌资源,但不包含附件,那么整封邮件的MIME类型则应定义为 multipart/related。
Content-Transfer-Encoding
Content-Transfer-Encoding 头字段用于指定MIME消息体中的内容所采用的邮件编码方式。
传统的 SMTP协议又是基于ASCII码字符设计的,基于传统SMTP协议设计的SMTP服务器在处理邮件内容时只取出每个字节中的7个低bit位进行处理,而将最高bit位忽略不计。为了能够在邮 件内容中包含中文、图像或声音等非ASCII字符的数据,可以采用某种编码方式将非ASCII字符的数据转换成可打印的ASCII字符后再发送。邮件阅读程序则按照相应的解码方式从邮件中还原出原始数据即可,比较常用的两种邮件编码方式为BASE64和Quoted-printable。扩展 SMTP协议允许直接在邮件中传递二进制数据,这种没有进行邮件编码的二进制数据的邮件内容称为8bit编码。为了区别,将没有进行邮件编码的纯ASCII码字符的邮件称为7bit编码。
编码方式如下:
7Bit
消息体内容全部是没有经过编码的ASCII字符。
8Bit
消息体内容是没有经过编码的原始数据,且其中包含有非ASCII字符的数据。现在的邮件服务器基本上都支持8Bit编码,使用支持8Bit编码的邮件服务器可以简化邮件的处理过程。
BASE64
将二进制数据转换成可打印的ASCII字符的一种最常见的编码方式,它的基本原理是将一组连续的字节数据按6个bit位进行分组,然后对每组数据用一个ASCII字符来表示。6个bit位最多能表示26=64个数值,因此可以使用64个ASCII字符来对应这64个数值,这64个ASCII字符为:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
编码细节请参阅其他资料,另外MIME规范建议BASE64编码结果中的每行最多76个字符。
Quoted-printable
Quoted- printable也是一种将二进制数据转换成可打印的ASCII字符的编码方式,它对ASCII字符不进行转换,只对非ASCII字符的数据进行编码转化。每个非ASCII字符的字节数据,都被转换成一个"="号后跟这个字节的十六进制数据。
Content-Disposition
Content- Disposition头字段用于指定邮件阅读程序处理数据内容的方式,有inline和attachment两种标准方式,inline表示直接处理, 而attachment表示当做附件处理。如果将Content-Disposition设置为attachment,在其后还可以指定filename 属性,如下面例子:
Content-Disposition: attachment; filename="1.bmp"
表示MIME消息体的内容为邮件附件,附件名"1.bmp"。
Content-ID (内部资源引用)
Content- ID头字段用于为“multipart/related”组合消息中的内嵌资源指定一个唯一标识号,在HTML格式的正文中可以使用这个唯一标识号来引用 该内嵌资源。如假设将一个表示内嵌图片的MIME消息的Content-ID头字段设置为下述样式:
Content-ID: it315logo_gif
则在HTML正文中通过如下HTML语句来引用该图片资源
<img src="cid:it315logo_gif">
注意,在引用Content-ID头字段标识的内嵌资源时,要在资源的唯一标识号前面加上 cid:
,以说明要采用唯一标识号对资源进行引用。
Content-Location (外部资源引用)
Content- Location头字段用于为内嵌资源设置一个URI地址,这个URI地址可以是绝对或相对的。当使用Content- Location头字段为一个内嵌资源指定一个URI地址后,在HTML格式的正文中也可以使用这个URI来引用该内嵌资源。例如,假设将一个表示内嵌图 片的MIME消息的Content-Location头字段设置为如下形式:
Content-Location:http://www.it315.org/images/it315logo.gif
则在HTML正文中就可以使用如下HTML语句来引用该图片资源:
Content-Base
Content- Base头字段用于为内嵌资源设置一个基准路径,只有这样,Content-Location头字段中设置的URI才可以采用相对地址。假如将一个 表示内嵌图片的MIME消息的Content-Base和Content-Location头字段设置为如下形式:
Content-Base: http://www.it315.org/images/
Content-Location: it315logo.gif
则内嵌资源的完整路径就是Content-Base头字段设置的基准路径与Content-Location头字段设置的相对路径相加的结果,在HTML正文中就可以使用如下HTML语句来引用该图片资源:
<img src="http://www.it315.org/images/it315logo.gif"/>
POP协议是第一个离线邮件协议,允许用户从服务器上把邮件下载到本地主机上,同时删除保存在邮件服务器上的邮件(现在的邮件服务商都可以设置是否同时删除),能让用户不必长时间地与邮件服务器连接,从而减少了服务器和网络的整体开销;邮局协议版本3 POP3(Post Office Protocol-Version 3)由RFC1939 定义,主要用于支持使用客户端远程管理在服务器上的电子邮件。默认端口号是110。POP3协议相对简单,POP3服务器响应一般为:“+OK”表示成功,“-ERR”表示失败。
POP3命令格式 | 说明 |
---|---|
userusername | user 命令是POP3客户端程序与POP3邮件服务器建立连接后通常发送的第一条命令,参数 username 表示收件人的帐户名称。 |
passpassword | pass 命令是在user命令成功通过后,POP3客户端程序接着发送的命令,它用于传递帐户的密码,参数 password 表示帐户的密码。 |
apopname,digest | apop 命令用于替代user和pass命令,它以MD5 数字摘要的形式向POP3邮件服务器提交帐户密码。 |
stat | stat 命令用于查询邮箱中的统计信息,例如:邮箱中的邮件数量和邮件占用的字节大小等。 |
uidlmsg# | uidl 命令用于查询某封邮件的唯一标志符,参数msg#表示邮件的序号,是一个从1开始编号的数字。 |
list[MSG#] | list 命令用于列出邮箱中的邮件信息,参数 msg#是一个可选参数,表示邮件的序号。当不指定参数时,POP3服务器列出邮箱中所有的邮件信息;当指定参数msg#时,POP3服务器只返回序号对应的邮件信息。 |
retrmsg# | retr 命令用于获取某封邮件的内容,参数 msg#表示邮件的序号。 |
delemsg# | dele 命令用于在某封邮件上设置删除标记,参数msg#表示邮件的序号。POP3服务器执行dele命令时,只是为邮件设置了删除标记,并没有真正把邮件删除掉,只有POP3客户端发出quit命令后,POP3服务器才会真正删除所有设置了删除标记的邮件。 |
rest | rest 命令用于清除所有邮件的删除标记。 |
topmsg#n | top 命令用于获取某封邮件的邮件头和邮件体中的前n行内容,参数msg#表示邮件的序号,参数n表示要返回邮件的前几行内容。使用这条命令以提高 Web Mail系统(通过Web站点上收发邮件)中的邮件列表显示的处理效率,因为这种情况下不需要获取每封邮件的完整内容,而是仅仅需要获取每封邮件的邮件头信息。 |
noop | noop 命令用于检测POP3客户端与POP3服务器的连接情况。 |
quit | quit 命令表示要结束邮件接收过程,POP3服务器接收到此命令后,将删除所有设置了删除标记的邮件,并关闭与POP3客户端程序的网络连接。 |
POP3协议中有三种状态,认证状态,处理状态,和更新状态。命令的执行可以改变协议的状态,而对于具体的某命令,它只能在具体的某状态下使用。客户机与服务器刚与服务器建立连接时,它的状态为认证状态;一旦客户机提供了自己身份并被成功地确认,即由认可状态转入处理状态; 在完成相应的操作后客户机发出QUIT命令(具体说明见后续内容),则进入更新状态,更新之后又重返认证状态;当然在认可状态下执行QUIT命令,可释放连接。
当用户接收电子邮件时,所有的信件都从服务器上清除并下载到客户机。在整个收信过程中,用户无法知道邮件的具体信息,只有照单全收入硬盘后,才能慢慢浏览和删除。这使用户几乎没有对邮件接收的控制决定权。一旦碰上邮箱被轰炸,或有比较大的邮件,用户不能通过分析邮件的内容及发信人地址来决定是否下载或删除,从而造成系统资源的浪费。而IMAP协议不但可以克服POP3的缺陷,而且还提供了更强大的功能。
交互式邮件存取协议IMAP(Internet Mail Access Protocol)在RFC2060文档中定义,是为了弥补POP协议不足产生的新协议,目前使用的是第4个版本,所以也称为IMAP4,默认端口号143。支持在线、离线访问模式。它与POP3协议的主要区别在于用户可以不用把所有的邮件全部下载,支持通过客户端直接对服务器上的邮件进行操作。具体功能如下:
# -*- coding:utf-8 -*-
import smtplib
# from email.mime.image import MIMEImage
# from email.mime.base import MIMEBase
# from email.mime.application import MIMEApplication
from email.header import Header
# import json
# import base64
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr
import email
username = '[email protected]'
password = '*****'
# 回信地址
replyto = '[email protected]'
# 显示的To收信地址
rcptto = ['[email protected]', '[email protected]']
# 显示的Cc收信地址
rcptcc = []
# Bcc收信地址,密送人不会显示在邮件上,但可以收到邮件
rcptbcc = []
# 全部收信地址,包含抄送地址,单次发送不能超过60人
receivers = rcptto + rcptcc + rcptbcc
# 构建alternative结构
msg = MIMEMultipart('alternative')
msg['Subject'] = Header('自定义信件主题')
msg['From'] = formataddr(["自定义发信昵称", username]) # 昵称+发信地址(或代发)
# list转为字符串
msg['To'] = ",".join(rcptto)
msg['Cc'] = ",".join(rcptcc)
msg['Reply-to'] = replyto # 用于接收回复邮件,需要收信方支持标准协议
msg['Return-Path'] = '[email protected]' # 用于接收退信邮件,需要收信方支持标准协议
msg['Message-id'] = email.utils.make_msgid()
msg['Date'] = email.utils.formatdate()
# 构建alternative的text/html部分
texthtml = MIMEText('自定义HTML超文本部分', _subtype='html', _charset='UTF-8')
msg.attach(texthtml)
if __name__ == '__main__':
try:
# client = smtplib.SMTP_SSL('smtpdm.aliyun.com', 465)
# SMTP普通端口为25或80
client = smtplib.SMTP('smtpdm.aliyun.com', 80)
# client = smtplib.SMTP_SSL('smtpdm.aliyun.com', 465)
# 开启DEBUG模式
client.set_debuglevel(0)
# 发件人和认证地址必须一致
client.login(username, password)
# 备注:若想取到DATA命令返回值,可参考smtplib的sendmail封装方法:
client.sendmail(username, receivers, msg.as_string()) # 支持多个收件人,最多60个
client.quit()
print('邮件发送成功!')
except smtplib.SMTPConnectError as e:
print('邮件发送失败,连接失败:', e.smtp_code, e.smtp_error)
except smtplib.SMTPAuthenticationError as e:
print('邮件发送失败,认证错误:', e.smtp_code, e.smtp_error)
except smtplib.SMTPSenderRefused as e:
print('邮件发送失败,发件人被拒绝:', e.smtp_code, e.smtp_error)
except smtplib.SMTPRecipientsRefused as e:
print('邮件发送失败,收件人被拒绝:', e.smtp_code, e.smtp_error)
except smtplib.SMTPDataError as e:
print('邮件发送失败,数据接收拒绝:', e.smtp_code, e.smtp_error)
except smtplib.SMTPException as e:
print('邮件发送失败, ', str(e))
except Exception as e:
print('邮件发送异常, ', str(e))
from imapclient import IMAPClient
from email.header import decode_header
from pathlib import Path
from base64_util import safe_b64decode
class Imapmail(object):
def __init__(self): # 初始化数据
self.serveraddress = None
self.user = None
self.passwd = None
self.prot = None
self.ssl = None
self.timeout = None
self.savepath = None
self.server = None
def client(self): # 链接
try:
self.server = IMAPClient(self.serveraddress, self.prot, self.ssl, timeout=self.timeout)
return self.server
except BaseException as e:
return "ERROR: >>> " + str(e)
def login(self): # 认证
try:
self.server.login(self.user, self.passwd)
except BaseException as e:
return "ERROR: >>> " + str(e)
def getmaildir(self): # 获取目录列表 [((), b'/', 'INBOX'), ((b'\\Drafts',), b'/', '草稿箱'),]
dirlist = self.server.list_folders()
return dirlist
def getallmail(self): # 收取所有邮件
print(self.server)
self.server.select_folder('INBOX', readonly=True) # 选择目录 readonly=True 只读,不修改,这里只选择了 收件箱
result = self.server.search() # 获取所有邮件总数目 [1,2,3,....]
print("邮件列表:", result[-10:])
for _sm in result[-10:]:
msgdict = self.server.fetch(_sm, ['BODY[]']) # 获取邮件内容
mailbody = msgdict[_sm][b'BODY[]'] # 获取邮件内容
path_save = Path(self.savepath, "email")
path_save.mkdir(parents=True, exist_ok=True)
file_save = Path(path_save, str(_sm))
file_save.open("wb").write(mailbody)
def close(self):
self.server.close()
if __name__ == "__main__":
imap = Imapmail()
imap.serveraddress = "imaphm.***.com" # 邮箱地址
imap.user = "[email protected]"
imap.passwd = "*****"
imap.savepath = "*****/***" # 邮件存放路径
imap.client()
imap.login()
imap.getallmail()
imap.close()
在邮件开发过程中,全局的认知应该是,STMP协议用来发送邮件,POP/POP3是早期版本邮件接收协议,IAMP/IAMP4是功能更强大的邮件协议。在开发过程中更值得关注的是MIME协议,因为其规定了富文本的邮件格式。
https://blog.csdn.net/bripengandre/article/details/2192982
https://www.cnblogs.com/wfwenchao/p/5208926.html
https://blog.csdn.net/kerry0071/article/details/28604267
https://www.163.com/dy/article/ECQKEMF7053179V7.html