原本业务使用javamail通过imap协议读取邮件,后来有个客户那边不支持imap协议,需要改为通过微软的ews(exchange web service)协议读取。结合网上已有的资料,自己测试了一把,以下是可以成功运行的代码
1.maven引入依赖
<dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.5.6</version> </dependency>
2.代码
import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.PropertySet;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.core.enumeration.property.BasePropertySet;
import microsoft.exchange.webservices.data.core.enumeration.property.BodyType;
import microsoft.exchange.webservices.data.core.enumeration.property.WellKnownFolderName;
import microsoft.exchange.webservices.data.core.enumeration.search.SortDirection;
import microsoft.exchange.webservices.data.core.enumeration.service.ConflictResolutionMode;
import microsoft.exchange.webservices.data.core.enumeration.service.DeleteMode;
import microsoft.exchange.webservices.data.core.service.folder.Folder;
import microsoft.exchange.webservices.data.core.service.item.EmailMessage;
import microsoft.exchange.webservices.data.core.service.item.Item;
import microsoft.exchange.webservices.data.core.service.schema.ItemSchema;
import microsoft.exchange.webservices.data.credential.ExchangeCredentials;
import microsoft.exchange.webservices.data.credential.WebCredentials;
import microsoft.exchange.webservices.data.property.complex.*;
import microsoft.exchange.webservices.data.search.FindItemsResults;
import microsoft.exchange.webservices.data.search.ItemView;
import microsoft.exchange.webservices.data.search.filter.SearchFilter;
import javax.mail.event.MailEvent;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
/**
* Exchange邮件服务工具类
*/
public class ExchangeMailUtil {
private String mailServer;//服务器地址
private String user; //用户名
private String password; //密码
private String domain; //域名
/**
* 不带域名的构造器
*/
public ExchangeMailUtil(String mailServer, String user, String password) {
this.mailServer = mailServer;
this.user = user;
this.password = password;
}
/**
* 带域名的构造器
*/
public ExchangeMailUtil(String mailServer, String user, String password, String domain) {
this.mailServer = mailServer;
this.user = user;
this.password = password;
this.domain = domain;
}
public static void main(String[] args) throws Exception {
// Outlook Web Access路径通常为/EWS/exchange.asmx
ExchangeMailUtil mailUtil = new ExchangeMailUtil("https://mail.xxxx.com/EWS/exchange.asmx",
"用户名", "密码");
// 接收邮件
ArrayList<EmailMessage> mails = mailUtil.receive(10);
for (EmailMessage mail : mails) {
// 处理附件
GetAttachmentsFromEmail(mail);
// 打印结果
System.out.println("邮件标题: " + mail.getSubject());
System.out.println("接收时间: " + mail.getDateTimeReceived());
System.out.println("发送人: " + mail.getFrom().getName() + ", 地址: " + mail.getFrom().getAddress());
System.out.println("邮件内容:" + mail.getBody());
System.out.println("附件:" + mail.getHasAttachments());
System.out.println("已读:" + mail.getIsRead());
// 更新已读
if (!mail.getIsRead()) {
mail.setIsRead(true);
mail.update(ConflictResolutionMode.AlwaysOverwrite);
}
}
// // 发送邮件
// String subject = "test";
// String[] to = {"xxxx@163.com"};
// //抄送人
// String[] cc = {};
// String bodyText = "我就是测试一下发邮件";
// //附件
// String[] attachmentPaths = new String[]{"C:\\test.TXT"};
// try {
// mailUtil.send(subject,to,cc,bodyText,attachmentPaths);
// System.out.println("发送成功!");
// } catch (Exception e) {
// e.printStackTrace();
// System.out.println("发送失败");
// }
}
/**
* 创建邮件服务
*
* @return 邮件服务
*/
private ExchangeService getExchangeService() {
// Exchange版本
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
//用户认证信息
ExchangeCredentials credentials;
if (domain == null) {
credentials = new WebCredentials(user, password);
} else {
credentials = new WebCredentials(user, password, domain);
}
service.setCredentials(credentials);
try {
// 连接服务器
service.setUrl(new URI(mailServer));
} catch (URISyntaxException e) {
e.printStackTrace();
}
return service;
}
/**
* 收取邮件
*
* @param max 最大收取邮件数
* @param searchFilter 收取邮件过滤规则
* @return
* @throws Exception
*/
public ArrayList<EmailMessage> receive(int max, SearchFilter searchFilter) throws Exception {
// 获取服务
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
ExchangeCredentials credentials = new WebCredentials(user, password);
service.setCredentials(credentials);
service.setUrl(new URI(mailServer));
//绑定收件箱,同样可以绑定发件箱
Folder inbox = Folder.bind(service, WellKnownFolderName.Inbox);
//获取读取邮件的数量
int count = inbox.getTotalCount();
if (max > 0) {
count = Math.min(count, max);
}
//设置获取的邮件数量、内容类型
PropertySet itempropertyset = new PropertySet(BasePropertySet.FirstClassProperties);
itempropertyset.setRequestedBodyType(BodyType.Text);
ItemView view = new ItemView(count);
// view.setPropertySet(itempropertyset);
//设置按照时间顺序收取
view.getOrderBy().add(ItemSchema.DateTimeReceived, SortDirection.Descending);
//查找邮件
FindItemsResults<Item> findResults;
if (searchFilter == null) {
findResults = service.findItems(inbox.getId(), view);
} else {
findResults = service.findItems(inbox.getId(), searchFilter, view);
}
//MOOOOOOST IMPORTANT: load messages' properties before
service.loadPropertiesForItems(findResults, PropertySet.FirstClassProperties);
ArrayList<EmailMessage> result = new ArrayList<EmailMessage>();
for (Item item : findResults.getItems()) {
// EmailMessage message = (EmailMessage) item;
EmailMessage message = EmailMessage.bind(service, item.getId(), itempropertyset);
result.add(message);
}
return result;
}
/**
* 收取指定数量的邮件
*
* @throws Exception
*/
public ArrayList<EmailMessage> receive(int max) throws Exception {
return receive(max, null);
}
/**
* 收取所有邮件
*
* @throws Exception
*/
public ArrayList<EmailMessage> receive() throws Exception {
return receive(0, null);
}
/**
* 发送带附件的mail
*
* @param subject 邮件标题
* @param to 收件人列表
* @param cc 抄送人列表
* @param bodyText 邮件内容
* @param attachmentPaths 附件地址列表
* @throws Exception
*/
public void send(String subject, String[] to, String[] cc, String bodyText, String[] attachmentPaths)
throws Exception {
// 获取服务
ExchangeService service = getExchangeService();
EmailMessage msg = new EmailMessage(service);
// 邮件标题
msg.setSubject(subject);
// 邮件内容和类型
MessageBody body = MessageBody.getMessageBodyFromText(bodyText);
// body.setBodyType(BodyType.HTML);
body.setBodyType(BodyType.Text);
msg.setBody(body);
// 收件人
for (String toPerson : to) {
msg.getToRecipients().add(toPerson);
}
// 抄送人
if (cc != null) {
for (String ccPerson : cc) {
msg.getCcRecipients().add(ccPerson);
}
}
// 附件
if (attachmentPaths != null) {
for (String attachmentPath : attachmentPaths) {
msg.getAttachments().addFileAttachment(attachmentPath);
}
}
msg.send();
}
/**
* 发送不带附件的mail
*
* @param subject 邮件标题
* @param to 收件人列表
* @param cc 抄送人列表
* @param bodyText 邮件内容
* @throws Exception
*/
public void send(String subject, String[] to, String[] cc, String bodyText) throws Exception {
send(subject, to, cc, bodyText, null);
}
/**
* 获取附件
* @param mail
* @throws Exception
*/
public static void GetAttachmentsFromEmail(EmailMessage mail) throws Exception {
List<Attachment> attachs = mail.getAttachments().getItems();
try {
// 判断是否有附件
if (mail.getHasAttachments()) {
// 迭代获取附件
for (Attachment attach : attachs) {
if (attach instanceof FileAttachment) {
//接收邮件到临时目录
System.out.println(attach.getName());
String dirPath = "C:\\temp\\";
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdir();
}
((FileAttachment) attach).load(dirPath + attach.getName());
} else // Attachment is an item attachment.
{
ItemAttachment itemAttachment = (ItemAttachment) attach;
// Load attachment into memory and write out the subject.
// This does not save the file like it does with a file attachment.
// This call results in a GetAttachment call to EWS.
itemAttachment.load();
System.out.println("Item attachment name: " + itemAttachment.getName());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.常见问题:
3.1 报401权限错误,一般是用户名或密码错误。
假设邮箱为:www.robin@xxx.com, 用户名则为:robin
3.2 测试URI路径是否错误
直接在浏览器输入uri:https://mail.xxxx.com/EWS/exchange.asmx
正确的话会出现用户名和密码登录页面,能成功登录则说明uri、用户名和密码都无误。