邮件的组织结构介绍 邮件实现详解(三)

要想各种邮件处理程序能识别我们所写的电子邮件,能从我们所书写的电子邮件中分析和提取出发件人,收件人,邮件主题和邮件内容以及附件等信息,那么我们所写的电子邮件必须要遵循一定的格式要求,正如我们上一篇博客 手工体验smtp和pop3协议 ,我们在发送邮件时有固定的写法。而这种邮件内容的基本格式和具体细节分别是由 RFC822 文档和 MIME 协议定义的。

1、RFC822 邮件格式

  英文参考文档如下:https://tools.ietf.org/html/rfc822

  RFC822 文档中定义的文件格式包括两个部分:邮件头和邮件体。在上一篇博客,我们通过SMTP服务发送一封邮件,然后用POP3服务器接收。邮件接收内容如下图红色框所显示:

  这上面显示的不全,我这里将其内容整理出来,并在每行左边加上标号:

1 Received: from smtpbg5.qq.com (unknown [183.60.61.230])
        by mx6 (Coremail) with SMTP id OMCowACXv+ssf99ZD5FqAg--.5570S3;
        Thu, 12 Oct 2017 22:41:48 +0800 (CST)
2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512;
        t=1507819308; bh=N2xK6iU/bt0tcntOdutSQ3tkYXbTtOi08RT+HjuXmBc=;
        h=From:To:Subject:Mime-Version:Content-Type:Content-Transfer-Encoding:Date:Message-ID;
        b=lzBtxAWw0+HB1bGLkkCqlUeU4bvVoMxDp3UZTKq3YCIJt5Ypu4FkE0m5rrrpcxF0D
         W0/PQajrQTughLTmpjoudI5aDWjfrfkOc1Z0+ltaAraoZfdE5HmNQ0hxQstNa+IbjC
         GMVEzCOMikVm5qklyCz/1Lwd5mBJ90YkknS3sL08=
3 X-QQ-FEAT: Gf8h89u9tNwRjwDYIPPhYegibbvTgUmwr4I/ntV6mwr6YOyFiWpUpVj+bCsJz
        tAz24NjMs/p1D8BXG7LYvZRCPMPQV7jdW3AKjTclrSS9xE29fxWsEjYk5QlD1cMIuhHF9Po
        1HMwWKIZX8q6smehIwr+t/du8sprvHVue4ty5KMPeWw967qaAZgta5hcnRtgajhZRcIumVx
        r+K4/nY7I+wwNenOTfHT4Ly4K1Ne+vD7VNJbLHH674HEJ2CsoSEEBW7X/LeeSq6M=
4 X-QQ-SSF: 0001000000000010000000000000007
5 X-HAS-ATTACH: no
6 X-QQ-BUSINESS-ORIGIN: 2
7 X-Originating-IP: 113.57.253.69
8 X-QQ-STYLE:
9 X-QQ-mid: webmail4t1507819307t4823829
 
10 From: "=?ISO-8859-1?B?MTEzMjgwMzk1MQ==?=" <1132803951@qq.com>
11 To: "=?ISO-8859-1?B?MTgyNzEyNjU3MzI=?=" <18271265732@163.com>
12 Subject: hello world
13 Mime-Version: 1.0
14 Content-Type: multipart/alternative;
        boundary="----=_NextPart_59DF7F2B_08CB07D0_339F08F2"
15 Content-Transfer-Encoding: 8Bit
16 Date: Thu, 12 Oct 2017 22:41:47 +0800
17 X-Priority: 3
18 Message-ID: <tencent_9EFED46440A5BAD43E6BC680FAC8A58E460A@qq.com>
19 X-QQ-MIME: TCMime 1.0 by Tencent
20 X-Mailer: QQMail 2.x
21 X-QQ-Mailer: QQMail 2.x
22 X-QQ-SENDSIZE: 520
23 Received: from qq.com (unknown [10.137.130.92])
        by smtp.qq.com (ESMTP) with SMTP
        id ; Thu, 12 Oct 2017 22:41:47 +0800 (CST)
24 Feedback-ID: webmail:qq.com:bgweb:bgweb4
25 X-CM-TRANSID:OMCowACXv+ssf99ZD5FqAg--.5570S3
26 Authentication-Results: mx6; spf=pass smtp.mail=1132803951@qq.com; dki
        m=pass header.i=@qq.com
27 X-Coremail-Antispam: 1Uf129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73
        VFW2AGmfu7bjvjm3AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvj4RWLvtDUUUU
 
28 This is a multi-part message in MIME format.
 
29 Content-Type: text/plain;
        charset="ISO-8859-1"
30 Content-Transfer-Encoding: base64
 
31 PGRpdj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6ICdsdWNpZGEgR3JhbmRlJywgVmVyZGFu
YSwgJ01pY3Jvc29mdCBZYUhlaSc7IGxpbmUtaGVpZ2h0OiAyMy44cHg7Ij5UaGlzIGlzIHRo
ZSBmaXJzdCBlbWFpbCBzZW50IGJ5IGhhbmQgdXNpbmcgdGhlIFNNVFAgcHJvdG9jb2w8L3Nw
YW4+PC9kaXY+

  上面便是 RFC822 所定义的邮件格式,从第 1 行到第 30 行都是邮件头,第 31 行是邮件体(经过base64加密过了,有兴趣的大家可以解码看看)。而邮件头和邮件体之间以一个空行间隔,邮件头部分是由多个头字段和字段内容组成,分别表示收件人,发件人,发件时间,主题等信息。还有一些信息是对应的SMTP服务器在邮件传递过程中所加上的,我们知道现实生活中的邮局在处理邮件时,通常都会在信封上加上邮戳,表示这封邮件在什么时候经过了哪个邮局哪个部门处理,我们上个例子是QQ邮箱发给163邮箱的。而SMTP服务器按从下往上的方式添加信息,即先添加的字段位于后添加字段的后面。所以qq的SMTP服务器会先添加头字段,但是添加的字段会在163的SMTP服务器添加字段的下面,另外 POP3服务器也会自己添加一些字段。

  每一个邮件头以“字段名:字段值”的格式出现,即每一行邮件头的内容依次由字段名、冒号、空格、字段值、回车换行符组成。RFC822文档中定义了多个标准的邮件头字段,每一个邮件头字段表示一种特定的信息。邮件头中也可以包含自定义的头字段,这种自定义的头字段通常是某个组织或机构内部专用的。下面是对一些主要的邮件头字段的解释:

  我们从上可以知道,RFC822文档存在两个问题:

  ①、定义了邮件内容的主体结构和各种邮件头字段的详细细节,但是,它没有定义邮件体的格式,RFC822文档定义的邮件体部分通常都只能用于表述一段普通的文本,而无法表达出图片、声音等二进制数据。

  ②、SMTP服务器在接收邮件内容时,当接收到只有一个“.”字符的单独行时,就会认为邮件内容已经结束,如果一封邮件正文中正好有内容仅为一个“.”字符的单独行,SMTP服务器就会丢弃掉该行后面的内容,从而导致信息丢失。

  上面两个问题是致命的,当今的电子邮件,人们希望在电子邮件中嵌入图片、声音、动画和附件。但是,由于图片和声音等内容是非ASCII码的二进制数据,而RFC822邮件格式只适合用来表达纯文本的邮件内容,所以,要使用RFC822邮件格式发送这些非ASCII码的二进制数据时,必须先采用某种编码方式将它们“编码”成可打印的ASCII字符后再作为RFC822邮件格式的内容。邮件阅读程序在读取到这种经过编码处理的邮件后,再按照相应的解码方式解码出原始的二进制数据,这样就可以借助RFC822邮件格式来传递多媒体数据了。这种做法需要解决一下两个技术问题:

  一、邮件阅读程序如何知道邮件中嵌入的原始二进制数据所采用的编码方式;

  二、邮件阅读程序如何知道每个嵌入的图像或其他资源在整个邮件内容中的起止位置。

  为了解决上面两个问题,人们后来专门为此定义了MIME(Multipurpose Internet Mail Extension,多用途Internet邮件扩展)协议。

2、MIME协议

  MIME协议用于定义复杂邮件体的格式,它可以表达多段平行的文本内容和非文本的邮件内容,例如,在邮件体中内嵌的图像数据和邮件附件等。另外,MIME协议的数据格式也可以避免邮件内容在传输过程中发生信息丢失。MIME协议不是对RFC822邮件格式的升级和替代,而是基于RFC822邮件格式的扩展应用。一言以蔽之,RFC822定义了邮件内容的格式和邮件头字段的详细细节,MIME协议则是定义了如何在邮件体部分表达出的丰富多样的数据内容。

  一个采用了MIME协议的电子邮件就叫做MIME邮件,MIME邮件在RFC822文档中定义的邮件头字段的基础上,扩充了一些自己专用的邮件头字段,例如,使用MIME-Version头字段指定MIME协议的版本,使用Content-Type头字段指定邮件体的MIME类型,使用Content-Transfer-Encoding头字段指定编码方法,如下所示:    

MIME-Version:1.0

Content-Type:multipart/mixed;boundary="----=_NextPart_000_0050_01C"

  其中,“multipart/mixed”部分说明邮件体中包含有多段数据,每段数据之间使用boundary属性中指定的字符文本作为分隔标识符。另外,MIME邮件也扩展了RFC822文档中已经定义了的邮件头字段的内涵,例如,定义了subject头字段中的值内容的格式,以便通过编码的方式让邮件主题中也可以使用非ASCII码的字符。subject头字段中的值嵌套在一对“=?”和“?=”标记符之间,标记符之间的内容由三部分组成:邮件主题的原始内容的字符集、当前采用的编码方式、编码后的结果,这三部分之间使用“?”进行分隔。

3、总结

  这篇博客,带上前面两篇博客,我们就将邮件的收发基本原理讲了一下。那么有人会问,实际项目中我们也需要考虑邮件的底层实现协议吗?答案是不用的,比如 sun 公司(现在已经被orcal收购了)开发的JavaMail API 就是为方便Java开发人员在应用程序中实现邮件接收和发送功能而提供的一套标准开发包,屏蔽了底层的邮件实现协议,那么下一篇博客我们就来用JavaMail 实现邮件收发功能。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2017-10-15

Java基于JavaMail实现向QQ邮箱发送邮件

最近项目在做新闻爬虫,想实现这个功能:爬虫某个页面失败后,把这个页面的 url 发到邮箱.最终实现的效果图如下,后期可以加上过滤标签.失败状态码等,方便分类搜索异常. 开发人员可以根据邮件里的 url 和堆栈信息,分析爬虫失败的原因. 是不是服务器 down 了? 还是爬虫的 Dom 解析没有解析到内容? 还是正则表达式对于这个页面不适用? 开启SMTP服务 在 QQ 邮箱里的 设置->账户里开启 SMTP 服务 注意开启完之后,QQ 邮箱会生成一个授权码,在代码里连接邮箱使用这个授权码而不是原

java中javamail发送带附件的邮件实现方法

本文实例讲述了java中javamail发送带附件的邮件实现方法.分享给大家供大家参考.具体分析如下: JavaMail,顾名思义,提供给开发者处理电子邮件相关的编程接口.它是Sun发布的用来处理email的API.它可以方便地执行一些常用的邮件传输,JavaMail是可选包,因此如果需要使用的话你需要首先从java官网上下载.目前最新版本是JavaMail1.5.0,下面我们来看看javamail发送带附件的邮件实例 mail.java 代码: 复制代码 代码如下: package mail;

JavaMail实现邮件发送的方法

本文实例讲述了JavaMail实现邮件发送的方法.分享给大家供大家参考.具体如下: 下载 activation.jar 和 mail.jar 配置CLASSPATH,将上面两个jar包加入到CLASSPATH中. JavaBean : "SendEmail.java" package cls; import java.util.Date; import java.util.Properties; import javax.mail.*; import javax.mail.intern

Java使用JavaMail API发送和接收邮件的代码示例

使用Javamail发送邮件,必需的jar包(请下载javamail的源文件,官方下载页:http://www.oracle.com/technetwork/java/javamail/index-138643.html): mailapi.jar.定义了收发邮件所使用到的接口API: smtp.jar.包含了发送邮件使用到的类: pop3.jar.包含了收邮件使用到的类: 我们通常发送邮件使用的协议是smtp协议,接受邮件使用的协议是pop3协议.或者,我们直接将mail.jar加入到工程,这

JavaWeb中使用JavaMail实现发送邮件功能实例详解

现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件.邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息.今天我们也来实现一个这样的功能,用户注册成功之后,就将用户的注册信息以Email的形式发送到用户的注册邮箱当中,实现发送邮件功能就得借助于JavaMail了. 一.搭建开发环境 1.1.创建Web项目 1.2.用户注册的Jsp页面 register.jsp <%@ page language="java" pag

java中javamail收发邮件实现方法

概述 1.邮件相关的标准 厂商所提供的 JavaMail 服务程序可以有选择地实现某些邮件协议,常见的邮件协议包括: SMTP(Simple Mail Transfer Protocol) :即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式. POP3(Post Office Protocol – Version 3) :即邮局协议版本 3 ,用于接收电子邮件的标准协议. IMAP(Internet Mail Access Protocol) :即 In

Java程序中使用JavaMail发送带图片和附件的邮件

我们常常在邮件中添加附件,以达到传输较大文件的目的.而上一篇文章只是将本机的一张图片内嵌到邮件的 HTML 格式的正文当中,这样的邮件显得不够丰富多彩.我们想要一封正文部分图文并茂,而游客附带若干附件的邮件. 下面是代码结构中3个重要的方法: MimeBodyPart createAttachment(String fileName) 方法用于创建附件并返回: MimeBodyPart createContent(String body, String fileName) 方法用于创建正文部分并

struts2集成javamail发邮件示例详解

一.代码预览这两天在做struts2上的邮件发送.以前的项目有用到spring,用spring提供的邮件支持类很方便可以完成这个功能,但是现在只用struts2的话,就碰到了一系列的问题. 请先将自己下载的 mail.jar,及activation.jar加入到classpath 复制代码 代码如下: package com.nerve.cloudoffice.common.util; import java.util.List;import java.util.Properties; impo

JavaMail实现发送超文本(html)格式邮件的方法

本文实例讲述了JavaMail实现发送超文本(html)格式邮件的方法.分享给大家供大家参考.具体如下: 附件以超文本形式,很常用,与普通的邮件,只是查了一些设置,只有处理方式有些细微的差别 代码如下: <%@ page contentType="text/html;charset=GBK" %> <%@ page import="java.util.*"%> <%@ page import="javax.mail.*&quo

基于SSM框架+Javamail发送邮件的代码实例

本篇介绍基于SSM框架(Spring4.0+SpringMVC+Mybatis)组合的Javamail应用,邮箱的话基于腾讯的QQ邮箱,其实也是Foxmail邮箱 先要了解一下SMTP协议和SSL加密 SMTP:称为简单邮件传输协议(Simple Mail Transfer Protocal),目标是向用户提供高效.可靠的邮件传输.SMTP是一种请求响应的协议,也就是客户机向远程服务器发送请求,服务器响应,监听端口是25,所以其工作模式有两种:发送SMTP,接收SMTP. SSL加密:用来保障浏

基于SSM框架之个人相册示例代码

学习了一阵子的SSM框架,一直在各种博客,简书,慕课网学习,最后终于自己撸出来一个简单的个人相册. 项目的演示效果: 开发的工具及环境: IntelliJ IDEA: 2016 Maven :3.0x Hbuilder(前端部分,可以用记事本代替2333) Java 8 项目流程(dao->service->web): 1.添加所有依赖: <dependency> <groupId>junit</groupId> <artifactId>juni

基于ssm框架实现layui分页效果

今天完成了基于ssm框架下,layui的分页操作,现在把核心内容分享一下: 1.前端页面的关键代码,基于html5 <!--自动渲染--> <table class="layui-table" lay-data="{cellMinWidth:100, height:'full-500', url:'meter/query', page:true, id:'idTest'}" lay-filter="demo"> <t

基于Django框架的权限组件rbac实例讲解

1.基于rbac的权限管理 RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,一个角色拥有若干权限.这样,就构造成"用户-角色-权限"的授权模型.在这种模型中,用户与角色之间,角色与权限之间都是多对多的关系. 简单的模型图示如下: 2.Rbac组件的基本目录结构: 3.按照写的流程,来讲解rbac组件中的各个部分,以及功能, 3.1 models数据库表设计(models.py). 为了在

python基于gevent实现并发下载器代码实例

这篇文章主要介绍了python基于gevent实现并发下载器代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 并发下载原理 import gevent from gevent import monkey import urllib.request monkey.patch_all() def my_download(url): print('GET: %s' % url) resp = urllib.request.urlopen(url

基于python判断目录或者文件代码实例

这篇文章主要介绍了基于python判断目录或者文件代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1. 判断目录是否存在 'isdir',删除目录时只有该目录为空才可以 'rmdir' import os if(os.path.isdir('D:/Python_workspace/spyder_space/test_各种功能/哈哈哈哈')): #判断目录是否存在 print('yes') os.rmdir('D:/Python_work

基于Java创建一个订单类代码实例

这篇文章主要介绍了基于Java创建一个订单类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 需求描述 定义一个类,描述订单信息 订单id 订单所属用户(用户对象) 订单所包含的商品(不定数量个商品对象) 订单总金额 订单应付金额: 总金额500~1000,打折85折 总金额1000~1500,打折80折 总金额1500~2000,打折70折 总金额超过2000,打折65折 在此基础上,还要看用户的vip等级 用户vip等级为:一般会员,

java基于poi导出excel透视表代码实例

这篇文章主要介绍了java基于poi导出excel透视表代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 从前,我是一个前端程序猿,怀着对打通任(前)督(后)二(开)脉(发)的梦想转了后端,自学两礼拜java+spring全家桶,直接上项目实战.最近接到一需求:将业务数据导出一张透视表. 需求开发完成已近有一段时间了,甲方的大爷大妈,爷爷奶奶们也都用的很开心,我也很开心,于是就心想咱学了也不能白学,所以写下这篇随笔. 先看下用easypo

基于javascript实现获取最短路径算法代码实例

这篇文章主要介绍了基于javascript实现获取最短路径算法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码如下 //A算法 自动寻路 路径 class GetAutoPath{ constructor(id, map, sPos, ePos, mapArr){ //this.type = id.type; this.id = id; this.map = map; this.sPos = sPos; this.ePos = eP

基于maven的ssm框架整合的示例代码

基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途不仅限于服务器端的开发.从简单性.可测试性和松耦合的角度而言,任何Java应用