发送电子邮件时主题编码出现问题

32

我正在发送一封电子邮件,我已经正确地接收到它,但是主题的编码不正确。我发送了“invitación”,但是我收到了“invitaci?n”。消息的内容是正确的。

消息的内容来自Velocity模板的转换,而主题在字符串变量中设置。

我已经搜索过并看到一些人说MimeUtility.encodeText()可以解决此问题,但我尝试使用它没有成功。

我该如何解决这个问题?这是我目前的代码。

String subject = "Invitación";
String msgBody = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, "/vmTemplates/template.vm", "UTF-8", model);

Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);

try {
    String encodingOptions = "text/html; charset=UTF-8";
    Message msg = new MimeMessage(session);
    msg.setHeader("Content-Type", encodingOptions);
    msg.setFrom(new javax.mail.internet.InternetAddress(emailFrom));
    msg.addRecipient(Message.RecipientType.TO, new InternetAddress(emailTo));

    msg.setSubject(subject);
    msg.setContent(msgBody, encodingOptions);
    Transport.send(msg);

    } catch (AddressException e) {
        ...
    } catch (MessagingException e) {
        ...
    } 
感谢。
5个回答

44

JavaMail 的抽象化可能有点过度,你在这里成为了受害者。当你使用

Message msg = new MimeMessage(session);

你正在创建一个MimeMessage对象,但是将其作为Message对象来处理。 Message仅有setSubject(String subject)方法,该方法使用平台默认字符集对主题进行编码。如果平台默认值无法对其进行编码,则在结果标头中会得到?字符。然而,MimeMessage具有setSubject(String subject,String charset)方法,可以允许您指定要用于编码主题的字符集。所以只需将您的代码切换到

MimeMessage msg = new MimeMessage(session);
msg.setHeader("Content-Type", encodingOptions);
msg.setFrom(new javax.mail.internet.InternetAddress(emailFrom));
msg.addRecipient(Message.RecipientType.TO, new InternetAddress(emailTo));

msg.setSubject(subject, "UTF-8");

而且它应该可以工作。


Message 的唯一已发布的子类是 MimeMessage。我怀疑是否有人实现了另一个子类。如果他们只合并了 javax.mailjavax.mail.internet,JavaMail 就会更好用 -- 那个额外的抽象层只意味着你不断地向子类转换。 - dkarp
这并没有解决我的问题(无法在主题行中发送£符号)。 - Mark W
1
@Mark:你尝试过 msg.setSubject("\u00a3", "UTF-8") 但它没有正确编码主题吗?那么结果的主题头部是什么? - dkarp
抱歉。我解决了我的问题,这与主题编码无关 - 它与读取用于填充主题的文件有关,因此在添加到消息之前,我的主题字符串是不正确的。 - Mark W
@dkarp:我一直以为拼写是“Groddy”... 我被纠正了 :) - mtyson
不知何故我看不到带有2个参数的签名。@edyluisrey的答案为我解决了问题。 - Schultz9999

8

你可以使用它,它可以正常工作。

msg.setSubject(MimeUtility.encodeText("string", "UTF-8", "Q"));

4
也许你可以尝试这样做:msg.setSubject(subject, "UTF8");。这将会设置邮件主题,并使用UTF-8编码。

1
javax.mail.Message 没有这个方法。我正在使用由AppEngine提供的Java Mail API。 - Javi
哦,抱歉!我没有注意到这与AppEngine有关! - ksimon
我一开始忘记了。后来我编辑了帖子并标记为AppEngine。无论如何还是谢谢。 - Javi

0

我在我的一个项目中实现了emailService,并且我正在使用MimeMessageHelper和MimeMailMessage。请参考以下代码。

private String sendEmail() {
  MimeMessage mimeMessage = EmailSenderFactory.INSTANCE.getEmailSender().createMimeMessage();
  MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
  mimeMessageHelper.setTo("YourToEmailId");
  mimeMessageHelper.setFrom("YourFromEmailId");
  mimeMessageHelper.setBcc("YourBccEmailId");
  mimeMessageHelper.setSubject("YourEmailSubject");
  mimeMessageHelper.setText("YourEmailContent", true);
  mimeMessageHelper.addAttachment("DocumentName", new ByteArrayDataSource("Document data in byte[]", "Document Content Type"));
  MimeMailMessage mimeMailMessage = new MimeMailMessage(mimeMessageHelper);
  return EmailSenderFactory.INSTANCE.getEmailSender().send(mimeMailMessage);
}

0
在我的情况下,唯一有效的方法是将系统区域设置更改为支持所需字符集的区域设置。在此之前,我尝试了许多不同的方法,包括这个线程中被接受的答案,但它们都没有起作用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接