最近在做一个邮件相关的项目,网上找资料时发现,关于发送邮件的资料倒是很多,收取邮件的就很少了。写下个人开发经验,供别人参考吧。
代码的demo下载,别忘了给我一个star~
也可以当成工具包使用,在pom文件中添加
jitpack.io
https://jitpack.io
com.github.zeemood
mail-plus
1.0.3
1. 开发准备
两个邮箱帐号:一个网易的,一个微软的,个人邮箱即可。例如163,hotmail。网易的邮箱主要是用来测试POP3和IMAP4的,hotmail则是用来测试Exchange的。网易邮箱需要在账户设置开通POP3和IMAP4的功能,开通方法如下:
网易使用IMAP的时候,还需要额外开通一次,不然没办法收件,收取邮件会被阻止,提示NO Select Unsafe Login. Please contact kefu@188.com for help。
开通方法是用http://config.mail.163.com/settings/imap/index.jsp?uid=xxxxxx@163.com
把上面链接的uid替换成自己的网易邮箱即可。
2.邮件收取的基本流程创建邮箱服务器的连接 >> 列举邮箱的文件夹 >> 匹对需要同步的邮件(根据邮件UID进行匹配)>> 解析邮件
根据这个流程,可以抽取成一个接口类IMailService。在抽取之前我们先来了解一下,拉取邮件需要一些什么参数。
- 收取邮件需要使用到的依赖
由于我们需要收取的是POP3、IMAP4和Exchange三种不同协议的邮件,会使用到两种不同的邮箱依赖,java mail和Exchange的java依赖,解析邮件的时候额外还需要使用到apache多个依赖和Emoji表情处理的依赖。主要的依赖如下:
com.microsoft.ews-java-api
ews-java-api
2.0
org.apache.commons
commons-email
1.5
com.vdurmont
emoji-java
4.0.0
com.sun.mail
javax.mail
1.6.2
compile
com.alibaba
fastjson
1.2.47
- 邮箱服务需要的基本参数
无疑 帐号,密码 是必须的。需要提醒一下的是IMAP、POP3的密码是自己设置的,和登录密码一点关系都没有。当然也有其他邮箱服务商开通IMAP和POP3的时候,直接把你登录密码作为协议密码的,如新浪和21cn的邮箱。而Exchange是一个特例,直接就是使用登录密码,也不需要做什么配置。
然后是服务器地址和端口,这个是IMAP和POP3需要的参数,Exchange有提供自动填入服务器地址和端口的函数。
我们把它抽取成一个配置类MailConnCfg,代码如下:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MailConnCfg {
private String email;
private String password;
private String host;
private Integer port;
private boolean ssl;
private ProxyTypeEnum proxyType;
private String proxyHost;
private Integer proxyPort;
private String proxyUsername;
private String proxyPassword;
private String socksProxyHost;
private Integer socksProxyPort;
public MailConnCfg(String email, String password, String host, Integer port) {
this.email = email;
this.password = password;
this.host = host;
this.port = port;
}
}
其中的代理配置类型枚举类代码ProxyTypeEnum如下所示
@Getter
@AllArgsConstructor
public enum ProxyTypeEnum {
SOCKS, HTTP;
}
- 邮箱服务器连接实体类
因为同时使用了java-mail和微软的ews的依赖,所以创建出来的网络连接实体类并不是一脉相承的父子类,对两个依赖的网络连接实体类进行一下包装(当然,你有更好的方法也可以使用,我能想到的就是用泛型,还有下面这种,我觉得对我的项目方便一点)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MailConn {
private POP3Store pop3Store;
private IMAPStore imapStore;
private ExchangeService exchangeService;
}
- 通用的邮件列表项
每个装有邮件文件夹打开后,都有邮件(废话),但是三种协议的邮件列表项都不一样。打个比方说,IMAPMessage的uid(邮件唯一标识)是纯数字,只针对那个账户和文件夹唯一。而POP3Message的uid则是字符串,不同的帐号邮件id也是唯一的。Exchange就更不用说了,ews和java-mail的封装肯定不一样。但是他们都能被转换成EML文件。所以我们创建一个通用的邮件列表项,来保证接口类。代码如下:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class MailItem {
private IMAPMessage imapMessage;
private POP3Message pop3Message;
private EmailMessage exchangeMessage;
}
- 通用邮件解析载体
解析后的邮件数据可以用一个自定义的类来承载,代码如下
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UniversalMail {
private String uid;
private String fromer;
private String receiver;
private String bcc;
private String cc;
private String folder;
private Boolean hasRead;
private Boolean hasAttachment;
private Date sendDate;
private String title;
private String emlPath;
private String content;
private String email;
private List attachments;
}
@Data
@AllArgsConstructor
@Builder
@NoArgsConstructor
public class UniversalAttachment {
private String path;
private String cid;
private String name;
private String contentType;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UniversalRecipient {
private String name;
private String email;
}
- 邮件服务接口类
IMailService的代码如下所示:
public interface IMailService {
UniversalMail parseEmail(MailItem mailItem, String localSavePath) throws MailPlusException;
List listAll(MailConn mailConn, List existUids) throws MailPlusException;
MailConn createConn(MailConnCfg mailConnCfg, boolean proxy) throws MailPlusException;
}
- 自定义的异常
主要是为了统一 一下抛出的邮件异常类型,方便开发,实际显示的异常信息还是原来的信息
@NoArgsConstructor
public class MailPlusException extends Exception {
private static final long serialVersionUID = -8014572218613182580L;
public MailPlusException(String message) {
super(message);
}
}
下一篇讲下接口三个实现类。
特别提示:对于上面的@Data之类的注解是使用了Lombok依赖,用来生成getter/setter方法。Builder生成Builder方法,不懂可以找下lombok方面的资料



