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 static void 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");



(属性值都以String类型进行设置,属性类型栏仅表示属性是如何被解析的):


属性名

属性类型

说明

mail.stmp.host

String

SMTP服务器地址,如smtp.sina.com.cn

mail.stmp.port

int

SMTP服务器端口号,默认为25

mail.stmp.auth

boolean

SMTP服务器是否需要用户认证,默认为false

mail.stmp.user

String

SMTP默认的登陆用户名

mail.stmp.from

String

默认的邮件发送源地址

mail.stmp.socketFactory.class

String

socket工厂类类名,通过设置该属性可以覆盖提供者默认的实现,必须实现javax.net.SocketFactory接口

mail.stmp.socketFactory.port

int

指定socket工厂类所用的端口号,如果没有规定,则使用默认的端口号

mail.smtp.socketFactory.fallback

boolean

设置为true时,当使用指定的socket类创建socket失败后,将使用java.net.Socket创建socket,默认为true

mail.stmp.timeout

int

I/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 and Store),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          Get the default Session object.

static Session

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

static Session

getInstance(Properties          Get a new Session object.

static Session

getInstance(Properties props,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)



Address类:地址。一旦你创建了Session和Message,并将内容填入消息后,就可以用Address确定信件地址了。和Message一样,Address也是一个抽象类,常用InternetAddress类实例。



    若创建的地址只包含电子邮件地址,只要传递电子邮件地址到构造器就行了。         Address address = new InternetAddress("president@whitehouse.gov");     若希望名字紧挨着电子邮件显示,也可以把它传递给构造器:         Address address = new InternetAddress("president@whitehouse.gov", "George Bush");



    下面来看下Message中设置邮件信息的一些方法。

发件人

abstract  void

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

abstract  void

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

 现在大多数SMTP服务器要求发件人与连接账户必须一致,否则会抛出验证失败的异常,这样是防止用户伪装成其它人的账户恶意发送邮件。

    如果需要消息显示多个 from 地址,可以使用 addFrom() 方法:

                 Address address[] = ...;

                message.addFrom(address);

收件人/抄送人/暗送人

void

setRecipient(Message.RecipientType type,Address          Set the recipient address.

abstract  void

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.

    设置收件人收到邮件后的回复地址。

标题

abstract  void

setSubject(String          Set the subject of this message.

    设置邮件标题/主题。

内容

 void

setContent(Multipart          This method sets the given Multipart object as this message's content.

 void

setContent(Object obj,String          A convenience method for setting this part's content.

 void

setText(String          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

我们知道提供者在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 a Store object that implements this user's desired Store protocol.

Store

getStore(Provider          Get an instance of the store specified by Provider.

Store

getStore(String          Get a Store object that implements the specified protocol.

Store

getStore(URLName          Get a Store object for the given URLName.

Transport

getTransport()          Get a Transport object that implements this user's desired Transport protcol.

Transport

getTransport(Address          Get a Transport object that can transport a Message of the specified address type.

Transport

getTransport(Provider          Get an instance of the transport specified in the Provider.

Transport

getTransport(String          Get a Transport object that implements the specified protocol.

Transport

getTransport(URLName          Get a Transport 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 static void 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);
	}

}





java使用icmp请求 imap java_java使用icmp请求

转载于:https://blog.51cto.com/psnx168/1439787