Java Mail API和camel-mail组件

什么是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,作为代理来接收邮件时,需要提供以下信息:

  1. 协议 : SMTP 用于发送; POP3 或 IMAP 用于接收
  2. 主机 : 用于发送和接收邮件的服务器主机地址
  3. 端口 : 服务器主机上对应于上述协议的邮件收发端口
  4. 用户名: 用于访问以上邮件服务器的用户名
  5. 密码 : 用于访问以上邮件服务器的、对应于用户名的密码

同样的,当使用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);

这里多了一个FromTo用来表示邮件的发送者和接收者,以上示例中,这两个值也来自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

Protocol

Default Port Number

SMTP

25

SMTPS

465

选项

下面是一些基础选项,更多的可以看 http://camel.apache.org/mail.html :

Property

Default

Description

host

 

The host name or IP address to connect to.

port

See DefaultPorts

The TCP port number to connect on.

username

 

The user name on the email server.

password

null

The password on the email server.

contentType

text/plain

The mail message content type. Use text/html for HTML mails.

to

username@host

The TO recipients (the receivers of the mail). Separate multiple email addresses with a comma.

replyTo

alias@host

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.

CC

null

The CC recipients (the receivers of the mail). Separate multiple email addresses with a comma.

BCC

null

The BCC recipients (the receivers of the mail). Separate multiple email addresses with a comma.

from

camel@localhost

The FROM email address.

subject

 

As of Camel 2.3, the Subject of the message being sent. Note: Setting the subject in the header takes precedence over this option.

connectionTimeout

30000

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://...");

猜你喜欢

转载自liugang594.iteye.com/blog/2020915