前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >电子邮件实现详解(上)

电子邮件实现详解(上)

作者头像
才浅Coding攻略
发布2022-12-12 17:26:14
2.8K0
发布2022-12-12 17:26:14
举报
文章被收录于专栏:才浅coding攻略才浅coding攻略

阿巩

好久不见~

电子邮件是大家日常工作生活中最常用的交流方式之一,我们常提到的SMTP和POP3协议分别是用来做什么的呢?MUA和MTA又是具体指哪些组件呢?邮件发送和接收过程是怎样的?SMTP邮件格式是什么样子,用python/django又如何实现发送邮件呢?本文将一一解释上述问题,并与第三方提供的API对比学习代码结构。日拱一卒,我们开始吧~

首先简要回答下前两个问题,在有了大致概念后我们来看下邮件收发过程:

MUA(Mail User Agent):邮件用户代理。由于客户端的机器无法自主实现发信,需要通过代理如Foxmail、Outlook等邮件客户端软件来进行编辑和发信。

MTA(Mail Transfer Agent):邮件传输代理。MTA的角色相当于邮局,负责帮用户寄信和收信以及转发到其他MTA。它和MUA的关系是这样的:用户在使用MUA编辑好邮件后,点击发送,邮件会被MTA接收,并且发到目的用户的MTA上。

MDA(Mail Delivery Agent):邮件投递代理。邮件在传输过程中很有可能被转移到另外一个MTA,但是最终会有某个MTA接管这封邮件,并且负责投递。MTA将邮件传递给MDA,MDA好比当地的邮递员,他负责完成将邮件存放在服务器上,以及邮件过滤或将邮件直接投递到子文件夹等整理派发的工作。

MRA(Mail Receive Agent):与MUA进行交互,实现账户的离线邮件接收,不需要一直在线等待。好比某个用户雇佣的专程检查信箱及收信的小工。

总结一下大致流程如下:

1、用户使用MUA编辑邮件,并配置smtp服务器域名,然后寄信给MTA发送邮件。(比如使用网易账户发送邮件就要在配置smtp.163.com,这样邮件就发送到网易MTA)

2、MTA检查收件人服务器是不是自己,不是则传递给下一跳的MTA,直到传递到目的MTA。

3、目的MTA收到邮件后通过MDA进行存储和过滤。

4、MRA从MDA中收取邮件,存到用户的收件箱中。

5、MUA收取邮件,即将MRA中的邮件下载到本地。

我们再来看过程中用到的具体协议:

SMTP协议:Simple Mail Transfer Protocol,简单邮件传输协议。用于邮件客户端与SMTP邮件服务器之间以及两台SMTP服务器之间的通信规则。SMTP协议的通信双方采用一问一答的命令/响应形式进行对话。

POP3协议:Post Office Protocol,邮局协议。用于邮件客户端软件和POP3邮件服务器之间的通信规则。

IMAP协议:Internet Message Access Protocol,Internet消息访问协议,它是对POP3协议的一种扩展,也是定义了邮件客户端软件和IMAP邮件服务器的通信规则。

SMTP邮件服务器:替用户发送邮件和接收外面发送给本地用户的邮件。

POP3/IMAP邮件服务器:帮助用户读取SMTP邮件服务器接收进来的邮件。

IMAP与POP3区别:POP3协议提供了邮件下载功能,但使用POP3协议时,在客户端上的操作不会反馈到服务器上,比如创建文件夹、保存草稿、移动邮件、标记已读等;IMAP提供webmail 与电子邮件客户端之间的双向通信,IMAP协议支持邮件下载,并且支持客户端和邮箱同步更新。

在了解了基础通信协议之后,我们再回到服务器层面,假设用户A使用QQ邮箱给用户B的163邮箱发送邮件,在哪个环节用到了上述的哪个协议,过程是怎样的呢。

① 这一步对应MUA到MTA,使用到的是SMTP协议。

② 从SMTP服务器转发到目的服务器,使用到的也是SMTP协议。

③ 这一步SMTP服务器,即MTA检查收件人服务器是不是自己,发现是自己的账户,便将邮件存放到自己的内部存储空间。

④ 用户A将邮件发送之后,会通知用户B到指定邮箱收取邮件。用户B会通过邮件客户端软件先向163邮箱服务器请求,要求收取自己的邮件。使用到了POP3协议。

⑤ 收到请求后,会从自己的存储空间中取出B未收取的邮件。也使用到了POP3协议。

⑥ 取出用户B未收取的邮件后,将邮件发给用户B。也使用到了POP3协议。


以下代码源自网络,是使用foxmail接收邮件后得到的邮件源码,包括正文和两个附件(.JPG, .TXT):

代码语言:javascript
复制
Received:from m15-17.126.com (unknown [220.181.15.17])
         bymx10 (Coremail) with SMTP id PMCowECZWSfPlodRSu6NCw--.779S2;
         Mon,06 May 2013 19:41:03 +0800 (CST)
DKIM-Signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=126.com; // 域名密钥识别邮件标准,判断垃圾邮件
         s=s110527;h=Received:Date:From:To:Subject:Content-Type:
         MIME-Version:Message-ID; bh=B57Zfi/+wCVQ61kM9GVkCECk1ax4OZVQDtnW // 不是base64编码
         T4lS0x8=;b=XdeYidC7bR1a1l7x3yGAMiMR5ElDx2O4/db2iPrVc0dZ7Y7ANStu     // 不是base64编码
         6d9o4l9yVysfwk8vifb0eqyxV2wp28pIlfLEGZbDDpKaLMCaLAbVXdW+2hQl4ojd    // 不是base64编码
         sJ7NiAdF1j5X2N87wktFKA8ZK4lPhBYI1yFrNIT+PODg2NzF1CX2FDM=
Received: from zzzzyy91$126.com ( [202.205.103.22] ) by ajax-webmail-wmsvr17
 (Coremail) ; Mon, 6 May 2013 19:41:01 +0800(CST)
X-Originating-IP: [202.205.103.22]                //初始ip地址,同一电脑不同邮箱发邮件,该值相同
---------------------------------------------------------------------------------------------------------
DATA(以下内容由邮件客户端定义,为DATA命令后输入的内容)
--------------------------------------------------------------------------------------------------------
Date: Mon, 6 May2013 19:41:01 +0800 (CST)
From: [base64code]<zzzzyy91@126.com>
To: [emailaddress]
Subject: [base64 code]
X-Priority: [integer]                                          // 邮件优先级
X-Mailer: [Coremail Webmail Server Version SP_ntes V3.5 build      // 代理发信客户端
 20130412(21945.5326.5325) Copyright (c)2002-2013 www.mailtech.cn 126com]
X-CM-CTRLDATA: [base64 code]                           // X-邮件服务器自定义的信息段,未知作用
Content-Type:multipart/mixed;                               // 声明邮件内容格式
         boundary="----=_Part_354288_309861106.1367840461937"    // 声明邮件内容boundary
MIME-Version: 1.0                                          // 声明MIME版本
Message-ID: <>                                             // X-邮件服务器自定义的信息段
X-CM-TRANSID:                                             //X-邮件服务器自定义的信息段
X-CM-SenderInfo:                                           // X-邮件服务器自定义的信息段
X-Coremail-Antispam:                                       // X-邮件服务器自定义的信息段
---------------------------------------------------------
以下为邮件的内容
--------------------------------------------------------
------=_Part_354288_309861106.1367840461937                 //邮件内容开始
Content-Type: multipart/alternative;                           //邮件内容格式
         boundary="----=_Part_354290_1105600126.1367840461937" // 邮件正文boundary
------=_Part_354290_1105600126.1367840461937              //邮件正文boundary -- 正文开始
Content-Type: text/plain; charset=GBK                        // 邮件正文格式和字符集
Content-Transfer-Encoding: base64
[base64]mailcontent (plain)[base64]                         //邮件正文(文本格式)编码(base64)
------=_Part_354290_1105600126.1367840461937              // 邮件正文boundary  --可选HTML格式
Content-Type: text/html; charset=GBK                        //邮件正文格式和字符集
Content-Transfer-Encoding: base64
[base64]mailcontent (html)[base64]                         //邮件正文(html格式)编码(base64)
------=_Part_354290_1105600126.1367840461937--           // 邮件正文boundary -- 正文结束

------=_Part_354288_309861106.1367840461937             // 邮件内容boundary -- 附件1开始
Content-Type: image/jpeg; name="20130324_224528_982.jpg" // 附件格式及文件名
Content-Transfer-Encoding: base64
Content-Disposition: attachment;filename="20130324_224528_982.jpg"
[base64](.jpg)image attachment[base64]                         //附件-图片内容编码(base64)

------=_Part_354288_309861106.1367840461937                  // 邮件内容boundary -- 附件2开始
Content-Type: text/plain; name="window data type.txt"            // 附件格式及文件名
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="window datatype.txt"
[base64](.txt)plain attachment[base64]                         // 附件-文本内容编码(base64)
------=_Part_354288_309861106.1367840461937--                // 邮件内容boundary  -- 附件结束

在代码第6行我们看到MIME-Version这个字段,MIME协议(Multipurpose Internet Mail Extension,多用途Internet邮件扩展)用于定义复杂邮件体的格式,它支持在邮件体部分表达出的丰富多样的数据内容。而对于邮件内容的基本格式,由RFC822 文档定义。MIME协议即为对RFC822 文档的扩展。

邮件头标准字段解释如下:

参考:

https://blog.csdn.net/Fly2Leo/article/details/10468411?spm=1001.2014.3001.5501

https://www.cnblogs.com/ysocean/p/7652934.html

http://help.163.com/10/0203/13/5UJONJ4I00753VB8.html?servCode=6010237

http://blog.sina.com.cn/s/blog_af19951a0102yz1j.html

由于涉及代码多篇幅过长,JavaMail API、Python smtplib以及django.core.mail实现邮件的收发等内容将放到下一节实现。

感谢所有TV,下期见。

END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 才浅coding攻略 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • https://blog.csdn.net/Fly2Leo/article/details/10468411?spm=1001.2014.3001.5501
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档