javamail 抛出 java.io.UnsupportedEncodingException: unknown-8bit

javamail throws java.io.UnsupportedEncodingException: unknown-8bit

我尝试使用 javamail lib 阅读一些电子邮件。当电子邮件包含 MIME header (Content-Type: text/plain; charset="unknown-8bit") 时,我收到此错误:java.io.UnsupportedEncodingException: unknown-8bit

知道为什么会这样吗?

因为 "unknown-8bit" 不是已知的字符集名称。 JavaMail FAQ 中对此进行了解释,并提供了处理此问题的备选方案。我在这里复制了答案,但请注意,这可能会过时。请务必搜索 JavaMail 常见问题解答以了解您可能遇到的任何其他 JavaMail 问题。

问:为什么在包含文本数据的正文部分调用 getContent() 时会出现 UnsupportedEncodingException?

A: 文本正文部分(即类型为 "text/plain"、"text/html" 或 "text/xml" 的正文部分)return使用 getContent() 时的 Unicode String 对象。通常,此类正文部分在内部将其文本数据保存在某些非 Unicode 字符集中。 JavaMail(通过相应的 DataContentHandler)尝试将该数据转换为 Unicode 字符串。底层 JDK 的字符集转换器用于执行此操作。如果 JDK 不支持特定的字符集,则会抛出 UnsupportedEncodingException。在这种情况下,您可以使用 getInputStream() 方法将内容检索为字节流。例如:

String s;
if (part.isMimeType("text/plain")) {
    try {
        s = part.getContent();
    } catch (UnsupportedEncodingException uex) {
        InputStream is = part.getInputStream();
        /*
         * Read the input stream into a byte array.
         * Choose a charset in some heuristic manner, use
         * that charset in the java.lang.String constructor
         * to convert the byte array into a String.
         */
         s = convert_to_string(is);
    } catch (Exception ex) {
        // Handle other exceptions appropriately
    }
}

JDK 尚不支持一些常用的字符集。您可以在位于 http://www.freeutils.net/source/jcharset/.

的 JCharset 包中找到对其中一些额外字符集的支持

您还可以为 JDK 已经支持的现有字符集添加别名,以便通过其他名称识别它。您可以为 "bad" 字符集名称创建一个字符集提供程序,它可以简单地重定向到现有的字符集提供程序;请参阅以下代码。创建一个适当的 CharsetProvider 子类并将其与 META-INF/services 文件一起包含,然后 JDK 将找到它。显然,您可以变得更加聪明,例如将所有未知字符集重定向到 "us-ascii"。

==> UnknownCharsetProvider.java <==
import java.nio.charset.*;
import java.nio.charset.spi.*;
import java.util.*;

public class UnknownCharsetProvider extends CharsetProvider {
     private static final String badCharset = "x-unknown";
     private static final String goodCharset = "iso-8859-1";

     public Charset charsetForName(String charset) {
         if (charset.equalsIgnoreCase(badCharset))
             return Charset.forName(goodCharset);
         return null;
     }

     public Iterator<Charset> charsets() {
         return Collections.emptyIterator();
     }
}

==> META-INF/services/java.nio.charset.spi.CharsetProvider <==
UnknownCharsetProvider