我在本地开发机器和一台AWS Linux机器上遇到这个问题,UTF-8字符串被正确编码,但在另一台机器上它们被问号取代。这两个字符串起源于MIME电子邮件,并且都起源于一个共同的代码路径。正确编码和问号之间的差异既出现在stderr中,也出现在我们上传到AWS S3上的文件中。我在本地运行IntelliJ和,使用部署到损坏的Linux机器上的完全相同的jar。
所有机器上的Java版本都是一样的:
java版本"1.7.0_04"Java(TM) SE运行环境(build 1.7.0_04-b20)Java HotSpot(TM) 64位Server VM (build 23.0-b21, mixed mode)
我使用以下程序来验证默认字符集在任何地方都是相同的:
public class Test {
public static void main(String[] args) {
System.err.println(java.nio.charset.Charset.defaultCharset());
}
}
所有的方框都显示
utf - 8
我们将所有MIME字符串以字节形式保存在内存中,然后通过以下代码返回更高级别的代码作为UTF-8编码的字符串:
static final Charset charset = Charset.forName("UTF8");
// ...
return new String(bytes, ImapClient.charset);
然后通过InputStream mimeStream = IOUtils.toInputStream(mime)
转化为InputStream
,通过org.apache.james.mime4j.stream.MimeTokenStream
解析。
当我们到达主题字段时,也就是无法正确编码的字段,我们使用
public static String decodeBodyText(String str) {
try {
return MimeUtility.decodeText(str);
}
catch (UnsupportedEncodingException exc) {
// ignore
}
return str;
}
MimeUtility
来自javax.mail.internet
包。
这是在System.err.println
呼叫中以不同的方式显示的主题。
是什么导致了这种不正确的编码?
缺少-Dmail.mime.charset=utf-8
。由于某些原因,不同机器的默认值不同,但这个修复了它。