邮件格式说明

Mutiple Internet Mail Extensions

Refer to Internet Official Protocol Standards RFC 822

1 概述

网络间传递的电子邮件需要公共认同的格式,以便于客户端邮箱软件识别拆解其间的信息。邮件本身是由ASCII字符构成,总体上分为邮件头邮件体两部分,其间允许字符编码、附件、压缩等等多样化的格式。本文档参考网络官方协议标准中,请求批注的邮件相关条款,总结了邮件结构及其各部分的格式说明,给出部分字符编码的相关解释。

RFC( Require for comment )是Internet Official Protocol Standards标准所提供的网络协议标准系列。

2 主体结构

邮件结构包括邮件头、邮件体(可无),邮件体实际上是一行行的ASCII字符构成的简单序列,它和邮件头是靠一个空行(该行只有一个回车换行符CRLF)来区分开的。

2.1 邮件头

1) 长字段的断行

邮件头由许多头字段(header fields)组成,这些字段包括字段名(field name)和字段值(field body);字段值(field body)可以分割成多行表述,叫做“可折叠”。

断行的规则是:在一行的线性空格处,可用CRLF(回车换行)之后至少跟一个LWSP-char(空格或TAB),把原来的单行变为多行表示。

RFC协议中推荐尽量把折叠的断行放置在特定的空格分隔处,比如,地址字段里的多个邮件地址,折叠时尽量在各地址之间,及逗号之后断行。

2) 字段主要结构

包括字段名(Field name),冒号(colon),字段值(Field body),结束符(CRLF);

有些字段属于结构化字段,比如日期(Date),邮件地址(Address),有着特定的表示格式,用于系统识别。而其他字段比如”Subject” “Comments”都被当作简单的字符串处理。

字段表示:

field-name ":" [ field-body ] CRLF

字段值(Field body)可断行(见1)),内容全部都是ASCII码,元素包括句号,引用字符串,特殊token,或一般文本。字段的含义参见后文附录。

3) 邮件头构造协议

邮件头字段不是必须按照特定的顺序安排,仅仅是注意要把邮件体放在邮件头之后。邮件协议中推荐的做法是在放置邮件字段时,邮件按照以下顺序安排:”Return-Path”, “Received”, “Date”, “From”, “Subject”, “Sender”, “To”, “cc”,等等。

邮件协议中规定邮件由字段和邮件体正文组成,两部分之间由一个空行(该行只有包含CRLF)分隔,也就是说,在遇见的第一个空行之后所有的内容都被当作邮件体。

Ø 转发-Forwarding

一些系统允许接受者转发信息,保留原有的邮件头,仅添加些新的字段,这些字段以”Resent-”为前缀。及前缀”Resent-”的字段表示接受者转发的原信息。

Ø 路径字段-Trace Field

路径信息用来追踪信息的发送者,”via” “with”等是记录变量。

“Return-Path” :该字段由信息的最后发送者添加,是关于信息原始来源的地址和回朔路径。Reply-To字段是有信息源添加用来直接回复(地址?),而Return-Path是一个到信息原始来源的回朔路径。

“Received” :由每个中继服务站添加,用于帮助追踪传输中出现的错误。字段内容包括,发送、接收的主机和接收时间。参数via用于记录信息发送后经过的物理站点,”with”指示了使用的邮件、连接的协议。参数id用于标识邮件。参数for用于记录发送者的分发的目的地址。

Ø 信息源的字段-Originator Field

“From/Resent-From” :与sender必须至少存在一个。

“Sender/Resent-Sender”

“Reply-To/Resent-Reply-To” 

当自动生成回复信息的地址列表时,应当注意:如果没有”Sender”,将会使用”From” .接收者在回复信息时,邮件sender中的信息不会被自动使用。如果”Reply-To”字段存在,将使用该字段信息,而不是”From”字段。如果有”From”而没有”Reply-To”,将使用”From”。

Ø 接收者字段-Receiver Field

“To/Resent-To”

“Cc/Resent-Cc”

“Bcc/Resent-Bcc”

Ø 参考字段

“Message-ID/Resent-Message-ID”

“In-Reply-To”

“Reference”

“Keywords”

4) 重要参数字段

a) “MIME-Version” :所使用的网络邮件格式标准版本

b) “Content-type”

邮件内容数据的类型,包括类型标识(type)和子类型标识(subtype),前者类型标识(type)声明了数据的类型,后者子类型标识(subtype)为这种数据类型指定了特定的格式。

比如content-type:image/xyz;说明数据类型是图像型(image)的,图像数据格式是xyz。

类型标识(type)与子类型标识(subtype)由斜杠”/”来分割。

类型之后是参数集合parameter。

邮件的数据类型分为七种,分别是:文本(Text)、多文档(mulipart)、消息(Message)、图像(Image)、音频(audio)、视频(Video)、应用(Application)。

文本(Text)—文字类信息,其基本的子类标识是”Plain”,即没有格式的文本。除了需要支持指定的字符集,获得文本信息不需要特殊的软件。文本子类用于多信息文本,在其上应用文字处理软件可以美化文本的外观,但文本的内容及涵义无需任何软件。因此子类型包括任何可读得文字处理格式。

多文档(mulipart) —包含具有独立数据类型的多个部分。其中定义了4个最原始的子类型:mixed(基本类型), alternative(具有可供选择的多个格式), parallel(同时阅览的部分), digest(都是消息型的多部内容).

消息(Message) –未封装的消息。该类型的消息体本身部分或全部都是RFC822格式。基本子类是” rfc822”。”partial”表示局部消息,允许邮件传输中可分块进行。”External-body”表示扩展大邮件。

图形(Image) –需要有现实设备。子类主要是两种应用广泛的图形格式:jpeg, gif。

声频(audio) –基本子类”basic”,需要声频输出设备。

视频(Video) –基本子雷”mpeg”,需要视频显示设备。

应用(Application) –其他类型数据,无法解析的二进制数据。基本子类”octet-stream”,用于不可解析的二进制数据情况,为用户提供将信息写入文件的方法。”PostScript”表示传输脚本文档。

Content-type类型默认为Content-type : text/plain; charset = us-ascii。如果content-type没有明确制定,那么系统会默认为该类型。

当遇到未知的类型时,将会把未知类型当作”application/octet-stream”对待。

c) Content-Transfer-Encoding头字段

许多邮件内容是以最原始的格式传输的,8位字符或二进制数据,但对于有些协议这种格式数据就不能正确传输了。例如RFC821限制messages必须为7位US-ASCII数据,而且每行不能超过1000个字符。

因此,有必要定义机制来把数据编码成7位短行格式。编码的目的就是用网络可以传输的方式来表达邮件内容。

      Content-Transfer-Encoding实际上就是在类型数据的本地表述和用7位邮件传输协议转化的表述之间的一种映射,比如协议RFC821(SMTP)。该字段的值就是指定编码类型的一种标识。

其值如下:

“7bit”,”8bit”, “quoted-printable”, “base64”, “binary”, “x-token”

标识不区分大小写,如果没有明确指定,该字段的默认值是”7bit”。

若值是”8bit”,”7bit”或”binary”时,表示没有做任何编码。(继续翻译)

2.2 Content-type字段Multipart类型说明

所有带前缀”Content-”的字段对正文都定义有含义,而其他得头字段一般都被邮件体部分忽略。

协议中指出,在multipart的情况下,即多个不同的数据集合合并在同一邮件体内,此时头字段中”multipart”参数值必须存在。这时邮件体必定存在一个或多个子部分,每一个子部分都会由边界(boundary)封装,而且最后一个子部分后面必须跟一个结尾边界。每一部分都会由边界开始,然后包含着邮件子体的头信息(header),空行,然后是邮件正文。

如果没有填写content-type的头字段,那就是暗示相应的邮件体时US-ASCII的普通text/plain文本。

      Boundary在作为边界值封装邮件时,其使用方法是值前加两个”-”。在一些特殊情况下,这种用法也不一定适用。

封装部分的结尾,boundary和前面的使用格式一样的情况下,后面再加两个”-”的形式表示。

Content-type字段参数的语法是把boundaries的值包含在引号之中。也可以没有引号,但又引号是最保险的。有一些非法字符会出现在boundary值中,如果不加引号会引起错误。

注意封装边界必须在行的开始,后面是回车换行CRLF,开头的CRLF会被当作边界的一部分,而不是上一块内容的一部分。边界后面跟一个CRLF和下一部分的邮件头字段,或者,两个CRLF,这种情况下不会有细一部分的邮件头。

在边界之间(子部分头一个boundary和上一部分结尾boundary之间或者正文第一个边界之前邮件头之后),会有一些可添加额外信息的空白空间,这些空间邮件解析时会略过。

      Multipart子类型的简要介绍:

             Mixed:表示个子部间互相独立,需要以特定的顺序排列。

      Alternative:每一子部分的是相同信息的不同版本,各部分排序,最优的排在最后,但优先使用。

      Digest:将子部分默认成message来处理。

      Parallel:同时显示多个子部

2.3 Content-type字段Message类型说明

在发送邮件时,该类型会频繁使用来封装子mail邮件。通常的子类型是message/rfc822,该类型下没有必须添加的参数。额外的子类型”partial”和”External-body ”,需要必要的参数。

编码方面,该类型只允许”7bit” “8bit”或”binary”。message的头字段通常是US_ASCII的,message体内可以按照其自身的content-transfer-encoding字段值进行编码。

1)message/rfc822

该类型是rfc822协议的message。但不必和最外层的rfc822 message那样有from, subject,以及目的字段。该类型可以由高版本的邮件替换,及兼容MIME message。

2)message/partial

有些邮件发送机构限制邮件发送的大小,这样,大的邮件对象(vedio等)必须分成多部分发送。“message/partial”说明该邮件体包含了一个大邮件的一段。该类型需要3个参数:

Id,尽可能保持唯一性,为了把各部组合到一起。

Number,该部分在整体序列中的编号。

Total,所分部分的总数,该参数一般在最后一部分出现。

发送大邮件诸如vedio文件时,由于文件太大,超出单次发送限制,需要把文件分割成多个部分。基本过程是,把vedio类型的message,分割成多个单独的vedio类型的message,每个部分再由”message/partial”类型的message封装起来,并添加分段信息。

当接收方收到该message时,各段落会`根据分割信息重新组合起来,新的信息仅是vedio类型,即去掉了外层的”message”类型封装。

组合原则:

(1) 拷贝第一部分的外层” message/partial”的头信息,除了”content-”,”message-id”,”Encrypted”,”MIME-Version”,其它为必拷贝信息

(2) 把内层的封装信息的”content-”,”message-id”,“Encrypted”,“MIME-Version”的头信息全部拷贝到新message中。

(3) 第二部分和以后部分的头信息全部忽略。

名词解释(Word Description)

RFC: Request For Common(Internet Official Protocol Standard)

CRLF:Carriage-return/Line-feed

MIME格式说明,电子邮件格式(转载)的更多相关文章

  1. C#RSA算法实现+如何将公钥为XML格式转为PEM格式,给object-C使用

    .net中,处于安全的考虑,RSACryptoServiceProvider类,解密时只有同时拥有公钥和私钥才可以.原因是公钥是公开的,会被多人持有.这样的数据传输是不安全的.C#RSA私钥加密,公钥 ...

  2. Linux在什么样的从脚本文件数据库sh格式改变sql格式

    在软件开发过程中,经常参与Linux从下一个脚本文件数据库sh格式改变sql格式问题.在本文中,一个实际的脚本文件,例如.描述格式转换过程.        1. sh文件内容 本文中的文件名称为exa ...

  3. H.264流媒体协议格式中的Annex B格式和AVCC格式深度解析

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Romantic_Energy/article/details/50508332本文需要读者对H.26 ...

  4. java中集合格式及json格式的特点和转换

    作者原创:转载请注明出处 今天在写代码,遇到一个难点,由于要调用webservice接口,返回的为一个list集合内容,从webservice调用接口返回的为一个string的io流, 在调用接口的地 ...

  5. 以太网帧格式、IP数据报格式、TCP段格式+UDP段格式 详解

    转载:http://www.cnblogs.com/lifan3a/articles/6649970.html 以太网帧格式.IP数据报格式.TCP段格式+UDP段格式 详解   1.ISO开放系统有 ...

  6. FFmpeg基础库编程开发学习笔记——音频常见格式及字幕格式

    声明一下:这些关于ffmpeg的文章仅仅是用于记录我的学习历程和以便于以后查阅,文章中的一些文字可能是直接摘自于其它文章.书籍或者文献,学习ffmpeg相关知识是为了使用在Android上,我也才是刚 ...

  7. ajax处理返回的三种格式(json格式 , xml通用格式 , html文本格式)(数据类型:整数、字符串、数组、对象)(基础最重要!)

    ajax方法的参数 常用的ajax参数比如url,data,type,包括预期返回类型dataType,发送到服务器的数据的编码类型contentType,成功方法,失败方法,完成方法.除了这些以外还 ...

  8. AngularJS过滤器filter-时间日期格式-渲染日期格式-$filter

    今天遇到了这些问题索性就 写篇文章吧 话不多说直接上栗子 不管任何是HTML格式还是JS格式必须要在  controller 里面写 // new Date() 获取当前时间 yyyy-MM-ddd ...

  9. RSA密钥之C#格式与Java格式转换

    前言 最近由于项目需求,服务端由c#编写,客户端由java编写.通信数据使用RSA非对称加密.但是java和c#生成的密钥格式是不一样的,所以需要转换格式才可以正常使用.网上搜到使用java进行格式转 ...

  10. Linux下如何将数据库脚本文件从sh格式变为sql格式

    在从事软件开发的过程中,经常会涉及到在Linux下将数据库脚本文件从sh格式变为sql格式的问题.本文以一个实际的脚本文件为例,说明格式转换的过程.        1. sh文件内容 本文中的文件名为 ...

随机推荐

  1. jmeter—解决响应乱码问题

    问题:    当响应数据或响应页面没有设置编码时,jmeter会按照jmeter.properties文件中,sampleresult.default.encoding 设置的格式解析默认ISO-88 ...

  2. CVE-2018-15982漏洞复现

    作者:欧根 漏洞信息:CVE-2018-15982 Adobe已发布适用于Windows,macOS,Linux和Chrome OS的Adobe Flash Player安全更新.这些更新解决一个  ...

  3. SSH登陆验证绕过漏洞(cve-2018-10933)

    名称: SSH登陆验证绕过漏洞 CVE-ID: cve-2018-10933 EXPLOIT-DB: https://www.exploit-db.com/exploits/45638/ 平台: Li ...

  4. 如何使用Node爬虫利器Puppteer进行自动化测试

    文:华为云DevCloud 乐少 1.背景 1.1 前端自动化测试较少 前端浏览器众多导致页面兼容性问题比较多,另外界面变化比较快,一个月内可能页面改版两三次,这样导致对前端自动化测试较少,大家也不是 ...

  5. 线性表中顺序表的的理解和实现(java)

    线性表的顺序表示指的是用一组地址连续的存储单元以此存储线性表的数据元素,这种表示也称作线性表的顺序存储结构或顺序映像.通常,称这种存储结构的线性表为顺序表.特点是:逻辑上相邻的数据元素,其物理次序上也 ...

  6. L06-Ubuntu系统中部署Vagrant和VirtualBox

    一.前言 1.Vagrant是一个搭建完整的虚拟开发环境的工具~~~更多关于Vagrant理论可查看这篇博文https://www.cnblogs.com/davenkin/p/vagrant-vir ...

  7. docker 暴露2375 端口。

    网上找的.大多不能用...一下是我自己找了半天的方法...,可能是版本太旧的原因 下图解决方法: ubuntu: 18.04 docker: Docker version 18.09.2, build ...

  8. Codeforces Round #555 (Div. 3) D. N Problems During K Days 【数学思维】

    一 题面 D. N Problems During K Days 二 分析 对于这题,刚开始我就是陷入了对公式的执着,企图用公式直接确定第一个数,然后试着去找序列.经过思考和手动模拟后发现是很难保证正 ...

  9. windows 下加载执行hta文件的方法

    首先编写这么一个hta的文件: <html> <head> <script> s = new ActiveXObject("WScript.Shell&q ...

  10. 03-树3 Tree Traversals Again (25 分)

    An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example ...