本文是一个简单的收取邮件的例子。
主要功能是:从服务器收取邮件,然后对邮件进行解析,解析出邮件的发件人、主题、内容、附件等。
使用的类库:JavaMail1.4.7,Apache的commons email1.3.1,另外还有javamail需要依赖jar包:activation.jar
实现过程如下:
1、定义一个简单的邮件收取类,作用连接邮件服务器,然后收取inbox里的邮件,返回Message[]
01 | package com.athena.mail.receiver; |
03 | import java.util.Properties; |
05 | import javax.mail.Authenticator; |
06 | import javax.mail.Folder; |
07 | import javax.mail.Message; |
08 | import javax.mail.MessagingException; |
09 | import javax.mail.NoSuchProviderException; |
10 | import javax.mail.Session; |
11 | import javax.mail.Store; |
19 | public class SimpleMailReceiver { |
26 | * @param authenticator |
28 | * @return Message数组(邮件数组) |
30 | public static Message[] fetchInbox(Properties props, Authenticator authenticator) { |
31 | return fetchInbox(props, authenticator, null ); |
39 | * @param authenticator |
42 | * 使用的收取邮件协议,有两个值"pop3"或者"imap" |
43 | * @return Message数组(邮件数组) |
45 | public static Message[] fetchInbox(Properties props, Authenticator authenticator, String protocol) { |
46 | Message[] messages = null ; |
47 | Session session = Session.getDefaultInstance(props, authenticator); |
52 | store = protocol == null || protocol.trim().length() == 0 ? session.getStore() : session.getStore(protocol); |
54 | folder = store.getFolder( "INBOX" ); |
55 | folder.open(Folder.READ_ONLY); |
56 | messages = folder.getMessages(); |
57 | } catch (NoSuchProviderException e) { |
59 | } catch (MessagingException e) { |
2、定义一个邮件解析类,用来解析上面返回的Message[]
01 | package com.athena.mail.receiver; |
03 | import java.io.BufferedInputStream; |
04 | import java.io.BufferedOutputStream; |
06 | import java.io.FileOutputStream; |
07 | import java.util.List; |
09 | import javax.activation.DataSource; |
10 | import javax.mail.Address; |
11 | import javax.mail.Folder; |
12 | import javax.mail.Message; |
13 | import javax.mail.MessagingException; |
14 | import javax.mail.Store; |
15 | import javax.mail.internet.MimeMessage; |
17 | import org.apache.commons.mail.util.MimeMessageParser; |
25 | public class MessageParser { |
29 | private static final String folder = "D:\\upload" ; |
31 | private static void parse(Message message) { |
33 | MimeMessageParser parser = new MimeMessageParser((MimeMessage) message).parse(); |
34 | String from = parser.getFrom(); |
35 | List<Address> cc = parser.getCc(); |
36 | List<Address> to = parser.getTo(); |
37 | String replyTo = parser.getReplyTo(); |
38 | String subject = parser.getSubject(); |
39 | String htmlContent = parser.getHtmlContent(); |
40 | String plainContent = parser.getPlainContent(); |
42 | System.out.println(subject); |
44 | List<DataSource> attachments = parser.getAttachmentList(); |
45 | for (DataSource ds : attachments) { |
46 | BufferedOutputStream outStream = null ; |
47 | BufferedInputStream ins = null ; |
49 | String fileName = folder + File.separator + ds.getName(); |
50 | outStream = new BufferedOutputStream( new FileOutputStream(fileName)); |
51 | ins = new BufferedInputStream(ds.getInputStream()); |
52 | byte [] data = new byte [ 2048 ]; |
54 | while ((length = ins.read(data)) != - 1 ) { |
55 | outStream.write(data, 0 , length); |
58 | System.out.println( "附件:" + fileName); |
63 | if (outStream != null ) { |
68 | } catch (Exception e) { |
73 | public static void parse(Message... messages) { |
74 | if (messages == null || messages.length == 0 ) { |
75 | System.out.println( "没有任何邮件" ); |
77 | for (Message m : messages) { |
81 | if (messages[ 0 ] != null ) { |
82 | Folder folder = messages[ 0 ].getFolder(); |
85 | Store store = folder.getStore(); |
90 | } catch (MessagingException e) { |
3、可以看到我在第1步的SimpleMailReceiver的方法fetchInbox方法的参数,其中一个是Properties,一个是Authenticator,做个邮件开发的都知道,这里不做解释。
为了方便用户使用,我为多个邮件服务器的一些基本信息进行了封装,如下:
01 | package com.athena.mail.props; |
03 | import java.util.Properties; |
06 | * 服务器种类:提供了网易和腾讯的企业邮箱(这两种已经测试通过),和谷歌(测试未通过) 后期有需要可以扩展 |
10 | public enum HostType { |
14 | public Properties getProperties() { |
15 | Properties defaults = new Properties(); |
16 | defaults.put( "mail.pop3.host" , "pop.163.com" ); |
17 | defaults.put( "mail.imap.host" , "imap.163.com" ); |
18 | defaults.put( "mail.store.protocol" , "pop3" ); |
25 | public Properties getProperties() { |
26 | Properties defaults = new Properties(); |
27 | defaults.put( "mail.pop3.host" , "pop.exmail.qq.com" ); |
28 | defaults.put( "mail.imap.host" , "imap.exmail.qq.com" ); |
29 | defaults.put( "mail.store.protocol" , "pop3" ); |
36 | public Properties getProperties() { |
37 | Properties defaults = new Properties(); |
38 | defaults.put( "mail.pop3.host" , "pop.gmail.com" ); |
39 | defaults.put( "mail.pop3.port" , "995" ); |
40 | defaults.put( "mail.imap.host" , "imap.gmail.com" ); |
41 | defaults.put( "mail.imap.port" , "465" ); |
42 | defaults.put( "mail.store.protocol" , "pop3" ); |
48 | public abstract Properties getProperties(); |
上面类的主要作用是方便用户使用,由于不同邮件服务器使用的地址以及参数都有所不同,而这些信息不会经常变化,所以就无需让用户操作了,用户使用的时候只需要获取她需要的服务器对象即可。
4、对Authenticator也进行了简单封装
01 | package com.athena.mail.props; |
03 | import javax.mail.Authenticator; |
04 | import javax.mail.PasswordAuthentication; |
12 | public final class AuthenticatorGenerator { |
15 | * 根据用户名和密码,生成Authenticator |
21 | public static Authenticator getAuthenticator( final String userName, final String password) { |
22 | return new Authenticator() { |
24 | protected PasswordAuthentication getPasswordAuthentication() { |
25 | return new PasswordAuthentication(userName, password); |
最后是一个简单的测试类:
01 | package com.athena.mail.client; |
03 | import com.athena.mail.props.AuthenticatorGenerator; |
04 | import com.athena.mail.props.HostType; |
05 | import com.athena.mail.receiver.MessageParser; |
06 | import com.athena.mail.receiver.SimpleMailReceiver; |
14 | public class MailTest { |
16 | public static void main(String[] args) { |
17 | MessageParser.parse(SimpleMailReceiver.fetchInbox(HostType.NETEASE.getProperties(), |
18 | AuthenticatorGenerator.getAuthenticator( "youraccount" , "yourpassword" ))); |
后记:
本来对于Properties的封装我采用的继承Properties的方式,如下:
01 | package com.athena.mail.props; |
03 | import java.util.Properties; |
05 | public class NeteaseProperties extends Properties { |
07 | private static final long serialVersionUID = -6623862312603756003L; |
10 | defaults = new Properties(); |
11 | defaults.put( "mail.pop3.host" , "pop.163.com" ); |
12 | defaults.put( "mail.imap.host" , "imap.163.com" ); |
13 | defaults.put( "mail.store.protocol" , "pop3" ); |
1 | 即通过在子类中添加一个非静态初始化块(当然,在子类的构造函数中也可以),将Properties类的成员变量defaults进行实例化(Properties将put进去的值都放在defaults变量中)并赋给相应的值。但考虑到如果有很多邮箱的话,类的数量就增加了,而且这样的一种扩展方式也不是很好(原因我也不知道,就是感觉不太好),所以就该成了上面的枚举的方式 |