什么是SMTP
SMTP 是Simple Mail Transfer Protocol (SMTP)的简称,由 RFC 821 定义。它是一个用来发送电子邮件的协议,互联网上绝大部分的邮件系统都使用SMTP作为邮件传输机制。
怎样使用Java Mail API来发送邮件
依赖
首先,添加Java Mail依赖:
<dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency>
设置
当我们使用某些邮件客户端,例如Outlook,作为代理来接收邮件时,需要提供以下信息:
- 协议 : SMTP 用于发送; POP3 或 IMAP 用于接收
- 主机 : 用于发送和接收邮件的服务器主机地址
- 端口 : 服务器主机上对应于上述协议的邮件收发端口
- 用户名: 用于访问以上邮件服务器的用户名
- 密码 : 用于访问以上邮件服务器的、对应于用户名的密码
同样的,当使用Java mail API去实现自己的邮件收送端时,也需要以上的信息,例如:
Properties properties = System.getProperties(); properties.setProperty("mail.smtp.host", "smtp.sohu.com"); //provide host, default is localhost properties.setProperty("mail.smtp.port", "25"); //provide port, default is 25 properties.setProperty("mail.smtp.auth", "true"); //indicate authentication is required or not, it's required by most of servers这些信息也可以存在一个Properties文件里,然后读取这个文件来获取山配置:
mail.smtp.host=smtp.sohu.com mail.smtp.port=25 mail.smtp.auth=true ...
然后加载:
FileInputStream is = new FileInputStream("mail.properties"); properties.load(is); is.close();
Session(会话)
接下来,就需要创建一个 Session, 一个邮件 Session 管理着配置选项和用来连接服务器以进行交互的用户认证信息,以下代码用来创建一个Session:
Session session = Session.getDefaultInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(properties.getProperty("username"), properties.getProperty("password")); } });
需要提供用户名、密码和其他的一些配置信息(Setting一节中介绍了)来创建一个Session。
发送文本
有了Session以后,就可以准备发送邮件了。在Java mail API里,每个邮件都由一个 javax.mail.Message 对象表示,然而 javax.mail.Message 是一个抽象类,因此需要转向它的一个具体实现,通常使用 javax.mail.internet.MimeMessage,下面代码展示了一个最简单的、用于发送文本邮件的方式:
MimeMessage message = new MimeMessage(session); message.setText("Hello Java Mail Body"); message.setSubject("Hello Java Mail"); message.setFrom(new InternetAddress(properties.getProperty("from"))); message.addRecipient(RecipientType.TO, new InternetAddress(properties.getProperty("to"))); message.saveChanges(); Transport.send(message);
这里多了一个From和To用来表示邮件的发送者和接收者,以上示例中,这两个值也来自properties文件。
Content-Type(内容类型)
当使用setText()方法设置邮件内容里,默认的Content-Type类型是 text/plain 。当发送邮件时,也可以指定期望的 Content-Type 值,方法之一就是使用 setDataHandler() 而不是 setText() 去设置邮件内容:
DataHandler dh = new DataHandler("<p style='color:red'>Html Mail Content</p>", "text/html"); message.setDataHandler(dh);
以上内容在邮件中展示后,类似于:
Html Mail Content
而如果把 Content-Type 从 "text/html" 变成 "text/plain",则结果大不一样了:
<p style='color:red'>Html Mail Content</p>
Multipart(复杂类型)
以上例子是一个简单,消息只包含单一类型的邮件内容,这个内容包装在一个 DataHandler 实例里(实际上,私底下所有的邮件内容都包装在一个 DataHandler 实例中,不管是通过 setText() 还是 setContent() 方法),以下是简单消息的一个结构图:
除了以上简单消息结构,消息也可以包含复杂类型的结构,这种情况下 DataHandler 对象包含的就是一个multipart 对象,而不是仅仅是一个单一的内容块。一个multipart 对象是一个 BodyPart 对象的容器,一个 BodyPart 对象的结构有点类似于 以上简单消息对象的结构,因为他们两都实现了 Part 接口。每一个 BodyPart 对象都包含了属性( attributes)和内容(content),但是 Bodypart 对象的属性只限定于定义在 Part 接口中的那些。一个重要的属性就是 content-type 。一个 BodyPart 对象的内容又是一个DataHandler 对象,它可以包含数据或者另一个 Multipart 对象,因此它是一个递归的结构:
下面是一个 multipart 的代码示例:
MimeMultipart mmp = new MimeMultipart(); // create textual content, and add it to the bodypart object MimeBodyPart body1 = new MimeBodyPart(); body1.setContent("<h1>Mail HTML Body Content</h1>", "text/html"); mmp.addBodyPart(body1); // Create a second body part object, set text to it, This // second object holds xml data. MimeBodyPart body2 = new MimeBodyPart(); body2.setContent("<a>Mail XML Content</a>", "application/xml"); mmp.addBodyPart(body2); message.setContent(mmp);
第一个body对象会作为邮件内容,以HTML格式呈现,第二部分内容会作一个XML格式的附件发送,附件名不定。
附件
以上介绍了一个发送附件的变通方法,但不是通常的选择。这一节里将介绍怎么用Java Mail API发送含有一个或多个附件的邮件,将以上示例中的 body2 内容作为一个实际的附件,而是上示的奇怪的方式。
首先将内容存成一个xml文件,假设文件名为: 'attach.xml',然后用以下代码添加为附件发送:
... MimeBodyPart body2 = new MimeBodyPart(); //old one // body2.setContent("<a>Mail XML Content</a>", "application/xml"); //new one FileDataSource attachment = new FileDataSource("attach.xml"); DataHandler dh = new DataHandler(attachment); body2.setDataHandler(dh); body2.setFileName("attach.xml"); mmp.addBodyPart(body2); ...
然后接收端就可以收到一个命令文件名为 'attach.xml' 的附件的邮件了。
更多...
如果连接要求 SSL 配置,则更多的设置选项需要被指定,例如 GMail的连接:
Properties props = System.getProperties(); props.setProperty("mail.smtp.host", "smtp.gmail.com"); props.setProperty("mail.smtp.port", "465"); props.setProperty("mail.smtp.auth", "true"); //more configurations props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.setProperty("mail.smtp.socketFactory.fallback", "false"); props.setProperty("mail.smtp.socketFactory.port", "465");
怎样使用camel-mail组件
依赖
添加以下依赖:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-mail</artifactId> <version>2.12.2</version> </dependency>
URI 格式
smtp://[username@]host[:port][?options]
或者是带安全的连接:
smtps://[username@]host[:port][?options]
缺省 Ports
|
|
|
|
|
|
选项
下面是一些基础选项,更多的可以看 http://camel.apache.org/mail.html :
| Default | Description |
|
| The host name or IP address to connect to. |
| See DefaultPorts | The TCP port number to connect on. |
|
| The user name on the email server. |
|
| The password on the email server. |
|
| The mail message content type. Use |
|
| The TO recipients (the receivers of the mail). Separate multiple email addresses with a comma. |
|
| As of Camel 2.8.4, 2.9.1+, the Reply-To recipients (the receivers of the response mail). Separate multiple email addresses with a comma. |
|
| The CC recipients (the receivers of the mail). Separate multiple email addresses with a comma. |
|
| The BCC recipients (the receivers of the mail). Separate multiple email addresses with a comma. |
|
| The FROM email address. |
|
| As of Camel 2.3, the Subject of the message being sent. Note: Setting the subject in the header takes precedence over this option. |
|
| The connection timeout in milliseconds. Default is 30 seconds. |
根据介绍,基本可以理解这些选项的意义和用法。
示例
下面是一些用camel-mail组件展示如何发送邮件的例子。
发送文本
from("timer:foo?repeatCount=1") .setBody(constant("MailBody")) //set mail body .to( "smtp:" //protocol, required + "//" + "host" //host, required, change as your case + ":" + "port" //port, has default value, change as your case + "?" + "from=from" //from, default is camel@localhost, change as your case + "&" + "username=from" //username, required , change as your case + "&" + "password=password" //password, required , change as your case + "&" + "subject=MailSubject" //mail subject + "&" + "to=to" //to, required, change as your case );
邮件的内容来自camel route的exchange的body。
Content-Type
默认的 Content-Type 为 text/plain,因此接收到文件内容就是纯文本的,没有任何修饰的,例如<b>MailBody</b>,如果想把它变成一个 HTML 格式的,则需要指定 Content-Type 为 text/html,例如:
from("timer:foo?repeatCount=1") .setBody(constant("<b>MailBody</b>"))//set body .to( "smtp:" //protocol, required + "//" + "host" //host, required, change as your case + ":" + "port" //port, has default value, change as your case + "?" + "from=from" //from, default is camel@localhost, change as your case + "&" + "username=username" //username, required , change as your case + "&" + "password=password" //password, required , change as your case + "&" + "subject=MailSubject" //mail subject + "&" + "to=to" //to, required, change as your case + "&" + "contentType=text/html" //specify content-type );
现在邮件内容会以HTML格式呈现:MailBody
附件
按我的了解,好像没有简单的选项可以指定附件,方法之一就是使用Bean或者是Processor去指定附件,例如:
from("timer:foo?repeatCount=1").process(new Processor() { public void process(Exchange exchange) throws Exception { exchange.getIn().setBody(constant("<h1>Mail HTML Body Content</h1>"));//set Body exchange.getIn().addAttachment("attach.xml", new DataHandler(new FileDataSource("attach.xml"))); //Add attachment } }).to("smtp://...");