程序员的福音 - Apache Commons Email

1,276 阅读5分钟

此文是系列文章第七篇,前几篇请点击链接查看

程序猿的福音 - Apache Commons简介

程序员的福音 - Apache Commons Lang

程序员的福音 - Apache Commons IO

程序员的福音 - Apache Commons Codec

程序员的福音 - Apache Commons Compress

程序员的福音 - Apache Commons Exec

Apache Commons Email是用Java发送电子邮件的工具类库,提供了几种发送电子邮件的API。它构建在Java Mail API 之上,主要是为了简化它。

commons-email目前最新版本是1.5,最低要求Java6以上。

maven坐标如下:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-email</artifactId>
    <version>1.5</version>
</dependency>

Commons-Email的核心是Email类,它是一个抽象类,提供了发送邮件的核心功能。具体有以下几个实现类

SimpleEmail:发送简单邮件,即纯文本邮件

MultiPartEmail:发送带附件的邮件

HtmlEmail:发送超文本邮件

ImageHtmlEmail:发送图文混排的超文本邮件

下面是Email的类图

图片

通过类图可以看到很多额外信息:

HtmlEmail继承了MultiPartEmail,说明它也同时支持附件。

ImageHtmlEmail继承了HtmlEmail,说明它也同时支持附件和超文本。

下面简单介绍一下用法。

01. 邮箱设置

想要通过程序发送邮件,首先需要有一个邮箱做为发件人,并开启POP3/SMTP服务,获取对应邮箱的授权码,不同的邮箱开启方式和位置不甚相同,以下以163邮箱和QQ邮箱为例说明,其余邮箱可以自行搜索开启方式。

1. 163邮箱

进入邮箱首页,点击设置,选择下拉选项的POP3/SMTP/IMAP,点击进入“POP3/SMTP/IMAP”部分 ,点击“POP3/SMTP服务”后的【开启】,弹出页面,用绑定手机扫码发送短信,发送完毕后可获得授权码。

图片

图片

2. QQ邮箱

进入邮箱首页,点击设置,切换到账户页签,将页面滑动到“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 ”部分,点击“POP3/SMTP服务”后的【开启】,会弹出页面提醒用QQ绑定的手机号发送短信,发送完毕后,点击“我已发送”,即可获得授权码。

图片

02. 简单邮件

简单邮件就是纯文本邮件,格式简单,下面看看使用Java的API和Commons-Email的API的例子

Java API示例:

// 使用Java Mail API
Properties prop = new Properties();
prop.setProperty("mail.host", "smtp.qq.com");
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");
// 创建session
Session session = Session.getInstance(prop);
// Session的debug模式,设置为true能够查看到程序发送Email的运行状态
// session.setDebug(true);
Transport ts = session.getTransport();
// 以qq邮箱为例,需要开启POP3/SMTP服务,生成授权码供connect时使用
ts.connect("from@qq.com", "xxxxxxxxx");
// 创建邮件对象
MimeMessage message = new MimeMessage(session);
message.setFrom("from@qq.com");
message.setRecipient(Message.RecipientType.TO, new InternetAddress("to@163.com"));
message.setSubject("javamail简单文本邮件");
message.setContent("这是一封javamail发送的简单邮件", "text/html;charset=UTF-8");

// 发送
ts.sendMessage(message, message.getAllRecipients());
ts.close();

Commons Email 示例:

// Commons Email 示例
Email email = new SimpleEmail();
// 发送邮件的SMTP服务器,如果不设置,默认查询系统变量mail.smtp.host的值,没有则会抛出异常
// org.apache.commons.mail.EmailException: Cannot find valid hostname for mail session
email.setHostName("smtp.qq.com");
email.setSmtpPort(465);
// javax.mail.AuthenticationFailedException: 535 Login fail. Authorization code is expired
email.setAuthenticator(new DefaultAuthenticator("from@qq.com", "xxxxxxxxx"));
email.setSSLOnConnect(true);
email.setFrom("from@qq.com");
email.setSubject("TestMail");
email.setMsg("这是一封简单的邮件This is the third test mail ... :-)");
email.addTo("to@163.com");
email.send();

由以上例子可见Commons-Email的API看起来更简单清晰一些。不过由于纯文本邮件非常简单,所以两者的代码量并没有太大差异。

03. 复杂邮件

复杂邮件带格式,图片,附件等,下面看看使用Java的API和Commons-Email的API的例子

Java API示例:

// 使用Java Mail API
Properties prop = new Properties();
prop.setProperty("mail.host", "smtp.qq.com");
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");
// 创建session
Session session = Session.getInstance(prop);
Transport ts = session.getTransport();
ts.connect("smtp.qq.com", "from@qq.com", "xxxxxxxx");
MimeMessage message = new MimeMessage(session);
// 设置基本信息
message.setFrom(new InternetAddress("from@qq.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("to@163.com"));
message.setSubject("javamail发送的比较全面的带有附件和带图片及正文的邮件");
// 内容
MimeBodyPart text = new MimeBodyPart();
text.setContent("简单的头像:<br/><img src='cid:portrait.jpg'>", "text/html;charset=UTF-8");
// 图片
MimeBodyPart image = new MimeBodyPart();
image.setDataHandler(new DataHandler(new FileDataSource("D:\\commons mail\\images\\5.jpg")));
image.setContentID("portrait.jpg");
// 附件1
MimeBodyPart attachment = new MimeBodyPart();
DataHandler handler = new DataHandler(new FileDataSource("D:\\commons mail\\files\\test.docx"));
attachment.setDataHandler(handler);
attachment.setFileName(handler.getName());
// 附件2
MimeBodyPart attachment2 = new MimeBodyPart();
DataHandler handler2 = new DataHandler(new FileDataSource("D:\\commons mail\\files\\test2.txt"));
attachment2.setDataHandler(handler2);
attachment2.setFileName(MimeUtility.encodeText(handler2.getName()));
// 构建
MimeMultipart part = new MimeMultipart();
part.addBodyPart(text);
part.addBodyPart(image);
part.setSubType("related");
MimeMultipart part2 = new MimeMultipart();
part2.addBodyPart(attachment);
part2.addBodyPart(attachment2);
MimeBodyPart content = new MimeBodyPart();
content.setContent(part);
part2.addBodyPart(content);
part2.setSubType("mixed");
message.setContent(part2);
message.saveChanges();
// 发送
ts.sendMessage(message, message.getAllRecipients());
ts.close();

Commons Email 示例:

// Commons Email 示例
HtmlEmail email = new HtmlEmail();
// 设置基本信息
email.setHostName("smtp.qq.com");
email.setAuthenticator(new DefaultAuthenticator("from@qq.com", "xxxxxxxx"));
email.setFrom("from@qq.com");
email.addTo("to@163.com");
email.setSubject("commons mail发送的比较全面的带有附件和带图片及正文的邮件");
// 生成图片标识
String cid = email.embed(new File("D:\\commons mail\\images\\5.jpg"));
email.setCharset(EmailConstants.UTF_8);
email.setHtmlMsg("<html>简单的头像:<br/><img src=\"cid:" + cid + "\"></html>");
// 额外提示
email.setTextMsg("您的邮件不支持html格式");
// 附件
EmailAttachment attachment = new EmailAttachment();
attachment.setPath("D:\\commons mail\\files\\test.docx");
EmailAttachment attachment2 = new EmailAttachment();
attachment2.setPath("D:\\commons mail\\files\\test2.txt");
email.attach(attachment);
email.attach(attachment2);
// 发送
email.send();

以上例子可以看出用Commons Email发送复杂邮件比较Java原生API要简单很多。

04. ImageHtmlEmail

上一章节的示例可以看出HtmlEmail其实也可以发送图片,那ImageHtmlEmail存在的意义是什么呢?

其实HtmlEmail发送图片都需要调用其embed方法,并将其返回值设置到标签的src上,示例如下

// embed方法有多个重载方法,支持URL,本地文件等
String cid = email.embed(new File("D:\\commons mail\\images\\5.jpg"));
email.setHtmlMsg("<html><img src=\"cid:" + cid + "\"></html>");

ImageHtmlEmail只需要设置对应的Resolver。如果发送图片较多,使用此类会方便不少,下面看一个简单的例子

// 省略部分代码 ...
ImageHtmlEmail email = new ImageHtmlEmail();
URL url = new URL("http://example.com");
email.setDataSourceResolver(new DataSourceUrlResolver(url));
email.setHtmlMsg("<img src=\"http://example.com/test.png\"> ...");
// 省略部分代码 ...

如果发送多张不同来源的图片需要依赖DataSourceCompositeResolver类,是组合模式的一种实现,支持同时设置多个resolver,下面直接看代码示例

// 省略部分代码 ...
ImageHtmlEmail email = new ImageHtmlEmail();
// 本地路径
File file = new File("D:\\commons email");
// 网络上的路径
URL url = new URL("http://example.com");
// 类路径
String classpath = "META-INF/img";
DataSourceResolver r1 = new DataSourceFileResolver(file);
DataSourceResolver r2 = new DataSourceUrlResolver(url);
DataSourceResolver r3 = new DataSourceClassPathResolver(classpath);
DataSourceResolver[] resolvers = {r1, r2, r3};
// 组合resolver, 可以接收多个resolver
DataSourceResolver compositeResolver = new DataSourceCompositeResolver(resolvers);
email.setDataSourceResolver(compositeResolver);
email.setHtmlMsg("图片1: <br>" +
        "<img src=\"D:\\commons email\\t1.png\">" +
        "图片2: <br>" +
        "<img src=\"http://example.com/t2.png\">" +
        "图片3: <br>" +
        "<img src=\"META-INF/img/t3.png\">");
// 省略部分代码 ...

05. 总结

Commons Email做为Java发送电子邮件的工具类,API简单易懂,大大简化了Java邮件发送程序的复杂度。用来代替Java自带的API是不错的选择。

后续章节我将继续给大家介绍commons中其他好用的工具类库,期待你的关注。