javax.mail 使用“[”字符解析电子邮件地址 header 时出错

javax.mail error when parsing email address header with '[' character

我正在尝试消化通过 gmail 帐户收到的一些邮件,而我收到的一封或多封邮件在 header 中有发件人的格式化名称。类似于

[hris [hristerson <chrisDoesNotExist@gmail.com>

上面的名称是假的,但说明了我遇到的情况,该名称将一个或多个 'C' 个字符替换为“[”。

触发错误的代码

String header = "[hris [hristerson <chrisDoesNotExist@gmail.com>";
boolean strict = true; // I also tried using a false value
InternetAddress.parse(header, strict);

错误本身表现为:javax.mail.internet.AddressException: Missing ']'

我所做的一些研究让我认为根据 RFC-2047 使用 encoded-words 可能是一个答案。但是除非我尝试不正确,否则它似乎没有用。此外,根据我的测试,其他类似的非法字符不会给我同样的错误,这让我认为这是偶然的,更独特的是 java 库问题。

我用来尝试基本 encoded-word 修复的代码是:

public String encodePrettyEmailHeader(String header, String charset, char encoding) {

    Map<String, String> illegalChars = new HashMap<>();

    illegalChars.put("\[", "=5B");
    illegalChars.put("]", "=5D");
    illegalChars.put("\(", "=28");
    illegalChars.put("\);", "=29");
    illegalChars.put("<", "=3C");
    illegalChars.put(">", "=3E");
    illegalChars.put("@", "=40");
    illegalChars.put(",", "=2C");
    illegalChars.put(";", "=3B");
    illegalChars.put(":", "=3A");
    illegalChars.put("\"", "=22");
    illegalChars.put("/", "=2F");
    illegalChars.put("\?", "=3F");
    illegalChars.put(" ", "=20");

    String email = getEmailFromHeader(header).trim(); // regex to get the <email@address.com> from the header
    String name = header.substring(0, header.indexOf(email)).trim();

    for (Map.Entry<String, String> anEntry : illegalChars.entrySet()) {
        name = name.replaceAll(anEntry.getKey(), anEntry.getValue());
    }

    return String.format("=?%s?%c?%s?= %s", charset, encoding, name, email);
}    

这样称呼它:InternetAddress.parse(encodePrettyEmailHeader(header, "UTF-8", 'Q'), strict);

我希望有一个不涉及手动将数据编码为 quoted-printable 的答案,我相信我应该能够使这个 janky 解决方案起作用,但是,这会增加更多开销因为我需要 un-encode 它才能有用地显示数据。

有人对我有什么建议可以继续吗?

编辑:

我升级了我的版本,结果也是一样的。但是,我意识到当我混淆地址 header 时,我添加了一组额外的引号,超出了来自 gmail 的引号。为简洁起见:

这是我错误格式化的方式: "[hris [hristerson" <chrisDoesNotExist@gmail.com>

这是对我来说失败的正确格式: [hris [hristerson <chrisDoesNotExist@gmail.com>

编辑 2:

为清楚起见,我使用的是 group: 'com.sun.mail', name: 'javax.mail', version: '1.5.5',并且我已经升级到 group: 'com.sun.mail', name: 'javax.mail', version: '1.6.0',但行为没有任何差异。

我也尝试过将 strict 设置为 false,但抛出的异常没有什么不同。

我有两个解决方案给你。

1) 使用构造函数:

InternetAddress workingStyle2 = new InternetAddress("chrisDoesNotExist@gmail.com", "[hris [hristerson","UTF-8");
System.out.println(workingStyle2.getPersonal());
System.out.println(workingStyle2.getAddress());

2) 使用 strict 模式 = false。注意不同的 API 当你使用严格模式时,调用 parseHeader 而不是仅仅解析。

To better support the range of "invalid" addresses seen in real messages, this method enforces fewer syntax rules than the parse method when the strict flag is false and enforces more rules when the strict flag is true. If the strict flag is false and the parse is successful in separating out an email address or addresses, the syntax of the addresses themselves is not checked.

    boolean strict = false;
    InternetAddress[] working = InternetAddress.parseHeader(header, strict);
    System.out.println(working[0].getPersonal());
    System.out.println(working[0].getAddress());