先概述一下邮件结构:
邮件(Mail):
1.邮件头(Mail-Header):邮件头包含与传输、投递邮件有关的基本信息。
2.邮件体(Mail-Body):(1)邮件正文;(2)邮件附件
注:邮件头与邮件体之间以空行进行分隔,邮件头中不允许出现空行。
1邮件的结构
1.1 邮件格式的发展
为了方便信息传输,人们规范了Internet邮件消息的结构形式。RFC 822是最早的一个标准,即标准ARPA互联网文本消息格式(standard for the format of ARPA internet text messages)。RFC822规定一个邮件由邮件头和邮件体两大部分组成。邮件头与邮件体之间以空行进行分隔,邮件头中不允许出现空行。邮件头包含与传输、投递邮件有关的基本信息,邮件体可分为邮件正文和邮件附件。
使用RFC822只能发送基本的ASCII码文本信息,邮件内容如果要包括二进制文件、声音和动画等,实现起来非常困难。MIME扩充了在RFC 822中定义的邮件格式,提供了一种可以在邮件中附加多种不同编码文件的方法,弥补了原来信息格式的不足,使得可以通过Internet邮件系统传送丰富的信息内容。
1.2 MIME邮件结构
MIME邮件也是由邮件头和邮件体两大部分组成。对照RFC822, MIME在Internet E-mail报文中增加了五个新头域,即MIME-Version, Content-Type, Content-Transfer-Encoding, Content-ID和Content-Description。
MIME-Version用来声明Internet消息主体所使用格式的版本号。
(1)Content-Type用来描述相应主体中数据的原始类型。
(2)Content-Transfer-Encoding指明了在传输主体时采用了哪种编码方式及必须用哪种解码方式将数据解码成它的原始状态。
(3)Content-ID和Content-Description头域是可选的,前者的值可被用来在多处上下文中唯一的确定MIME实体;后者允许用户增加关于主体的描述性信息。
其中multipart媒体类型,是MIME邮件的精髓。若邮件的“Content-Type”字段值为multipart,则邮件体被分为多个体部分(bodypart),每个体部分由头域、空行、体组成。因此,一个体部分在语法上类似于RFC822中的邮件(message),但是在意义上是不同的:①在体部分中实际上不需要头域,因此一个以空行开始的体部分是允许的,它被解释成缺省值的头域。②RFC822邮件和体部分的区别是微妙的、不重要的。但是它们两个的区别必须被邮件解析器程序理解。③相似的语法便于邮件到体部分的转化,反之亦然。
常见的multipart类型有三种:multipart/mixed, multipart/related和 multipart/alternative。它们之间的层次关系可以归纳如下图所示。
如果在邮件中要添加附件,必须定义multipart/mixed段;如果存在内嵌资源,至少要定义multipart/related段;如果纯文本与超文本共存,至少要定义multipart/alternative段。
总而言之,一个或多个不同的数据段合并在一个单一的体(body)中,实体的头域必须指定multipart类型。 multipart诸类型的共同特征是,在段头指定“boundary”参数字符串,段体内的每个子段以此串定界。所有的子段都以“--”+boundary行开始,父段则以“--”+boundary+“--”行结束。段与段之间也以空行分隔。MIME邮件的整个结构其实就是递归定义的。
Multipart/mixed
|-------------------------------------------------------------- |
| Multipart/related |
|--------------------------------------------| |
| Multipart/alternative |
|-------------------------------| |
| 纯文本/ 超文本 | 内嵌资源 | 附件1….N |
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(mailFrom,MimeUtility.encodeWord(fromMailName, charSet, null)));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(mailTo));
msg.setSubject(mailSubject, charSet);
msg.setHeader("Content-Transfer-Encoding","8bit");
if("".equals(htmlBody)){
msg.setHeader("Content-Type","text/plain; charset=" + charSet);
msg.setText(textBody, charSet);
} else if("".equals(textBody)) {
msg.setHeader("Content-Type","text/html; charset=" + charSet);
msg.setContent(createHtmlPart(htmlBody, charSet));
} else {
msg.setHeader("Content-Type","multipart/alternative;charset=" + charSet);
MimeMultipart mimeMultipart = new MimeMultipart();
MimeBodyPart mimeTextPart = new MimeBodyPart();
mimeTextPart.setContent(textBody, "text/plain; charset=" + charSet);
MimeBodyPart htmlText=new MimeBodyPart();
htmlText.setContent(htmlBody, "text/html; charset=" + charSet);
mimeMultipart.addBodyPart(mimeTextPart);
mimeMultipart.addBodyPart(htmlText);
msg.setContent(mimeMultipart);
}