您的位置:首页 > 编程语言 > Java开发

JavaMail介绍及相关类介绍

2016-03-07 11:42 597 查看
JavaMail是SUN提供给开发人员在应用程序中实现“邮件发送和接收功能”的一套标准开发类库,支持常用的邮件协议,如SMTP、POP3、IMAP。
SMTP:简单邮件传输协议,用于发送电子邮件的传输协议;
POP3:邮局协议,用于接收电子邮件的标准协议;
IMAP:互联网消息访问协议,是POP3的替代协议。(这三种协议都有对应SSL加密传输的协议,分别是SMTPS,POP3S和IMAP3)。

MIME:多用途因特网邮件扩展别准,它不是邮件传输消息,但对传输内容的消息、附件及其他的内容定义了格式。
开发人员使用JavaMail编写邮件程序时,无需考虑底层的通信细节(Socket),JavaMail也提供了能够创建出各种复杂MIME格式的邮件内容的API。使用JavaMail,我们可以实现类似OutLook、FoxMail的软件。虽然JavaMail(仅支持JDK4及以上)也是Java的API之一,但是却没有直接加入到JDK中,所以我们需要另行下载。另外,JavaMail依赖JAF(JavaBeans Activation Framework)来处理不是纯文本的邮件内容(如MIME多用途互联网邮件扩展、URL页面和文件附件等内容),JAF在Java6之后已经合并到JDK中,而JDK5之前需要另外下载JAF的类库。下载地址如下: JavaMail:http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-eeplat-419426.html#javamail-1.4.5-oth-JPR JavaMail spec:http://www.oracle.com/technetwork/java/javamail-1-149769.pdf JAF:http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html#jaf-1.1.1-fcs-oth-JPR JavaMail下载好后,我们来看一下其主要内容:
README.txt:整体介绍JavaMail,需要看一下
docs/javadocs:The JavaMail API javadocs,需要看一下
mail.jar:包括JavaMail API和所有service providers,大部分用户只需要该jar包
lib/mailapi.jar	:只有JavaMail API
lib/imap.jar:The IMAP service provider
lib/smtp.jar:The SMTP service provider
lib/pop3.jar:The POP3 service provider
lib/dsn.jar:multipart/report DSN message support
demo:demo示例,简单了解,有需要再看
JavaMail包含两部分内容,一部分是JavaMail API,定义了一组平台无关、独立于通讯协议的邮件程序框架,该部分称为应用级接口,也就是供我们调用的部分,另一部分是service provider,该部分使用特定的协议语言来实现第一部分定义的抽象类和接口,这些协议包括:SMTP、NNTP、POP3、IMAP,如果让JavaMail与邮件服务器通信,就需要相应的协议支持,该部分称为服务提供者接口,也就是JavaMail自身需要的协议支持。在使用JavaMail时,通常我们只需将mail.jar放在classpath下使用,它包含了JavaMail API部分和SUN自己实现的service provider部分。可能也有特殊的时候,我们应用程序中需要自己实现service provider部分,那我们只需要mailapi.jar。下面通过几个类来简单认识下JavaMail API:
javax.mail.Session:上下文环境信息,如服务器的主机名、端口号、协议名称等
javax.mail.Message:邮件模型,发送邮件和接收邮件的媒介,封装了邮件的信息,如发件人、收件人、邮件标题、邮件内容等
javax.mail.Transport:连接邮件SMTP服务器,发送邮件
javax.mail.Store:连接邮件POP3、IMAP服务器,收取邮件
通过这些类,最终就可以实现收发邮件,一个发送邮件的简单示例:
public class JavaMailTest1 {
public staticvoid main(String[] args) throws MessagingException {
Properties props = new Properties();
// 开启debug调试
props.setProperty("mail.debug", "true");
// 发送服务器需要身份验证
props.setProperty("mail.smtp.auth", "true");
// 设置邮件服务器主机名
props.setProperty("mail.host", "smtp.163.com");
// 发送邮件协议名称
props.setProperty("mail.transport.protocol", "smtp");

// 设置环境信息
Session session = Session.getInstance(props);

// 创建邮件对象
Message msg = new MimeMessage(session);
msg.setSubject("JavaMail测试");
// 设置邮件内容
msg.setText("这是一封由JavaMail发送的邮件!");
// 设置发件人
msg.setFrom(new InternetAddress("java_mail_001@163.com"));

Transport transport = session.getTransport();
// 连接邮件服务器
transport.connect("java_mail_001", "javamail");
// 发送邮件
transport.sendMessage(msg, new Address[] {new InternetAddress("java_mail_002@163.com")});
// 关闭连接
transport.close();
}
}
最终运行后,邮件发送成功。由于我们开启了debug调试,在控制台可以看到JavaMail和服务器之间的交互信息记录。

PS:文中示例以及以后的示例中所用的邮箱账户均为在163申请的测试账户,分别为java_mail_001至java_mail_004,密码均为javamail。

JavaMail API使用上非常灵活。它对收发邮件进行了高级的抽象,形成了一些关键的接口和类,它们构成了程序的基础,下面分别介绍这些对象:Properties
属性对象。由于JavaMail需要和邮件服务器进行通信,这就要求程序提供许多诸如服务器地址、端口、用户名、密码等信息,JavaMail通过Properties对象封装这些属性信息。例如
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.sina.com.cn");
props.put("mail.smtp.auth", "true");
针对不同的邮件协议,JavaMail规定了服务提供者必须支持一系列属性,下表是针对SMTP协议的一些常见属性(属性值都以String类型进行设置,属性类型栏仅表示属性是如何被解析的):
属性名属性类型说明
mail.stmp.hostStringSMTP服务器地址,如smtp.sina.com.cn
mail.stmp.portintSMTP服务器端口号,默认为25
mail.stmp.authbooleanSMTP服务器是否需要用户认证,默认为false
mail.stmp.userStringSMTP默认的登陆用户名
mail.stmp.fromString默认的邮件发送源地址
mail.stmp.socketFactory.classStringsocket工厂类类名,通过设置该属性可以覆盖提供者默认的实现,必须实现javax.net.SocketFactory接口
mail.stmp.socketFactory.portint指定socket工厂类所用的端口号,如果没有规定,则使用默认的端口号
mail.smtp.socketFactory.fallbackboolean设置为true时,当使用指定的socket类创建socket失败后,将使用java.net.Socket创建socket,默认为true
mail.stmp.timeoutintI/O连接超时时间,单位为毫秒,默认为永不超时
其他几个协议也有类似的一系列属性,如POP3的mail.pop3.host、mail.pop3.port以及IMAP的mail.imap.host、mail.imap.port等。更详细的信息请查看com.sun.mail.smtp、com.sun.mail.pop3和com.sun.mail.imap这三个包的Javadoc:http://java.sun.com/products/javamail/javadocs/index.html

Session

会话对象。千万别以为这里的Session向HTTPSession一样代表真实的交互会话,创建Session对象时,并没有对应的物理连接,它只不过是一对配置信息的集合。主要作用包括两个方面: 1)接收各种配置属性信息:通过Properties对象设置的属性信息;
2)初始化JavaMail环境:根据JavaMail的配置文件,初始化JavaMail环境,以便通过Session对象创建其他重要类的实例。 JavaMail分为API和service provider两部分,API定义了相关接口(eg.:Transport andStore),service provider中实现了这些接口。JavaMail提供的mail.jar/smtp.jar/pop3.jar/imap.jar等jar包的META-INF目录下,通过javamail.providers或javamail.default.provider、javamail.address.map和javamail.default.address.map文件提供了基本的配置信息,以便session能够根据这个配置文件家在提供者的实现类。javamail.default.provider文件的配置信息如:
# JavaMail IMAP provider Sun Microsystems, Inc
protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Sun Microsystems, Inc;
protocol=imaps; type=store; class=com.sun.mail.imap.IMAPSSLStore; vendor=Sun Microsystems, Inc;
# JavaMail SMTP provider Sun Microsystems, Inc
protocol=smtp; type=transport; class=com.sun.mail.smtp.SMTPTransport; vendor=Sun Microsystems, Inc;
protocol=smtps; type=transport; class=com.sun.mail.smtp.SMTPSSLTransport; vendor=Sun Microsystems, Inc;
# JavaMail POP3 provider Sun Microsystems, Inc
protocol=pop3; type=store; class=com.sun.mail.pop3.POP3Store; vendor=Sun Microsystems, Inc;
protocol=pop3s; type=store; class=com.sun.mail.pop3.POP3SSLStore; vendor=Sun Microsystems, Inc;
每一行声明了协议名称、协议类型、实现类、供应商、版本等信息,如果需要自己实现相应的协议,必须按照该格式配置好,Java Mail API中才能正确的调用到。 Session在加载配置文件时会按照以下优先级顺序进行: 1)首先使用<JAVA_HOME>/lib中的javamail.providers; 2)如果1)不存在相应的配置文件,使用类路径下mail.jar中META-INF目录下的javamail.providers; 3)如果2)不存在相应的配置文件,使用类路径下的mail.jar中META-INF目录下的javamail.default.providers; 所以开发者可以在<JAVA_HOME>/lib目录下提供配置文件覆盖mail.jar/META-INF目录中厂商的配置。但是,一般情况下,我们无须这样做。 Session用于收集JavaMail运行过程中的环境信息,它可以创建一个单例的对象,也可以每次创建新的对象,Session没有构造器,但拥有多个静态工厂方法用于创造实例:
static Session
getDefaultInstance(Properties props)

Get the default Session object.
static Session
getDefaultInstance(Properties props,Authenticator authenticator)

Get the default Session object.
static Session
getInstance(Properties props)

Get a new Session object.
static Session
getInstance(Properties props,Authenticator authenticator)

Get a new Session object.
l static Session getDefaultInstance(Properties props, Authenticator authenticator):当JVM中已经存在默认的Session实例中,直接返回这个实例,否则创建一个新的Session实例,并将其作为JVM中默认Session实例。这个API很诡异,我们将对它进行详细的讲解。由于这个默认Session实例可以被同一个JVM所有的代码访问到,而Session中本身又可能包括密码、用户名等敏感信息在内的所有属性信息,所以后续调用也必须传入和第一次相同的Authenticator实例,否则将抛出java.lang.SecurityException异常。如果第一次调用时Authenticator入参为null,则后续调用通过null的Authenticator入参或直接使用getDefaultInstance(Properties props)即可返回这个默认的Session实例。值得一提的是,虽然后续调用也会传入Properties,但新属性并不会起作用,如果希望采用新的属性值,则可以通过getDefaultInstance(Properties props)创建一个新的Session实例达到目的。Authenticator在这里承当了两个功能:首先,对JVM中默认Session实例进行认证保护,后续调用执行getDefaultInstance(Properties props, Authenticator authenticator)方法时必须和第一次一样;其次,在具体和邮件服务器交互时,又作为认证的信息;l static Session getDefaultInstance(Properties props):返回JVM中默认的Session实例,如果第一次创建Session未指定Authenticator入参,后续调用可以使用该访问获取Session;l static Session getInstance(Properties props, Authenticator authenticator):创建一个新的Session实例,它不会在JVM中被作为默认实例共享;l static Session getInstance(Properties props):根据相关属性创建一个新的Session实例,未使用安全认证信息; getDefaultInstance得到的始终是该方法初次创建的缺省的对象,而getInstance得到的始终是新的对象,Authenticator的使用后面会说到。Session是JavaMail提供者配置文件以及设置属性信息的“容器”,其本身不会和邮件服务器进行任何的通信。所以,一般情况下,我们仅需要通过getDefaultInstance获取一个共享的Session实例就可以了。例如:
Properties props = System.getProperties();
props.setProperty("mail.transport.protocol", "smtp");              …
Session session = Session.getDefaultInstance(props);

Message

消息对象。Message是邮件的载体,用于封装邮件的所有信息,Message是一个抽象类,已知的实现类有MimeMessage。
MimeMessage message=new MimeMessage(session)
ps:Address类:地址。一旦你创建了Session和Message,并将内容填入消息后,就可以用Address确定信件地址了。和Message一样,Address也是一个抽象类,常用InternetAddress类实例。
若创建的地址只包含电子邮件地址,只要传递电子邮件地址到构造器就行了。
Address address = new InternetAddress("president@whitehouse.gov");
若希望名字紧挨着电子邮件显示,也可以把它传递给构造器:
Address address = new InternetAddress("president@whitehouse.gov", "George Bush");
下面来看下Message中设置邮件信息的一些方法。

发件人

abstractvoid
setFrom()

Set the "From" attribute in this Message.
abstractvoid
setFrom(Address address)

Set the "From" attribute in this Message.
现在大多数SMTP服务器要求发件人与连接账户必须一致,否则会抛出验证失败的异常,这样是防止用户伪装成其它人的账户恶意发送邮件。 如果需要消息显示多个 from 地址,可以使用 addFrom() 方法: Address address[] = ...; message.addFrom(address);

收件人/抄送人/暗送人

void
setRecipient(Message.RecipientType type,Address address)

Set the recipient address.
abstractvoid
setRecipients(Message.RecipientType type,Address[] addresses)

Set the recipient addresses.
第一个方法设置单个人,第二个方法设置多个人。 方法中第一个参数涉及到另一个类RecipientType(预定义地址),该类是Message的静态内部类,期内有三个常量值:
static Message.RecipientType
BCC

The "Bcc" (blind carbon copy) recipients.
static Message.RecipientType
CC

The "Cc" (carbon copy) recipients.
static Message.RecipientType
TO

The "To" (primary) recipients.
TO - 收件人;CC - 抄送人;BCC - 暗送人。

回复人

void
setReplyTo(Address[] addresses)

Set the addresses to which replies should be directed.
设置收件人收到邮件后的回复地址。

标题

abstractvoid
setSubject(String subject)

Set the subject of this message.
设置邮件标题/主题。

内容

void
setContent(Multipart mp)

This method sets the given Multipart object as this message's content.
void
setContent(Object obj,String type)

A convenience method for setting this part's content.
void
setText(String text)

A convenience method that sets the given String as this part's content with a MIME type of "text/plain".
设置邮件文本内容、HTML内容、附件内容。示例 如果消息是发给副总统的,同时发送一个副本(carbon copy)给总统夫人,以下做法比较恰当:
Address toAddress = new InternetAddress("vice.president@whitehouse.gov");
Address ccAddress = new InternetAddress("first.lady@whitehouse.gov");
message.addRecipient(Message.RecipientType.TO, toAddress);
message.addRecipient(Message.RecipientType.CC, ccAddress);
Transport和Store 传输和存储。通过Session可以创建Transport(用于发送邮件)和Store(用于接收邮件)。创建机制:我们知道提供者在javamail.providers配置文件中为每一种支持的邮件协议定义了实现类,Session根据协议类型(stmp、pop3等)和邮件操作方式(传输和存储)这两个信息就可以定位到一个实例类上。比如,指定stmp协议和transport类型后,Session就会使用com.sun.mail.smtp.SMTPTransport实现类创建一个Transport实例,而指定pop3协议和store类型时,则会使用com.sun.mail.pop3.POP3Store实例类创建一个Store实例。Session提供了多个重载的getTransport()和getStore()方法,这些方法将根据Session中Properties属性设置情况进行工作,影响这两套方法工作的属性包括:
属性名说明
mail.transport.protocol默认的邮件传输协议,例如,smtp
mail.store.protocol默认的存储邮件协议,例如:pop3
mail.host默认的邮件服务地址,例如:192.168.67.1
mail.user默认的登陆用户名,例如:zapldy
Session中提供的创建Trasnsport和Store的方法如下(当Session实例设置了mail.transport.protocol属性时,该方法返回对应的Transport实例,否则抛出javax.mail.NoSuchProviderException。如果Session没有设置mail.transport.protocol属性,可以通过该方法返回指定类型的Transport,如transport = session.getTransport(“smtp”)。):
Store
getStore()

Get aStore object that implements this user's desiredStore protocol.
Store
getStore(Provider provider)

Get an instance of the store specified by Provider.
Store
getStore(String protocol)

Get aStore object that implements the specified protocol.
Store
getStore(URLName url)

Get aStore object for the given URLName.
Transport
getTransport()

Get aTransport object that implements this user's desiredTransport protcol.
Transport
getTransport(Address address)

Get aTransport object that can transport a Message of the specified address type.
Transport
getTransport(Provider provider)

Get an instance of the transport specified in the Provider.
Transport
getTransport(String protocol)

Get aTransport object that implements the specified protocol.
Transport
getTransport(URLName url)

Get aTransport object for the given URLName.
可以看到,重构了很多,这些方法最终都会去解析上文提到的配置文件,找到对应配置信息。 如果Session中未包含Authenticator,以上两方法创建的Transport实例和邮件服务器交互时必须显示提供用户名/密码的认证信息。如果Authenticator非空,则可以在和邮件服务器交互时被作为认证信息使用。除了以上两种提供认证信息的方式外,Session还可以使用以下的方法为Transport提供认证信息。Transport getTransport(URLName url):用户可以通过URLName入参指定邮件协议、邮件服务器、端口、用户名和密码信息,请看下面的代码:
URLName urln = new URLName(“smtp”, “smtp.sina.com.cn”, 25, null, “masterspring2”, “spring”);
Transport transport = session.getTransport(urln);
这里,指定了邮件协议为smtp,邮件服务器是smtp.sina.com.cn,端口为25,用户名/密码为masterspring2/spring。

消息发送:使用Transport 类。这个类用协议指定的语言发送消息(通常是 SMTP)。它是抽象类,它的工作方式与 Session 有些类似,仅调用静态 send() 方法,就能使用类的缺省版本:
Transport.send(message);
或者,您也可以从针对您的协议的会话中获得一个特定的实例,传递用户名和密码(如果不必要就不传),发送消息,然后关闭连接。
message.saveChanges(); // implicit with send()
Transport transport = session.getTransport("smtp");
transport.connect(host, username, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
后面这种方法在您要发送多条消息时最好,因为它能保持邮件服务器在消息间的活动状态。基本 send() 机制为每个方法的调用设置与服务器独立的连接。 注意:要观察传到邮件服务器上的邮件命令,请用 session.setDebug(true) 设置调试标志。 获取消息:用 Session 获取消息与发送消息开始很相似。但是,在 session 得到后,很可能使用用户名和密码或使用 Authenticator 连接到一个Store。类似于Transport ,您告知Store 使用什么协议:
    //Store store = session.getStore("imap");
Store store = session.getStore("pop3");
store.connect(host, username, password);
连接到Store 之后,接下来,您就可以获取一个 Folder,您必需先打开它,然后才能读里面的消息。
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
Message message[] = folder.getMessages();
POP3 唯一可以用的文件夹是 INBOX。如果使用 IMAP,还可以用其它文件夹。 注意:Sun 的供应商有意变得聪明。虽然 Message message[] = folder.getMessages(); 看上去是个很慢的操作,它从服务器上读取每一条消息,但仅在你实际需要消息的一部分时,消息的内容才会被检索。 一旦有了要读的 Message,您可以用 getContent() 来获取其内容,或者用 writeTo() 将内容写入流。getContent() 方法只能得到消息内容,而 writeTo() 的输出却包含消息头。
System.out.println(((MimeMessage)message).getContent());
一旦读完邮件,要关闭与 folder 和 store 的连接。
folder.close(aBoolean);
store.close();
传递给 folder 的 close() 方法的 boolean 表示是否清除已删除的消息从而更新 folder。

示例

下面来看一个稍复杂点的示例:
public class JavaMailTest2 {

public staticvoid main(String[] args) throws MessagingException {
Properties props = new Properties();
// 开启debug调试
props.setProperty("mail.debug", "true");
// 发送服务器需要身份验证
props.setProperty("mail.smtp.auth", "true");
// 设置邮件服务器主机名
props.setProperty("mail.host", "smtp.163.com");
// 发送邮件协议名称
props.setProperty("mail.transport.protocol", "smtp");

// 设置环境信息
Session session = Session.getInstance(props, new Authenticator() {
// 在session中设置账户信息,Transport发送邮件时会使用
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("java_mail_001", "javamail");
}
});

// 创建邮件对象
Message msg = new MimeMessage(session);
// 发件人
msg.setFrom(new InternetAddress("java_mail_001@163.com"));
// 多个收件人
msg.setRecipients(RecipientType.TO, InternetAddress.parse("java_mail_002@163.com,java_mail_003@163.com"));
// 抄送人
msg.setRecipient(RecipientType.CC, new InternetAddress("java_mail_001@163.com"));
// 暗送人
msg.setRecipient(RecipientType.BCC, new InternetAddress("java_mail_004@163.com"));

// 主题
msg.setSubject("中文主题");
// HTML内容
msg.setContent("<div align=\"center\">你好啊</div>", "text/html;charset=utf-8");

// 连接邮件服务器、发送邮件、关闭连接,全干了
Transport.send(msg);
}

}





本文来自: 高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/17839983 zapldy,原文地址:http://blog.csdn.net/zapldy/article/details/3971579
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java mail