【问题标题】:Javamail problem with ñ characters in mail addresses邮件地址中带有ñ字符的Javamail问题
【发布时间】:2011-06-04 06:13:53
【问题描述】:

我在使用ñ 字符时遇到了解析方法问题:

essage.setRecipients(Message.RecipientType.TO, internetAddress.parse("somedir.withñchar@m ailserver.com",false));

我将 false 传递给严格参数,但我总是得到错误:

javax.mail.internet.AddressException: Local address contains control or whitespace in string ``somedir.with±har@mailserver.com''
at Mailer.main(Mailer.java:386)
Caused by: javax.mail.internet.AddressException: Local address contains control
or whitespace in string ``somedir.with±har@mailserver.com''
        at javax.mail.internet.InternetAddress.checkAddress(InternetAddress.java
:1155)
        at javax.mail.internet.InternetAddress.parse(InternetAddress.java:1044)
        at javax.mail.internet.InternetAddress.parse(InternetAddress.java:575)
        at Mailer.main(Mailer.java:377)

【问题讨论】:

    标签: java jakarta-mail


    【解决方案1】:

    创建一个新类,扩展它并覆盖验证功能。但是我不明白你为什么想要那个。

    public class invalidInternetAddress extends internetAddress {
    
      @Override
      private static void checkAddress() throws AddressException {
      }
    }
    

    【讨论】:

      【解决方案2】:

      验证您的 ñ 实际上是一个正代字号。以下内容非常适合我

      InternetAddress[] list = InternetAddress.parse("fred.joñes@example.com", false);
      for (InternetAddress a : list) {
          System.out.println("[" + a + "]");
      }
      

      在用 unicode 转义符替换 ñ 时也可以使用(在源 .java 文件中)

      InternetAddress[] list = InternetAddress.parse("fred.jo\u00F1es@example.com", false);
      

      您可以尝试像这样替换它作为测试。

      编辑:顺便说一句,我还使用了带有地址且没有第二个参数的 parse("..."),并通过 true 表示严格,这两种方法也都有效。

      【讨论】:

      • 我都试过了,但结果相同。您使用的是哪个版本的 javamail?
      • @user871611 这自 Java Mail 1.4.4 以来一直为我工作,并且仍在工作。在否决我之前,请确保您确实有一个 U+00F1 ñ Unicode "LATIN SMALL LETTER N WITH TILDE" 而不是 n U+006E "LATIN SMALL LETTER N" 后跟 U+0303 "COMBINING TILDE"
      • [...] 字符序列应该根据 unicode 规范化进行规范化。但这是应该的,所以有些事情在这里会起作用(可能会中断,但在接收端)。
      【解决方案3】:

      也许您的文本编辑器没有将您的源文件保存为 UTF8,而是保存为 ASCII,因此您的 nya 变得一团糟。确保将其保存为 UTF8。当保存为 UTF8 时,编译 .java 文件可能还需要一个编译选项。我有一段时间没有这样做了,但我记得是这样的。

      【讨论】:

        【解决方案4】:

        JavaMail 的地址解析器在这里告诉您一些非常重要的事情:您只能在电子邮件地址的@ 符号的左侧使用普通的可打印ASCII 字符。查看 RFC 5322 以获取 ABNF for valid email addresses

        addr-spec       =   local-part "@" domain
        
        local-part      =   dot-atom / quoted-string / obs-local-part
        
        dot-atom        =   [CFWS] dot-atom-text [CFWS]
        
        dot-atom-text   =   1*atext *("." 1*atext)
        
        atext           =   ALPHA / DIGIT /    ; Printable US-ASCII
                            "!" / "#" /        ;  characters not including
                            "$" / "%" /        ;  specials.  Used for atoms.
                            "&" / "'" /
                            "*" / "+" /
                            "-" / "/" /
                            "=" / "?" /
                            "^" / "_" /
                            "`" / "{" /
                            "|" / "}" /
                            "~"
        
        quoted-string   =   [CFWS]
                            DQUOTE *([FWS] qcontent) [FWS] DQUOTE
                            [CFWS]
        
        qcontent        =   qtext / quoted-pair
        
        quoted-pair     =   ("\" (VCHAR / WSP)) / obs-qp
        
        qtext           =   %d33 /             ; Printable US-ASCII
                            %d35-91 /          ;  characters not including
                            %d93-126 /         ;  "\" or the quote character
                            obs-qtext
        

        在继续之前,请确保地址正确。

        【讨论】:

        • 最新版本的 RFC 6532 不再适用,它允许使用 UTF-8 字符。
        【解决方案5】:

        如果您仍然遇到此问题,我建议您像我一样在您不寻常的电子邮件地址中添加双引号。它对我有用,因为 InternetAddress 的 checkAddress 方法放弃验证引用的地址。这是简单快捷的解决方案。

        示例:

        unusual_email_without_at_sign_or_with_accentuátion (won't work)
        "unusual_email_without_at_sign_or_with_accentuátion" (it works!)
        

        完美且正确的解决方案是 Java 团队修复 InternetAddress 类的错误,即使在构造函数中接收 "strict=false" 也会检查电子邮件语法,什么时候不应该。

        错误示例:

        InternetAddress i = new InternetAddress("unusual_email_without_at_sign_or_with_accentuátion ", false)
        

        变通解决方案示例:

        InternetAddress i = new InternetAddress("\"unusual_email_without_at_sign_or_with_accentuátion\"", false)
        

        创建扩展地址的新类的方法不起作用,因为 Transport.send() 出于某种原因似乎再次验证了地址并且也启动了异常。

        如果有帮助,请告诉我们!

        【讨论】:

        • 谢谢!这对我有用(我在发件人邮件的域中有'_')!
        【解决方案6】:

        要将电子邮件发送到包含不可打印字符(如 ñ)的地址,您必须使用 UTF-8 对电子邮件地址进行编码。

        原始RFC 5322 Internet Message Format 不允许使用重音字符。但此后,RFC 6532 (Internationalized Email Headers) 提供了一种在电子邮件地址中使用国际字符的方法。

        查看this StackOverflow question了解更多详情。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-26
          • 2010-10-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-14
          相关资源
          最近更新 更多