2015-01-10 8 views
-1

Это меня озадачило в течение многих часов, и кажется маловероятным, но, пожалуйста, несите меня; Я считаю, что у меня есть доказательства.Использование службы Java SOAP прерывает цитируемую почтовую инкапсуляцию javax.mail

Я упростил это до минимального тестового примера (ниже). Чтобы проверить код, вам нужно будет использовать EmailTest.java (ниже), а затем импортировать SOAP-сервис. Для этого я использовал:

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

Для удобства я также поставил код на GitHub here, так что вы можете просто клонировать и запустить его; это уже имеет wsimport.

Что ниже код делает это следующим образом:

  • звонков testMime(), что создает quoted-printable части, а затем отображает его правильно (с верхними битым набором символы отделались последовательности, начиная с =);
  • вызывает stockQuoteTest, который просто получает новую точку входа в веб-службу - на самом деле ее не нужно называть веб-службой;
  • снова вызывает testMime(), который создает часть quoted-printable, но отображает ее неправильно, не избегая символов; system.out.Println затем (предположительно) заменяет их ?.

Я использовал несколько SOAP-библиотек, все из которых делают то же самое - я выбрал простой демонстрационный пример для демонстрации. В действительности нет необходимости называть конечную точку SOAP. Похоже, что вызов getPort (здесь, в getStockQuoteSoap12).

До сих пор моя отладка определила, что ни один из кодировок по умолчанию, о которых я знаю, не изменился, и проблема заключается в том, что при втором вызове кодер quoted-printable никогда не вызывается. Это связано с тем, что part.dh.dataContentHandler получает какое-то значение ObjectDataContentHandler, когда он работает, и типа StringDataContentHandler, когда он не работает.

Любые идеи о том, что здесь происходит или как это исправить?

Я использую javax.mail 1.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.

Update

Это, казалось бы, a bug in jax-ws и, возможно, ошибка в javax.mail для полагаться на text/plain обработчик, который случается в ФСД, а самостоятельно. Любые идеи для работы? (использование Java 7, где, как утверждается, установлено в jax-ws, не является опцией)

+0

ОК, почему нижний предел без объяснения причин? Это полностью реплицируемая проблема с минимальным примером. – abligh

ответ

0

Я считаю, что это из-за this bug в JAX-WS (предположительно исправлено на Java 7).

JAX-WS использует JAF, чтобы ввести DataHandler для типа text/plain, который не уважает набор символов (т.е. text/plain; charset="utf-8". Когда класс JAX-WS загружается, это используется вместо text/plain обработчика в javax.mail. Затем это использует кодировка платформы Java по умолчанию, а не указана кодировка

Два возможных обходных являются:.

  • Обновление до Java 7 (специально для JAX-WS)

  • Запустите приложение с -Dfile.encoding=UTF-8 в командной строке, чтобы установить кодировку файла по умолчанию Java; очевидно, это может иметь и другие последствия