0

这让我困惑了好几个小时,而且似乎天生就不太可能,但请多多包涵;我相信我有证据。

我已将其简化为最小的测试用例(如下)。要测试代码,您需要使用EmailTest.java(如下),然后导入 SOAP 服务。为此,我使用了:

wsimport -d bin -s src -keep -extension 'http://www.webservicex.net/stockquote.asmx?wsdl'

为方便起见,我也把代码放在了github上所以你可以简单地克隆它并运行它;这wsimport已经执行了。

以下代码的作用如下:

  • 调用testMime(),它创建了一个quoted-printable部分,然后正确显示它(使用以 开头的序列转义的最高位设置字符=);
  • 调用stockQuoteTest,它只是获取一个新的 Web 服务入口点——它不需要实际调用 Web 服务;
  • 再次调用testMime(),它创建了一个quoted-printable部分,但显示不正确,没有转义字符;system.out.Println然后(可以预见地)将它们替换为?.

我使用了多个 SOAP 库,它们都做同样的事情——我选择了一个简单的演示来演示。实际上没有必要调用 SOAP 端点。getPort对(此处)的调用getStockQuoteSoap12似乎是问题所在。

到目前为止,我的调试已经确定我所知道的默认 Java 编码都没有改变,而且问题似乎是在第二次调用时,quoted-printable编码器永远不会被调用。这似乎是因为当它工作时part.dh.dataContentHandler被设置为某种类型ObjectDataContentHandler,而StringDataContentHandler当它不工作时被设置为类型。

关于这里发生了什么或如何解决它的任何想法?

我正在使用javax.mail1.5.2(最新的,但旧版本是相同的) - 和

$ java -version
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

这里是EmailTest.java

package emailtest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;

// use any SOAP service. This one was generated using
//   wsimport -d bin -s src -keep -extension http://www.webservicex.net/stockquote.asmx?wsdl
import net.webservicex.StockQuote;
import net.webservicex.StockQuoteSoap;

public class Emailtest {

    public static void stockQuoteTest() {
        StockQuote stockService = new StockQuote();
        StockQuoteSoap s = stockService.getStockQuoteSoap12();
        // We don't actually need to call SOAP to demonstrate the problem
        // System.out.println("quote is "+s.getQuote("GOOG"));
    }

    public static void testMime() throws MessagingException {
        String msg = "\u0287x\u01DD\u0287 u\u028Dop \u01DDp\u1D09sdn";

        MimeBodyPart messageBodyPart = new MimeBodyPart();
        messageBodyPart.setText("" + msg, "utf-8");
        messageBodyPart.setHeader("Content-Type", "text/plain; charset=\"utf-8\"");
        messageBodyPart.setHeader("Content-Transfer-Encoding", "quoted-printable");

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            messageBodyPart.writeTo(os);
            String aString = new String(os.toByteArray(),"UTF-8");
            System.out.println(aString);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("");
    }

    public static void main(String args[]) {
        try {
            System.out.println("Before call to SOAP:");
            testMime();

            stockQuoteTest();

            System.out.println("After call to SOAP:");
            testMime();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }
}

这是输出:

Before call to SOAP:
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable

=CA=87x=C7=9D=CA=87 u=CA=8Dop =C7=9Dp=E1=B4=89sdn

After call to SOAP:
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable

?x?? u?op ?p?sdn

哦,如果重要的话,编码文本是:

ʇxǝʇ uʍop ǝpᴉsdn

您可以看到quoted-printable使用普通字母创建的“颠倒”字母显示在哪里无法工作(第二次调用)。调查表明它根本没有做quoted-printable

更新

这似乎是jax-ws 中的一个错误,并且可以说是 javax.mail 中的一个错误,因为它依赖于text/plain恰好位于 JAF 而不是它自己的处理程序。任何解决方法的想法?(使用 Java 7,据称在 jax-ws 中修复的地方不是一个选项)

4

1 回答 1

1

我相信这是因为 JAX-WS 中的这个错误(据称已在 Java 7 中修复)。

JAX-WS 使用 JAF 来引入不尊重字符集的DataHandlerfor 类型(即。当 JAX-WS 类被加载时,使用 this 而不是.指定的编码。text/plaintext/plain; charset="utf-8"text/plainjavax.mail

两种可能的解决方法是:

  • 升级到 Java 7(专门针对 JAX-WS)

  • -Dfile.encoding=UTF-8在命令行启动应用程序以设置 Java 默认文件编码;显然这可能会产生其他后果

于 2015-01-10T17:39:23.907 回答