JavaMail读发邮件

来源:互联网 发布:印度超级联赛直播数据 编辑:程序博客网 时间:2024/06/08 09:34

http://log-cd.iteye.com/blog/421229


一、基本概念:

  SMTP(Simple Mail Transfer Protocol),即简单邮件传输协议,它定义了发送电子邮件的机制。在 JavaMail API 环境中,基于 JavaMail 的程序将和您的公司或因特网服务供应商的(Internet Service Provider's,ISP's)SMTP 服务器通信。SMTP 服务器可将消息中转至接收方 SMTP 服务器,以便最终让用户经由 POP 或 IMAP 获得。这不是要求 SMTP 服务器成为开放的中继,尽管 SMTP 服务器支持身份验证,不过还是得确保它的配置正确。像配置服务器来中继消息或添加删除邮件账号这类任务的实现,JavaMail API 中并不支持。

  POP(Post Office Protocol),即邮局协议。目前用的是版本3,所以人们通常将它称为 POP3,RFC 1939 定义了这个协议。POP 和SMTP一样,也是一种机制,Internet上大多数人通过它得到邮件。该协议规定每个用户只能有一个邮箱的支持。这就是它所能做的,而这也造成了许多混淆。使用 POP 时,用户熟悉的许多性能并不是由 POP 协议支持的,如查看有几封新邮件消息这一性能。这些性能内建于如 Eudora 或 Microsoft Outlook 之类的程序中,它们能记住一些事,诸如最近一次收到的邮件,还能计算出有多少是新的。所以当使用 JavaMail API 时,如果读者想要这类信息,就只能由自己来计算了。

  IMAP(Internet Message Access Protocol),即Internet消息访问协议,是更高级的用于接收消息的协议,在 RFC 2060 中有它的定义。目前使用的IMAP版本为4,人们习惯将它称为 IMAP4。在用到 IMAP 时,邮件服务器必需支持这个协议。不能仅仅把使用 POP 的程序用于 IMAP,并指望它支持 IMAP 所有性能。假设邮件服务器支持 IMAP,基于 JavaMail 的程序可以利用这种情况--用户在服务器上可以有多个文件夹(folder),并且这些文件夹可以被多个用户共享。
  因为有这一更高级的性能,您也许会认为所有用户都会使用 IMAP。事实并不是这样。要求服务器接收新消息,在用户请求时发送到用户手中,还要在每个用户的多个文件夹中维护消息。这样虽然能将消息集中备份,但随着用户长期的邮件夹越来越大,到磁盘空间耗尽时,每个用户都会受到损失。使用 POP,就能卸载邮件服务器上保存的消息了。

  MIME(Multipurpose Internet Mail Extensions),即多用途Internet邮件扩展标准。它不是邮件传输协议,而是对传输内容的消息、附件及其它的内容定义了格式。这里有很多不同的RFC(Requirement of Comment)文档:RFC 822、RFC 2045、RFC 2046 和 RFC 2047。作为一个 JavaMail API 的用户,您通常不必对这些格式操心。无论如何,一定存在这些格式而且程序会用到它。

二、例子

Java代码  收藏代码
  1. import java.io.File;  
  2. import java.io.FileOutputStream;  
  3. import java.io.InputStream;  
  4. import java.io.OutputStream;  
  5. import java.io.UnsupportedEncodingException;  
  6. import java.security.Security;  
  7. import java.util.Date;  
  8. import java.util.Enumeration;  
  9. import java.util.Properties;  
  10. import java.util.Vector;  
  11.   
  12. import javax.activation.DataHandler;  
  13. import javax.activation.FileDataSource;  
  14. import javax.mail.Authenticator;  
  15. import javax.mail.BodyPart;  
  16. import javax.mail.FetchProfile;  
  17. import javax.mail.Folder;  
  18. import javax.mail.Message;  
  19. import javax.mail.MessagingException;  
  20. import javax.mail.Multipart;  
  21. import javax.mail.Part;  
  22. import javax.mail.PasswordAuthentication;  
  23. import javax.mail.Session;  
  24. import javax.mail.Store;  
  25. import javax.mail.Transport;  
  26. import javax.mail.URLName;  
  27. import javax.mail.internet.AddressException;  
  28. import javax.mail.internet.InternetAddress;  
  29. import javax.mail.internet.MimeBodyPart;  
  30. import javax.mail.internet.MimeMessage;  
  31. import javax.mail.internet.MimeMultipart;  
  32. import javax.mail.internet.MimeUtility;  
  33.   
  34. /** 
  35.  * 使用Gmail发送邮件 
  36.  */  
  37. public class GmailSenderAndFetch {  
  38.   
  39.     private static String messageContentMimeType = "text/html; charset=gb2312";  
  40.   
  41.     private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";  
  42.   
  43.     public static Properties getProperties() {  
  44.         Properties props = System.getProperties();  
  45.         props.setProperty("mail.smtp.host""smtp.gmail.com");  
  46.         // Gmail提供的POP3和SMTP是使用安全套接字层SSL的  
  47.         props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);  
  48.         props.setProperty("mail.smtp.socketFactory.fallback""false");  
  49.         props.setProperty("mail.smtp.port""465");  
  50.         props.setProperty("mail.smtp.socketFactory.port""465");  
  51.   
  52.         props.setProperty("mail.imap.socketFactory.class", SSL_FACTORY);  
  53.         props.setProperty("mail.imap.socketFactory.fallback""false");  
  54.         props.setProperty("mail.imap.port""993");  
  55.         props.setProperty("mail.imap.socketFactory.port""993");  
  56.   
  57.         props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);  
  58.         props.setProperty("mail.pop3.socketFactory.fallback""false");  
  59.         props.setProperty("mail.pop3.port""995");  
  60.         props.setProperty("mail.pop3.socketFactory.port""995");  
  61.   
  62.         props.put("mail.smtp.auth""true");  
  63.         return props;  
  64.     }  
  65.   
  66.     /** 
  67.      * 构建邮件 
  68.      *  
  69.      * @param username 
  70.      * @param password 
  71.      * @param receiver 
  72.      * @return 
  73.      * @throws AddressException 
  74.      * @throws MessagingException 
  75.      */  
  76.     @SuppressWarnings( { "unchecked""serial" })  
  77.     public static Message buildMimeMessage(final String username,  
  78.             final String password, String receiver) throws AddressException,  
  79.             MessagingException {  
  80.         Session session = Session.getDefaultInstance(getProperties(),  
  81.                 new Authenticator() {  
  82.                     protected PasswordAuthentication getPasswordAuthentication() {  
  83.                         return new PasswordAuthentication(username, password);  
  84.                     }  
  85.                 });  
  86.   
  87.         Message msg = new MimeMessage(session);  
  88.           
  89.         //鉴别发送者,您可以使用setFrom()和setReplyTo()方法。  
  90.         //msg.setFrom(new InternetAddress("[发件人]"));  
  91.         msg.addFrom(InternetAddress.parse("[发件人]"));//地址来源,没作用?  
  92.         msg.setReplyTo(InternetAddress.parse("[回复时收件人]"));//回复时用的地址  
  93.         //消息接收者  
  94.         msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(  
  95.                 receiver, false));  
  96.         msg.setSubject("JavaMail邮件发送");  
  97.         msg.setSentDate(new Date());  
  98.   
  99.         String content = "How are you!这是一个测试!";  
  100.         // 邮件内容数据(Content)  
  101.         msg.setContent(buildMimeMultipart(content, new Vector() {  
  102.             {  
  103.                 add("D:/uploadDir/test.txt");  
  104.             }  
  105.         }));  
  106.   
  107.         return msg;  
  108.     }  
  109.   
  110.     /** 
  111.      * 构建邮件的正文和附件 
  112.      *  
  113.      * @param msgContent 
  114.      * @param attachedFileList 
  115.      * @return 
  116.      * @throws MessagingException 
  117.      */  
  118.     public static Multipart buildMimeMultipart(String msgContent,  
  119.             Vector attachedFileList) throws MessagingException {  
  120.         Multipart mPart = new MimeMultipart();// 多部分实现  
  121.   
  122.         // 邮件正文  
  123.         MimeBodyPart mBodyContent = new MimeBodyPart();// MIME邮件段体  
  124.         if (msgContent != null) {  
  125.             mBodyContent.setContent(msgContent, messageContentMimeType);  
  126.         } else {  
  127.             mBodyContent.setContent("", messageContentMimeType);  
  128.         }  
  129.         mPart.addBodyPart(mBodyContent);  
  130.   
  131.         // 附件  
  132.         String file;  
  133.         String fileName;  
  134.         if (attachedFileList != null) {  
  135.             for (Enumeration fileList = attachedFileList.elements(); fileList  
  136.                     .hasMoreElements();) {  
  137.                 file = (String) fileList.nextElement();  
  138.                 fileName = file.substring(file.lastIndexOf("/") + 1);  
  139.                 MimeBodyPart mBodyPart = new MimeBodyPart();  
  140.                 //远程资源  
  141.                 //URLDataSource uds=new URLDataSource(http://www.iteye.com/logo.gif);  
  142.                 FileDataSource fds = new FileDataSource(file);  
  143.                 mBodyPart.setDataHandler(new DataHandler(fds));  
  144.                 //mBodyPart.setFileName(fileName);  
  145.             mBodyPart.setFileName(javax.mail.internet.MimeUtility.encodeWord(fileName));//解决中文附件名问题  
  146.                 mPart.addBodyPart(mBodyPart);  
  147.             }  
  148.         }  
  149.   
  150.         return mPart;  
  151.     }  
  152.   
  153.     /** 
  154.      * 字串解码 
  155.      *  
  156.      * @param text 
  157.      * @return 
  158.      * @throws UnsupportedEncodingException 
  159.      */  
  160.     protected static String decodeText(String text)  
  161.             throws UnsupportedEncodingException {  
  162.         if (text == null)  
  163.             return null;  
  164.         if (text.startsWith("=?GB") || text.startsWith("=?gb")) {  
  165.             text = MimeUtility.decodeText(text);  
  166.         } else {  
  167.             text = new String(text.getBytes("ISO8859_1"));  
  168.         }  
  169.         return text;  
  170.     }  
  171.   
  172.     /** 
  173.      * 分析邮件 
  174.      *  
  175.      * @param mPart 
  176.      */  
  177.     public static void parseMailContent(Object content) {  
  178.         try {  
  179.             if (content instanceof Multipart) {  
  180.                 Multipart mPart = (MimeMultipart) content;  
  181.                 for (int i = 0; i < mPart.getCount(); i++) {  
  182.                     extractPart((MimeBodyPart) mPart.getBodyPart(i));  
  183.                 }  
  184.             }  
  185.         } catch (Exception e) {  
  186.             e.printStackTrace();  
  187.         }  
  188.     }  
  189.   
  190.     /** 
  191.      * 抽取内容 
  192.      *  
  193.      * @param part 
  194.      */  
  195.     public static void extractPart(MimeBodyPart part) {  
  196.         try {  
  197.             String disposition = part.getDisposition();  
  198.   
  199.             if (disposition != null  
  200.                     && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) {// 附件  
  201.                 String fileName = decodeText(part.getFileName());  
  202.                 System.out.println(fileName);  
  203.                 saveAttachFile(part);//保存附件  
  204.             } else {// 正文  
  205.                 if(part.getContent() instanceof String){//接收到的纯文本  
  206.                     System.out.println(part.getContent());  
  207.                 }  
  208.                 if(part.getContent() instanceof MimeMultipart){//接收的邮件有附件时  
  209.                     BodyPart bodyPart = ((MimeMultipart) part.getContent()).getBodyPart(0);  
  210.                     System.out.println(bodyPart.getContent());  
  211.                 }  
  212.             }  
  213.         } catch (Exception e) {  
  214.             e.printStackTrace();  
  215.         }  
  216.     }  
  217.   
  218.     /** 
  219.      * 保存附件 
  220.      * @param part 
  221.      */  
  222.     public static void saveAttachFile(Part part){  
  223.         try{  
  224.             if(part.getDisposition()==nullreturn;  
  225.   
  226.             String dir="D:/uploadDir/";  
  227.             String filename = decodeText(part.getFileName());  
  228.               
  229.             InputStream in=part.getInputStream();  
  230.             OutputStream out = new FileOutputStream(new File(dir+filename));  
  231.               
  232.             byte [] buffer=new byte[8192];  
  233.             while(in.read(buffer) != -1){  
  234.                 out.write(buffer);  
  235.             }  
  236.               
  237.             in.close();  
  238.             out.flush();  
  239.             out.close();  
  240.         }catch(Exception e){  
  241.             e.printStackTrace();  
  242.         }  
  243.     }  
  244.       
  245.     /** 
  246.      * 发送邮件 
  247.      *  
  248.      * @throws AddressException 
  249.      * @throws MessagingException 
  250.      */  
  251.     public static void sendMail() throws AddressException, MessagingException {  
  252.         Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());  
  253.         //Transport 是用来发送信息的  
  254.         Transport.send(buildMimeMessage("[用户名]""[邮箱密码]",  
  255.                 "[收件地址]"));  
  256.   
  257.         System.out.println("Message send...");  
  258.   
  259.     }  
  260.   
  261.     /** 
  262.      * 取邮件信息 
  263.      *  
  264.      * @throws Exception 
  265.      */  
  266.     public static void fetchMail() throws Exception {  
  267.         Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());  
  268.         Session session = Session.getDefaultInstance(getProperties(), null);  
  269.         //用pop3协议:new URLName("pop3", "pop.gmail.com", 995, null,"[邮箱帐号]", "[邮箱密码]");  
  270.         //用IMAP协议  
  271.         URLName urln = new URLName("imap""imap.gmail.com"995null,  
  272.                 "[邮箱帐号]""[邮箱密码]");  
  273.         Store store = null;  
  274.         Folder inbox = null;  
  275.         try {  
  276.             //Store用来收信,Store类实现特定邮件协议上的读、写、监视、查找等操作。  
  277.             store = session.getStore(urln);  
  278.             store.connect();  
  279.             inbox = store.getFolder("INBOX");//收件箱  
  280.             inbox.open(Folder.READ_ONLY);  
  281.             FetchProfile profile = new FetchProfile();  
  282.             profile.add(FetchProfile.Item.ENVELOPE);  
  283.             Message[] messages = inbox.getMessages();  
  284.             inbox.fetch(messages, profile);  
  285.             System.out.println("收件箱的邮件数:" + messages.length);  
  286.             System.out.println("未读邮件数:" + inbox.getUnreadMessageCount());  
  287.             System.out.println("新邮件数:" + inbox.getNewMessageCount());  
  288.   
  289.             for (int i = 0; i < messages.length; i++) {  
  290.                 // 邮件发送者  
  291.                 String from = decodeText(messages[i].getFrom()[0].toString());  
  292.                 InternetAddress ia = new InternetAddress(from);  
  293.                 System.out.println("FROM:" + ia.getPersonal() + '('  
  294.                         + ia.getAddress() + ')');  
  295.                 // 邮件标题  
  296.                 System.out.println("TITLE:" + messages[i].getSubject());  
  297.                 // 邮件内容  
  298.                 parseMailContent(messages[i].getContent());  
  299.   
  300.                 // 邮件大小  
  301.                 System.out.println("SIZE:" + messages[i].getSize());  
  302.                 // 邮件发送时间  
  303.                 System.out.println("DATE:" + messages[i].getSentDate());  
  304.             }  
  305.         } finally {  
  306.             try {  
  307.                 inbox.close(false);  
  308.             } catch (Exception e) {  
  309.             }  
  310.             try {  
  311.                 store.close();  
  312.             } catch (Exception e) {  
  313.             }  
  314.         }  
  315.     }  
  316.   


三、如何实现消息的删除
    消息的删除涉及到与消息相关的 Flags(标志)。不同 flag 表示不同的状态,有些标志由系统定义,而有些则由用户自己定义。下面列出在内部类 Flags.Flag 中预定义的标志:
  ·Flags.Flag.ANSWERED
  ·Flags.Flag.DELETED
  ·Flags.Flag.DRAFT
  ·Flags.Flag.FLAGGED
  ·Flags.Flag.RECENT
  ·Flags.Flag.SEEN
  ·Flags.Flag.USER
  上述这些标志只是标准定义,并不意味着所有邮件服务器或供应商都支持所有这些标志。例如,除了删除消息标志外,POP 协议不再支持其它任何标志。检查是否存在新邮件,这不是个 POP 任务,而是内建于邮件客户机的任务。为找出哪些标志能被支持,可以用 getPermanentFlags() 向 folder 提出请求。
  要删除消息,您可以设置消息的 DELETED flag:
  message.setFlag(Flags.Flag.DELETED, true);
  首先,请以 READ_WRITE 模式打开 folder:
  folder.open(Folder.READ_WRITE);
  然后,当所有消息的处理完成后,关闭 folder,并传递一个 true 值,从而擦除(expunge)有 delete 标志的消息。
  folder.close(true);
  一个 Folder 的 expunge() 方法可以用来删除消息。但 Sun 的 POP3 供应商不支持。其它供应商有的或许能够实现这一功能,而有的则不能。IMAP 供应商极有可能实现此功能。因为 POP 只支持单个对邮箱的访问,对 Sun 的供应商来说,您必需关闭 folder 以删除消息。
  要取消标志,只要传递 false 给 setFlag() 方法就行了。想知道是否设置过标志,可以用 isSet() 检查。

原创粉丝点击