JavaMail学习笔记

原创 2006年06月14日 17:45:00
JavaMail的基本概念:
定义
1.         JavaMail是J2EE平台的一部分,是一个抽象的类组,使基于消息的系统得以实现。
       The JavaMail API provides a platform-independent and protocol-independent framework to build mail and messaging applications.
功能
2.         JavaMail对于电子邮件领域所起的作用就类似于JDBC对于数据库领域所起的作用,只是将请求传递到后台服务器,而本身不做处理。
3.         Create a mail message consisting of a collection of header attributes and a block of data of some known data type as specified in the Content-Type header field.
4.         Create a Session object, which authenticates the user, and controls access to the message store and transport.
5.         Send the message to its recipient list.
6.         Retrieve a message from a message type.
7.         Execute a high-level command on a retrieved message. High-level commands like view and print are intended to be implemented via JAF-Aware JavaBeans.
8.        
下载安装
9.         JavaMail下载地址:http://java.sun.com/products/javamail,最新的版本是1.4(包含在J2EE5中,已经开源,源代码下载地址如下:),符合JSR919规范,附带了SMTP、IMAP、POP3的实现。JavaMail API附带了许多不同的JAR文件,可供我们自定义安装或发布系统,最简单的实现就是使用mail.jar,其中包含着整个API和全部三个协议的实现,也可以选择使用mailapi.jar, smtp.jar, pop3jar, imap.jar中的一个或多个,这几个jar包中的内容都包含在mail.jar中。在使用JavaMail之前还需要下载JAF框架即activation.jar并将其放入类路径中,JavaMail推荐使用JAF1.1。JAF下载地址:http://java.sun.com/beans/glasgow/jaf.html
       JavaMail参考网站:https://glassfish.dev.java.net/javaee5/mail/
     相关协议
10.     JavaMail用到的核心协议包括:SMTP、POP3、IMAP、MIME等。
11.     SMTP(Simple Mail Transport Protocol):用于向邮件服务器发送邮件消息的协议,只是一个发送代理。
       SMTP协议原始文档地址:http://www.rfc-editor.org/rfc/rfc821.txt
 
12.     POP3(Post Office Protocol version 3):用于从邮件服务器收集邮件消息的协议,像是实际邮件中的一个邮箱,用户可以通过它收集、下载电子邮件并存储在本地机器上。
       POP3协议原始文档地址:http://www.rfc-editor.org/rfc/rfc1939.txt
 
13.     IMAP(Internet Message Access Protocol):提供了更丰富的功能集,包括收集、发送、搜索电子邮件等。为用户提供了一个可以与之交互的文件夹结构,并且所有的消息都存储在服务器上,不需要下载到用户本地计算机中。POP3中用户负责存储电子邮件而IMAP由服务器负责存储邮件。
       IMAP协议原始文档地址:http://www.rfc-editor.org/rfc/rfc2060.txt
       IMAP参考网站:http://www.imap.org/
 
14.     MIME(Multipurpose Internet Mail Extensions):用于处理将二进制文件编码成ASCII文件和将ASCII文件解码成二进制文件,MIME定义了这种翻译机制以及关于传送的全部规则。
       MIME协议原始文档地址:http://www.oac.uci.edu/indiv/ehood/MIME/MIME.html
       IMAP参考网站:http://www.oac.uci.edu/indiv/ehood/MIME/MIME.html
       相关RFC协议原始文档地址:http://www.rfc-editor.org/rfc/rfc2045.txt
       http://www.rfc-editor.org/rfc/rfc2046.txt
       http://www.rfc-editor.org/rfc/rfc2047.txt
15.     RFC822(Standard for the Format of Internet Text Messages): describes the structure of messages exchanged across the Internet.
       RFC822协议原始文档地址:http://www.rfc-editor.org/rfc/rfc822.txt
16.      
架构
17.     JavaMail架构图如下:
       Mail-enabled Application: client of JavaMail, use the JavaMail API to implement JavaMail Appcation.
       JavaMail API: The Abstract Layer declares classes, interfaces and abstract methods intended to support mail handling functions that all mail systems support. The internet implementation layer implements part of the abstract layer using internet standards-RFC822 and MIME.
       IMAP/POP3/NNTP implementation Layer: protocol implementation layer
JavaMail API:
18.     JavaMail共包括四个主要领域:会话管理、消息管理、邮件存储和检索、传送
会话管理
19.     JavaMail 会话管理API主要包括:javax.mail.Session、javax.mail.Authenticator
20.     javax.mail.Session:定义了用于与远程邮件服务器通信的邮件会话。在JavaMail上下文环境中,会话仅仅用于存储与服务器建立连接会话相关的逻辑信息,因此对于使用相同服务器的用户可以共享会话,这一点与Servlet环境中的会话的概念是不同的。Session本身不处理任何授权操作,但可以存储登录信息。通过调用静态方法获得一个Session实例,如下:static Session getInstance(Properties prop)或者static Session getDefaultInstance(Properties prop)。两个方法的区别在于getDefaultInstance会返回与以前调用相同的Session实例即每次返回的实例都是相同的,而getInstance每次返回一个新的Session实例,这里使用了Singleton设计模式。
21.     javax.mail.Authenticator:用于在得到Session时传递相关的验证信息。这是一个抽象类,需要继承并实现getPasswordAuthenticator()方法。调用方式如下:Session.getInstance(props,new SimpleAuthenticator());
22.     The Session class also acts as a factory for Store and Transport objects that implement specific access and transport protocols. A mail Session object manages the configuration options and user authentication information used to interact with messaging systems.
消息管理
23.     一条邮件消息主要有头部和内容两个部分组成,头部主要包括MessageID, From, To, Subject, Data, Content-Type, Reply-To等描述信息。其中Reply-To可以实现从一个地址发出但是回复给其他人的功能。内容采用的递归树结构,其中可以包含MultiPart或者数据块,Multipart由一个或多个BodyPart组成,而BodyPart可以包含MultiPart或者数据块,这就形成了一个递归树结构。JavaMail使用MIME实现了这种结构,采用了Composite设计模式。
24.     javax.mail.Message:用于封装一条邮件消息。这是一个抽象类,需要继承并实现。JavaMail API中包含一个实现javax.mail.internet.MimeMessage(实现了RFC822和MIME标准),它有多个构造函数,最常使用的是public MimeMessage(Session session),其中Session就是生成的javax.mail.Session实例。其中Message的public Message reply(boolean replyToAll)方法主要用于回复邮件时使用,可以使用必要的头部设置直接生成一个新的Message。
25.     javax.mail.Part:用于把一组复杂的消息组合在一起的类的接口。当Part实现类在处理内容时,所有的操作都通过JAF中的javax.activation.DataHandler类执行,可以将Part类看作是提供了一些快捷方法。Part的实现采用了Strategy设计模式。
       Part content is carried in a DataHandler object, that carries either data or a Multipart object.
       To add content to a Message, a client creates content, instantiates a DataHandler object, places content into that DataHandler object, and places that object into a Message object that has had its attributes defined. The Message class provides two techniques that set message content: setDataHandler() & setContent().
       The content is available through the Part can be either an InputStream or an object in the Java. When an InputStream is returned, any mail-specific encodings are decoded before the stream is returned. When an Object is returned, the type of the returned object depends upon the content itself.
26.     javax.mail.Multipart:一个占位符类以便可以包含多个BodyPart。A multipart message is a Message object where the content-type specifier has been set to multipart.
27.     javax.mail.BodyPart:用于在MultiPart内容列表中指出构成整个内容块的各个数据块。The BodyPart class is an abstract class that implements the Part interface in order to define the attribute and content body definitions that Part declares. A BodyPart object is intended to be inserted into a Multipart container, later accessed via a multipart message. A BodyPart contains either a new Multipart container object, or a DataHandler object.
28.    
29.    
30.    
31.    
邮件存储和检索
32.     Messages are contained in Folders. New messages are usually delivered to folders by a transport protocol or a delivery agent. Clients retrieve message from folders using an access protocol.
33.     邮件消息被组织成文件夹的形式,而这些文件存储在一个目录中,所以邮件消息是以目录结构的形式被存储的。我们在访问文件夹之前必须先获得一个与Session关联的javax.mail.Store对象实例。通过Store对象实例检索对其文件夹的引用,Store对象必须至少提供一个文件夹。
34.     javax.mail.Store:为文件夹层次结构提供了访问方法,并且在基层协议需要的时候,对连接进行验证。
35.     javax.mail.Folder:为了实施消息的存储和管理,支持列表、检索、复制、移动、删除等操作。默认状态为关闭,改变内容的操作之前必须调用open()打开,操作之后使用close()关闭,可以通过isOpen()检查是否已经打开。可以调用expunge()方法清除消息。
       Message objects can be retrieved from a Folder object. Message stored within a Folder object are sequentially numbered, starting at one. An assigned message number can change when the folder is expunged, since the expunge operation removes deleted messages from the folder and also renumbers the remaining messages.
36.     javax.mail.FetchProfile:支持高级消息提取,只提取给定的数据。
37.     javax.mail.search.SearchTerm:帮助建立复杂的搜索表达式。
38.     javax.mail.URLName:封装了访问邮件服务给定资源的所需的全部信息,如下:<protocol>://<username>:<password>@<server>[:<port>][/<foldername>]
39.     The Expunge Process is a two-phase operation. Setting the DELETED flag on messages marks them as deleted, but it does not remove them from the Folder. The deleted messages are removed only when the client invokes the expunge method on that Folder object. Folder object also renumbers the messages falling after the expunged messages in the message list. Thus, when the expunge method returns, the sequence number of those Message objects will change. Note, however, that the expunged messages still retain their original sequence numbers. The set of recommendations for clients wanting to expunge a Folder is: Expunge the folder; close it; and then reopen and refetch messages from that Folder. Multithreaded clients that expect to handle shared folders are advised not to use sequence numbers. If a client receives a MessageEvent indicating message removal, it should check the removed flag.
传送
40.     javax.mail.Transport:负责发送邮件消息。最简单是通过静态方法send(msg)发送消息。可以通过获得与Session关联的Transport对象实例,手工连接然后发送消息。
41.     传送相关的类调用顺序:Session.getTransport()调用得到javamail.default.providers文件中设置的com.sun.mail.smtp.SMTPTransport对象的实例transport。然后调用transport.connect()->transport.protocolConnect()->transport.openServer()->SocketFetcher.getSocket,最终得到Socket实例并存放在transport实例中。最后调用transport.sendMessage()通过Socket发送Message.
Event Model
42.     JavaMail Event Model使用了Observer设计模式。
43.     Javax.mail.event.MailEvent:All events are subclassed from the MailEvent class. During a session, A JavaMail component generates a specific event-type to notify objects registered as listeners for that event-type.
44.     JavaMail sends the following events to interested listeners:
       ConnectionEvent: Generated when a connection is successfully made to the Store, or when an existing connection is terminated or disconnected.
       StoreEvent: Communicates alerts and notification messages from the Store to the end user.
       FolderEvent: Communicate changes to any folder contained within the store.
       MessageCountEvent: This event notifies listeners that the message count has changed.
       MessageChangeEvent: models Message change events.
       TransportEvent: models transport events
45.     each event has its corresponding listeners, some may be have adapters which implement listener.
其它
46.     javax.mail.Flags:管理着所有的状态标记,包括系统和用户定义的状态。主要包括Flags.Flag.ANSWERED, DELETED, DRAFT, FLAGGED, RECENT, SEEN, USER几种状态,这些状态的支持完全由服务提供者决定。可以使用public Flags getPermanentFlags()判断提供者支持那些标记。可以使用Message.isSet(Flag)等方法检查和设置标记。
47.     javax.mailAddress:表示电子邮件地址信息。另外JavaMail附带了两个实现:javax.mail.internet.InternetAddress和javax.mail.internet.NewsAddress。
48.     The Provider Registry allows providers to register their protocol implementations to be used by JavaMail APIs. Each Javamail.x resource file is searched in the following order: java.home/lib/javamail.X, META-INF/javamail.X, META-INF/javamail.default.X. The javamail.default.providers file specifys the stores and transports that are available on the system, allowing an application to “discover” what store and transport implementations are available. The javamail.default.address.map file map transport address types to the transport protocol. 可以在代码中动态的修改默认的Providers,使用Session.setProvider(Provider provider);
49.     com.sun.mail.handlers.*:includes JAF-Aware JavaBeans of sun, these are the implementation classes of DataContentHandler.
50.     com.sun.mail.smtp.*:
51.     com.sun.mail.pop3.*:
52.     com.sun.mail.imap.*:
附录:源代码:
发送邮件:
package com.sample.mail;
import java.util.Date;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Provider;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Provider.Type;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
public class SendSMTP {
 public static void main(String[] args) {
  try {
   // 1 get a session instance
   // 1.1 create the instance of Properties and set values to it
   Properties props = new Properties();
   props.put("mail.transport.protocol", "smtp");
   props.put("mail.smtp.auth", "true");
   props.put("mail.smtp.host", "10.6.168.229");
   props.put("mail.smtp.port", "25");
   // 1.2 get the same instance as before and output it's id.
   // We can see that the session instance id is always same
   Session mailSession = Session.getDefaultInstance(props);
   // You also can use Authenticator to supply information of connect validation
   // Session mailSession=Session.getInstance(props,new SimpleAuthenticator());
   System.out.println("mailSession:" + mailSession);
   // 1.3 set the debug mode of session, used only for debug
   mailSession.setDebug(true);
   // 1.4 find out which implementations are available
   // Provider[] providers=mailSession.getProviders();
   // set the defaults based on altered provider
   // Provider provider=new Provider(Type.TRANSPORT,"smtp","com.sun.mail.smtp.SMTPTransport","Sun Microsystems","1.0");
   // mailSession.setProvider(provider);
   // 2 creat a message
   // 2.1 new a MimeMessage with the created session
   Message msg = new MimeMessage(mailSession);
   // 2.2 set the headers of this message
   msg.setSubject("this is a subject");
   msg.setFrom(new InternetAddress("tddmaster@travelsky.com"));
   msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("sgjiang@travelsky.com"));
   msg.setSentDate(new Date());
   // msg.setReplyTo(InternetAddress.parse("jiang_shuguo@hotmail.com"));
   // 2.3 set the content of this message.
   // there are two kinds of modes which set message's content:
   // set content which only includes text and set multipart content which includes binarystream and text bothly
   String msgBody = "Hello from my first e-mail with JavaMail";
   // 2.3 Mode 1 singlePart
   // msg.setText(msgBody);
   // System.out.println(msg.getContent());
   // the function of below clauses equals the above clauses,but it use original DataHandler to handler the datas; //
   // msg.setDataHandler(new DataHandler(msgBody, "text/plain"));
   // DataHandler dh0 = msg.getDataHandler();
   // if (dh0.getContentType().equals("text/plain")) {
   // System.out.println((String) dh0.getContent());
   // }
   // 2.3 Mode 2 MultiPart
   Multipart mp = new MimeMultipart();
   // create the first bodypart and add it to multipart
   MimeBodyPart mbpText = new MimeBodyPart();
   mbpText.setText(msgBody);
   mp.addBodyPart(mbpText);
   // create the secand bodypart and add it to multipart
   FileDataSource fds = new FileDataSource("c://shock_ferret.jpg");
   MimeBodyPart mbpFile = new MimeBodyPart();
   mbpFile.setDataHandler(new DataHandler(fds));
   mbpFile.setFileName(fds.getName());
   mp.addBodyPart(mbpFile);
   // set the multipart as the content of the message
   msg.setContent(mp);
   // 2.4 Save any changes made to this message into the message-store when the containing folder is closed, if the message is contained in a
   // folder.
   // (Some implementations may save the changes immediately.)
   // Update any header fields to be consistent with the changed message contents, and ensure that the client writes appropriate message headers.
   // If any part of a message's headers or contents are changed, saveChanges must be called to ensure that those changes are permanent.
   // If saveChanges is not called, any such modifications may or may not be saved, depending on the message store and folder implementation.
   // Messages obtained from folders opened READ_ONLY should not be modified and saveChanges should not be called on such messages.
   // Note that teh JavaMail API calls the saveChanges method implicitly during the send process, so invoking
   // it is unnecessary and expensive if the message is to be sent immediately.
   msg.saveChanges();
   // 3 send message use transport
   // 3.1 get transport instance from session
   Transport transport = mailSession.getTransport("smtp");
   // 3.2 connect to the server use the transport
   transport.connect("10.6.168.229", "lihaijun", "765717");
   // 3.3 send message to recipients
   transport.sendMessage(msg, msg.getAllRecipients());
   // 3.4 close the transport instance and connect
   transport.close();
   System.out.println("send successfully");
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}
接受邮件:
package com.sample.mail;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.mail.FetchProfile;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.search.FromStringTerm;
import javax.mail.search.OrTerm;
import javax.mail.search.SearchTerm;
public class GetPOP3 {
 public static void main(String[] args) {
  try {
   // 1 get a session instance
   Properties props = new Properties();
   props.put("mail.transport.protocol", "pop");
   Session mailSession = Session.getDefaultInstance(props);
   System.out.println("mailSession:" + mailSession);
   mailSession.setDebug(true);
   // 2 get a store instance from session
   // there are two modes to get store
   // 2 Mode 1
   // URLName urlname=new URLName("pop3://lihaijun:765717@10.6.168.229:110");
   // Store store=mailSession.getStore(urlname);
   // 2 Mode 2
   Store store = mailSession.getStore();
   store.connect("10.6.168.229", 110, "lihaijun", "765717");
   // 3 manipulate the folders
   // 3.1 get inbox folder instance from store
   Folder inbox = store.getDefaultFolder();
   // the below clause equals to the above clause
   // Folder inbox=store.getFolder("INBOX");
   // 3.2 list the subfolders of the inbox folder and output the folders' name
   Folder[] listOfInbox = null;
   // check if the folder can be list
   if ((inbox.getType() == Folder.HOLDS_FOLDERS)) {
    // You can use wildcard to set the condition of list
    listOfInbox = inbox.list("*");
    for (int i = 0; i < listOfInbox.length; i++) {
     System.out.println("FolderName=" + listOfInbox[i].getName());
    }
   }
   // 3.3 search some messages from inbox folder
   // open the inbox folder
   inbox.open(Folder.READ_ONLY);
   Message[] allMsgs = inbox.getMessages();
   SearchTerm st = new OrTerm(new FromStringTerm("tdpmaster@travelsky.com"), new FromStringTerm("sgjiang@travelsky.com"));
   Message[] someMsgs = inbox.search(st);
   for (int i = 0; i < allMsgs.length; i++) {
    // print subject of each message
    System.out.println("ID:" + i + " Subject:" + allMsgs[i].getSubject());
    // print content of each message
    printParts(allMsgs[i]);
   }
   // 3.4 fetch some fields of messsages use fetchprofile
   FetchProfile fProfile = new FetchProfile();
   // fProfile.add("To");
   // fProfile.add("From");
   // fProfile.add("Subject");
   fProfile.add(FetchProfile.Item.ENVELOPE);
   inbox.fetch(allMsgs, fProfile);
   // close the inbox folder
   inbox.close(false);
   // 4 close the store
   store.close();
  } catch (NoSuchProviderException e) {
   e.printStackTrace();
  } catch (MessagingException e) {
   e.printStackTrace();
  }
 }
 public static void printParts(Part p) {
  try {
   Object o = p.getContent();
   if (o instanceof String) {
    System.out.println("This is a String ");
    System.out.println((String) o);
   } else if (o instanceof Multipart) {
    System.out.println("This is a Multipart");
    Multipart mp = (Multipart) o;
    int count = mp.getCount();
    for (int i = 0; i < count; i++) {
     printParts(mp.getBodyPart(i));
    }
   } else if (o instanceof InputStream) {
    System.out.println("This is just an input stream");
    InputStream is = (InputStream) o;
    int c;
    while ((c = is.read()) != -1)
     System.out.write(c);
   }
  } catch (IOException e) {
   e.printStackTrace();
  } catch (MessagingException e) {
   e.printStackTrace();
  }
 }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

JavaMail学习笔记(四)、使用POP3协议接收并解析电子邮件

[java] package org.yangxin.study.jm; import java.io.BufferedInputStream; import java.io.Buffered...

JavaMail学习笔记(六)搜索邮件

JavaMail在javax.mail.search包中定义了一个用于创建搜索条件的SearchTerm类,应用程序创建SearchTerm类的实例对象后,就可以调用Folder.Search(Sea...

JavaMail学习笔记(三)、使用SMTP协议发送电子邮件(全)

package org.yangxin.study.jm; import java.io.File; import java.io.FileInputStream; import java.io.F...

JavaMail学习笔记(七)帐号激活与忘记密码 实例

一、帐户激活           在很多时候,在某些网站注册一个用户之后,网站会给这个用户注册时填写的email地址发送一封帐户激活邮件,这封邮件的内容就是一个激活帐户的链接和一段简短的文字...

JavaMail学习笔记(六)、搜索邮件

JavaMail在javax.mail.search包中定义了一个用于创建搜索条件的SearchTerm类,应用程序创建SearchTerm类的实例对象后,就可以调用Folder.Search(Sea...

JavaMail学习笔记

package cn.itcast.javamail2; import java.util.Properties; import javax.mail.Address; import j...

JavaMail学习笔记(三)、使用SMTP协议发送电子邮件

[java] package org.yangxin.study.jm; import java.io.File; import java.io.FileInputStream; impor...

JavaMail学习笔记(三)使用SMTP协议发送电子邮件

[java] view plaincopyprint? package org.yangxin.study.jm;    import java.io.File;  import ...

JavaMail学习笔记(五)使用IMAP协议接收并解析电子邮件

[java] view plaincopyprint? package org.yangxin.study.jm;    import java.io.BufferedReader; ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)