像上一篇文章那样,我们只能创建一封封只包含纯文本或者HTML格式的文本邮件,这远远不能满足我们现在的需要,我们经常想要把本机上的图片、相片包含在邮件的正文部分,或者是直接将自己制作的贺卡等作为邮件正文发送给我们的朋友。
想要在邮件中包含图片、音频、视频等其他格式的文件,就不能再简单地使用 RFC 文档来对邮件结构、内容进行描述了,因为 RFC 只能描述普通的文本,而且一旦遇到单独一行的句号“.”时,SMTP 服务器就会以此为邮件正文部分的结束符,因此很大可能会导致邮件信息的丢失。
关于MIME:
引入 MIME (Multipurpose Internet Mail Extension ,多功能 Internet 邮件扩展)协议来满足我们上面的需求。使用了 MIME 协议描述的邮件可称为 MIME 邮件,一个 MIME 邮件可由若干个 符合 MIME 格式描述的消息组成。而一个消息既可以表示邮件中一个基本的 MIME 资源文件(例如纯文本、音频、视频等),又可以表示若干个此类基本资源文件组合而成的大的 MIME 消息的组合体。
一个 MIME 消息分为消息头和消息体,消息头包含对于消息体的描述,消息体则包含资源文件的具体内容。
JavaMail 中使用MIME:
在 JavaMail 中,一个 MIME 邮件用一个 MimeMessage 对象表示,仔细看下图:
其中标了红色圈圈的则是 MIME 消息的资源类型。
BodyPart 相当于上述的 MIME 基本消息;
MultiPart 相当于由多个 BodyPart (基本消息)组合而成的较大的 MIME 消息组合体;
Message 则相当于一封 MIME 邮件;
在上图中,我们看到 BodyPart 还可以再包含 MultiPart ,很明显这是一种组合结构、模式,或者说成树状结构。
注:下面的类都是抽象类,其实它们之下就有 MimeMessage 类、MimeMultiPart 类、MimeBodyPart 类一一对应,如下图:
好了,用代码来说明问题,实现一下,不管是否合适,我还是在代码中写上较多注释,其中有一些事必须注意的,代码如下:
- /**
- * 创建内含图片的邮件,保存为 Outlook 的 ".eml" 文件
- * @author haolloyin
- */
- public class WithPictureMessage {
- public static void main(String[] args) throws Exception{
- String from = "test_hao@sina.cn";
- String to = "test_hao@163.com";
- String subject = "创建一个内含图片的邮件!";
- String body = "<h4>内含图片的邮件测试!!!</h4> " +
- "<a href = http://haolloyin.blog.51cto.com/> 蚂蚁</a></br></br>" +
- "<a href = http://haolloyin.blog.51cto.com/>" +
- "<img src = \"cid:haolloyin_logo_jpg\"></a>";
- /*
- * 上面的 cid 是指 MIME 协议中的 Content-ID 头,它是
- * 对于文件资源的唯一标识符,下面的 setContentID()方法
- * 中传入的 ID 号就必须与这个haolloyin_logo_jpg相一致
- */
- // 创建该邮件应用程序所需的环境信息以及会话信息
- Session session = Session.getDefaultInstance(new Properties());
- // 以下几句是设置邮件的基本信息
- MimeMessage msg = new MimeMessage(session);
- msg.setFrom(new InternetAddress(from));
- msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
- msg.setSubject(subject);
- msg.setSentDate(new Date());
- /*
- * 创建一个子类型为 “related” 的 MIME 消息组合对象,
- * 其实 MimeMultipart 类还有另外两种子类型,请自行
- * 查阅并比较其中的适用场景
- */
- MimeMultipart multipart = new MimeMultipart("related");
- /*
- * 创建一个表示 HTML 正文部分的 MimeBodyPart 对象,
- * 并加入 到上一语句创建的 MimeMultiPart 对象中,
- * 由于 HTML 正文中包含中文,故下面应该指定字符集为 gbk 或 gb2312
- */
- MimeBodyPart htmlBodyPart = new MimeBodyPart();
- htmlBodyPart.setContent(body, "text/html;charset=gbk");
- multipart.addBodyPart(htmlBodyPart);
- /*
- * 创建一个表示图片文件的 MimeBodyPart 对象,
- * 并加入 到上面所创建的 MimeMultiPart 对象中,
- * 使用 JAF 框架中的 FileDataSource 类获取图片文件源,
- * 它能够自动获知文件的 MIME 格式并设置好消息头
- */
- MimeBodyPart jpgBodyPart = new MimeBodyPart();
- FileDataSource fds = new FileDataSource("F:\\java\\haolloyin_logo.jpg");
- jpgBodyPart.setDataHandler(new DataHandler(fds));
- jpgBodyPart.setContentID("haolloyin_logo_jpg");
- multipart.addBodyPart(jpgBodyPart);
- /*
- * 这里不用再设置字符集了,因为上面的 HTML MimeBodyPart 对象中
- * 已经设置了,而图片文件的因为使用了 DataSource 对象,即 JAF 框架
- * 中的具体数据处理操作类,能够自动判断获知数据的 MIME 类型
- */
- msg.setContent(multipart);
- // 保存对邮件的修改并写入文件中
- msg.saveChanges();
- msg.writeTo(new FileOutputStream("withPictureMail.eml"));
- }
- }
编译、运行,生成 withPictureMail.eml 文件,双击打开,如下图:
在代码中的许多注释是比较重要的,必须要注意。此外,还可像上一篇文章中在 Outlook 中查看该 MIME 邮件的原始内容,其中应该既有 quoted-printable 编码也有 BASE64 编码方式,有兴趣的还可以看看各个消息头的格式是怎样的。
小结:
1、明白当 MIME 邮件需要附上多种格式(不仅仅是纯文本)的资源文件时,它是运用了层层嵌套的组合结构来表示、组织各个资源文件的;
2、在代码中的许多注释就是很重要的注意点了,必须掌握。
本文转自 xxxx66yyyy 51CTO博客,原文链接:http://blog.51cto.com/haolloyin/353957,如需转载请自行联系原作者