You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过EWS Java代码访问Outlook邮件时的字符引用解析错误问题

EWS Java API解析Outlook邮件字符引用错误解决方案

问题概述

使用Java通过EWS(Exchange Web Services)访问Outlook邮件时,部分邮件触发XML解析错误,错误信息:

ParseError at [row,col]:[852,6] Message: Character reference "&#

相关业务代码:

try { 
    ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2); 
    ExchangeCredentials credentials = new WebCredentials(EMAIL_ID, EMAIL_PWD); 
    service.setCredentials(credentials); 
    service.setUrl(new URI("https://*****************/ews/exchange.asmx")); 
    service.setTraceEnabled(true); 
    ExtendedPropertyDefinition PR_TRANSPORT_MESSAGE_HEADERS = new ExtendedPropertyDefinition(0x007D,MapiPropertyType.String); 
    PropertySet propset = new PropertySet(PropertySet.FirstClassProperties.getBasePropertySet(),ItemSchema.MimeContent,PR_TRANSPORT_MESSAGE_HEADERS); 
    propset.setRequestedBodyType(BodyType.Text);
    
    ItemView view = new ItemView(30);
    view.getOrderBy().add(ItemSchema.DateTimeReceived, SortDirection.Descending);
    FindItemsResults<Item> findResults;
    findResults = service.findItems(WellKnownFolderName.Inbox,"Body:"+currency, view);

    if (findResults.getTotalCount() == 0) {
        logger.info("INFO:: There is no emails available");
    }
    else {
        for (Item item : findResults) {
            EmailMessage message = EmailMessage.bind(service, item.getId(), new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.Attachments));
            EmailMessage message = EmailMessage.bind(service, item.getId(), propset);
            item.load();
            //emailBody = item.getBody().toString();
            emailBody = message.getBody().toString();
            logger.info("Email Body " + StringUtils.normalizeSpace(emailBody));
            Date dateTimeReceived = item.getDateTimeReceived();
            SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
            Date todays_date = new Date();
            resultList.add(emailBody);
        }
        item.delete(DeleteMode.MoveToDeletedItems);
    }
} catch (Exception e) {
    logger.info("Error in Executing outlookEmailRead : "+e.getMessage());
}

POM依赖:

<dependency>
    <groupId>com.microsoft.ews-java-api</groupId>
    <artifactId>ews-java-api</artifactId>
    <version>2.0</version>
</dependency>

该问题为EWS Java API已知问题,以下是可行的解决方案:

解决方案

1. 直接获取MimeContent自行解析邮件内容

绕过EWS API自带的XML解析,直接获取邮件的MIME内容,使用JavaMail等工具解析文本:

// 修改PropertySet,只请求MimeContent
PropertySet mimeProps = new PropertySet(ItemSchema.MimeContent);
EmailMessage message = EmailMessage.bind(service, item.getId(), mimeProps);

// 解析MIME内容
MimeContent mimeContent = message.getMimeContent();
ByteArrayInputStream inputStream = new ByteArrayInputStream(mimeContent.getContent());
MimeMessage mimeMsg = new MimeMessage(null, inputStream);

// 提取文本内容
String emailBody = "";
if (mimeMsg.isMimeType("text/plain")) {
    emailBody = mimeMsg.getContent().toString();
} else if (mimeMsg.isMimeType("multipart/*")) {
    Multipart multipart = (Multipart) mimeMsg.getContent();
    for (int i = 0; i < multipart.getCount(); i++) {
        BodyPart part = multipart.getBodyPart(i);
        if (part.isMimeType("text/plain")) {
            emailBody = part.getContent().toString();
            break;
        }
    }
}

2. 自定义XML解析器修复截断字符

通过自定义XML阅读器,在解析前修复不完整的字符引用(如截断的&amp;#):

// 继承EWS的XmlReader,重写解析逻辑
public class FixInvalidXmlReader extends EwsXmlReader {
    public FixInvalidXmlReader(InputStream inputStream) throws XmlException {
        super(fixInvalidCharacters(inputStream));
    }

    private static InputStream fixInvalidCharacters(InputStream inputStream) throws IOException {
        String xmlContent = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
        // 修复截断的字符引用,将不完整的实体替换为空或合法格式
        xmlContent = xmlContent.replaceAll("&amp;#(?![0-9a-fA-F]+;)", "");
        return new ByteArrayInputStream(xmlContent.getBytes(StandardCharsets.UTF_8));
    }
}

// 替换EWS服务的XmlReaderFactory
service.setXmlReaderFactory(new IXmlReaderFactory() {
    @Override
    public EwsXmlReader createXmlReader(InputStream inputStream) throws XmlException, IOException {
        return new FixInvalidXmlReader(inputStream);
    }
});

3. 切换到社区维护的EWS API分支

原官方项目已归档,可使用社区维护的分支版本,该分支可能已修复此问题,修改POM依赖:

<dependency>
    <groupId>com.github.sgroschupf</groupId>
    <artifactId>ews-java-api</artifactId>
    <version>2.0.1</version>
</dependency>

4. 容错处理:捕获ParseError后重试加载

在catch块中针对XML解析错误单独处理,尝试使用不同的PropertySet加载邮件:

catch (XmlException e) {
    if (e.getMessage().contains("Character reference")) {
        // 尝试仅加载基础属性,跳过Body解析
        PropertySet fallbackProps = new PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject, ItemSchema.DateTimeReceived);
        EmailMessage fallbackMsg = EmailMessage.bind(service, item.getId(), fallbackProps);
        logger.warn("邮件解析失败,仅加载基础信息:" + fallbackMsg.getSubject());
    }
}

内容的提问来源于stack exchange,提问作者Parthiban

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:20:39