【问题标题】:UTF-8 charset doesn't work with javax.mailUTF-8 字符集不适用于 javax.mail
【发布时间】:2013-02-09 05:49:06
【问题描述】:

我使用Java Mail API 发送电子邮件。我正在使用联系人公式来发送输入,该输入必须发送到特定的电子邮件。

虽然我是丹麦人,但电子邮件发送没有问题,因此我需要三个丹麦字符,即主题和电子邮件文本中的“æ”、“ø”和“å”。

因此,我看到我可以使用 UTF-8 字符编码来提供这些字符,但是当我发送邮件时,我只看到一些奇怪的字母 - 'ã¦'、'ã¸' 和 'ã¥' -而不是丹麦字母 - 'æ'、'ø' 和 'å'。

我发送电子邮件的方法如下所示:

public void sendEmail(String name, String fromEmail, String subject, String message) throws AddressException, MessagingException, UnsupportedEncodingException, SendFailedException
{
    //Set Mail properties
    Properties props = System.getProperties();
    props.setProperty("mail.smtp.starttls.enable", "true");
    props.setProperty("mail.smtp.host", "smtp.gmail.com");
    props.setProperty("mail.smtp.socketFactory.port", "465");
    props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    props.setProperty("mail.smtp.auth", "true");
    props.setProperty("mail.smtp.port", "465");
    Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication("my_username", "my_password");
        }
    });

    //Create the email with variable input
    MimeMessage mimeMessage = new MimeMessage(session);
    mimeMessage.setHeader("Content-Type", "text/plain; charset=UTF-8");
    mimeMessage.setFrom(new InternetAddress(fromEmail, name));
    mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("my_email"));
    mimeMessage.setSubject(subject, "utf-8");
    mimeMessage.setContent(message, "text/plain");

    //Send the email
    Transport.send(mimeMessage);
}

请帮助我了解如何纠正这个“错误”。

【问题讨论】:

  • setText(message, "UTF"),因此必须为主题和内容设置编码。
  • 我这样做了,但没有用。虽然我在发送电子邮件时收到错误,但按照您的建议仅写入 UTF 作为编码时。

标签: java utf-8 character-encoding jakarta-mail


【解决方案1】:

对于所有电子邮件

有几个system properties related to mailing,可能可以简化您的代码。我实际上是在谈论这个特定的属性:"mail.mime.charset"

mail.mime.charset 系统属性可用于指定默认 MIME 字符集,以用于未指定字符集的编码单词和文本部分。通常,默认 MIME 字符集派生自默认 Java 字符集,如 file.encoding 系统属性中指定的那样。大多数应用程序无需显式设置默认 MIME 字符集。如果用于邮件消息的默认 MIME 字符集与用于存储在系统上的文件的字符集不同,则应设置此属性。

正如您在上面看到的,默认情况下mail.mime.charset 没有值,并且使用文件编码(file.encoding 属性)。

对于特定的电子邮件

但是,如果您想为特定的电子邮件指定特定的编码,那么您可能应该使用setSubject(subject,charset)setText(text,charset) 两个参数方法。

如果这不起作用,那么您的输入可能在达到这一点之前已经损坏。换句话说,您可能使用了错误的编码来收集数据

Mime 类型很复杂

setContent(content, "UTF-8")(正如其他消息来源所声称的)将无法正常工作。看看这个方法的签名:setContent(Object content, String mimetype)Mime 类型和字符集是两种完全不同的东西。 恕我直言,您真的应该使用带有字符集参数的 setText(...) 方法之一。

但如果你坚持使用 mimetype 来设置字符集setContent(content,mimetype),那么请使用正确的格式。 (不仅仅是"UTF-8",还有"text/plain; charset=UTF-8"之类的东西)。但更重要的是,请注意,每种 mime 类型都有自己处理字符集的方式。

  • 正如RFC-2046 中指定的那样,text/plain 的默认字符集是US-ASCII,但可以使用附加的字符集参数来否决。
  • 但是,在RFC-6657 中明确指出text/xml 类型使用消息的内容来确定字符集。 这里将忽略字符集参数。
  • RFC-2854 中声明text/html 应该始终指定一个字符集。但如果你不这样做,那么它将使用ISO-8859-1 (=Latin-1)。

【讨论】:

  • 很好的解释。当我遇到这个问题时,我改变了这个:message.setContent(body, "text/html");对此:message.setContent(body, "text/html;charset=utf-8");
  • 您好,这是否意味着 javax 邮件会在发送邮件之前对该字符集中的内容(字符串)进行编码?在邮件客户端,如果我们以不同的编码读取邮件,它不会正确显示,不是吗?
  • @ĐỗCôngBằng mimetype 将在电子邮件的标题中一起发送。然后,接收客户端首先从标头中提取 mimetype。这告诉客户端如何解析消息。但正如我在回答中提到的,虽然可以在 mime-type 中指定编码,但在某些情况下,它实际上会通过一些更复杂的规则来最终确定编码。一旦它知道编码,它就能够解析完整的消息。所有这些都是您的邮件客户端的责任。
  • @bvdb 我同意邮件客户端使用标头中指定的字符集。但是,标头中的字符集是否也是 Java 邮件在发送前用于对内容进行编码的字符集?当我使用setContent(text, "text/html"); 时,我在 OUTLOOK 上有电子邮件,其内容以 ISO-8859-1 编码,但其标题显示为 text/html;字符集=UTF-8。它导致 OUTLOOK 使用 UTF-8 来解码邮件,但它是用 ISO-8859-1 编码的,所以我有奇怪的字符。在com.sun.mail.handlers.text_plain.getCharset(String) 中,如果未指定字符集,则使用 us-ascii (ISO-8859-1) 在发送前对邮件进行编码。
【解决方案2】:

也许你也应该在这里提供 UTF-8

mimeMessage.setContent(message, "text/plain; charset=UTF-8");

你要看看http://www.coderanch.com/t/274480/java/java/JavaMail-set-content-utf

【讨论】:

  • 对不起,我从您的链接中尝试了很多东西,包括您自己的“解决方案”,但它似乎不起作用:(
【解决方案3】:

花了很多时间调试,并在互联网上搜索线索后,我找到了解决问题的方法。

似乎每当我通过网络请求发送数据时,我的应用程序都没有使用 UTF-8 编码对字符进行编码。这意味着从我的联系表单发送的包含 æ、ø 和 å 字符的数据无法通过字符编码正确处理。

解决方案似乎在我的部署描述符中设置了一个字符编码过滤器,它将所有来自网络的传入请求编码为字符编码 UTF-8。

private void registerCharacterEncodingFilter(ServletContext servletContext) {
    CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
    encodingFilter.setEncoding("UTF-8");
    encodingFilter.setForceEncoding(true);
    FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("characterEncodingFilter", encodingFilter);
    characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
}

此过滤器将编码设置为 UTF-8,并强制对来自 url ' /* ' 的所有请求进行编码。

【讨论】:

    【解决方案4】:

    这很简单, 使用参数 -Dfile.encoding=UTF-8 运行您的项目 前任: java -Dfile.encoding=UTF-8 -jar MyProject.jar

    //修正错别字

    【讨论】:

    • @Rohwedder,您的过滤器可能会解决您的特定问题。但这不是您最初问题的答案。您的问题是关于发送电子邮件,而不是关于处理网络请求。
    • 请修正您的错字:-Dfile.ecoding=UTF-8 -> -Dfile.encoding=UTF-8
    【解决方案5】:

    在将您的字符串发送到发送方法之前,您必须将字符串转换为 UTF-8

    如果你收到一个“请求”参数,你可以使用“setCharacterEncoding”:

    request.setCharacterEncoding("utf-8");
    String subject = request.getParameter("subject");
    String content = request.getParameter("content");
    ...
    MimeMessage mineMessage = new MimeMessage(session);
            mineMessage.setFrom(new InternetAddress(myAccountEmail));
            mineMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recepient));
            mineMessage.setSubject(subject, "UTF-8");
            mineMessage.setContent(content, "text/plain;charset=UTF-8");
    

    否则,请使用以下方法将您的字符串转换为 UTF-8 格式:

    String subject = new String(subject.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8"));
    String content = new String(content.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8"));
    ...
    MimeMessage mineMessage = new MimeMessage(session);
        mineMessage.setFrom(new InternetAddress(myAccountEmail));
        mineMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recepient));
        mineMessage.setSubject(subject, "UTF-8");
        mineMessage.setContent(content, "plain/plain;charset=UTF-8");
    

    This is the result in Spanish.

    【讨论】:

      【解决方案6】:

      我知道我这个问题迟到了,但我刚才遇到了类似的问题。

      检查您的源编码可能也是值得的!我正在使用一个测试类,其中包含一些特殊字符的硬编码主题/文本,在发送电子邮件时不断出现乱码。即使我在适用的地方设置了字符集 UTF-8 (mimeMessage.setSubject(subject, charset), mimeMessage.setContent(content, "text/plain; charset=UTF-8"))。

      然后我注意到这个类的源编码是windows-1252。据我了解,编译 java 文件时,任何源文本都会转换为 UTF-8。但是在这种情况下,在这个项目的 maven pom.xml 中,缺少 project.build.sourceEncoding 属性 - 所以我实际上不确定在编译期间(默认情况下)使用哪个编码 maven,因为没有指定。

      在这里无法更改源编码,但只要我将特殊字符更改为 Unicode 代码文字(例如“ü”到“\u00fc”),整个事情就可以正常工作了。

      【讨论】:

        【解决方案7】:
        mimeMessage.setContent(mail.getBody(), "text/html; charset=UTF-8");
        

        也许我错了,但这对我有用。 :) 任何 ööö、äää、üüü 字符都会在我的 Outlook 中正确显示。

        outlook screenshot

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多