2009-03-01 10 views
0

J'ai une question à propos de Java Mail et comment cela fonctionne avec les flux. Dans Java Mail 1.4.1, il existe un MimeMessage constructor that accepts a stream. Ma compréhension est que je pourrais passer un flux à ce constructeur et il l'analyserait pour moi dans un MimeMessage. J'ai écrit 2 tests pour le prouver. Le premier test envoie un flux contenant uniquement un message MIME partiel en plusieurs parties. Le second test envoie un flux contenant 2 messages MIME multi-parties complets. Ni travailler comme je l'espérais. Le premier ne lance pas d'exception et le second lit le flux entier dans un seul message en quelque sorte. Est-ce un bug dans Java Mail ou est-ce que j'utilise le mauvais type de flux? Ou est-ce que je manque quelque chose de plus gros?JavaMail Question ou Bug?

Il est un peu long, mais voici le code de test:

import java.io.BufferedInputStream; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Properties; 

import javax.activation.DataHandler; 
import javax.activation.DataSource; 
import javax.mail.BodyPart; 
import javax.mail.MessagingException; 
import javax.mail.Multipart; 
import javax.mail.Session; 
import javax.mail.internet.MimeBodyPart; 
import javax.mail.internet.MimeMessage; 
import javax.mail.internet.MimeMultipart; 
import javax.mail.util.ByteArrayDataSource; 

import junit.framework.TestCase; 


public class mimeTest extends TestCase { 

    public void testPartialMulitpartMessage() throws MessagingException, IOException 
    { 
     Properties props = new Properties(); 
     Session session = Session.getInstance(props, null); 
     String testMsg1 = "test"; 
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 

     // Step 1 - Create first MIME message 
     MimeMessage mesg = new MimeMessage(session); 
     Multipart mp = new MimeMultipart("mixed"); 
     //create a child part 
     BodyPart bodyPart = new MimeBodyPart(); 
     bodyPart.setContent(testMsg1, "application/x-special"); 
     bodyPart.setHeader("Content-Length", String.valueOf(testMsg1.length())); 
     DataSource ds = new ByteArrayDataSource(testMsg1, "application/x-special"); 
     bodyPart.setDataHandler(new DataHandler(ds)); 
     bodyPart.setHeader("Content-Transfer-Encoding", "8bit"); 
     // Add the child part to the multipart 
     mp.addBodyPart(bodyPart); 
     // Put the MultiPart into the Message 
     mesg.setContent(mp); 

     // Step 2 - write to a stream 
     mesg.writeTo(byteArrayOutputStream); 

     byte bytes[] = byteArrayOutputStream.toByteArray(); 
     ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes, 0, 10); 
     BufferedInputStream bufferedInputStream = new BufferedInputStream(byteArrayInputStream); 
     boolean thrown = false; 
     try 
     { 
      //Why does this not throw a messageexception. 
      MimeMessage mesg2 = new MimeMessage(session, bufferedInputStream); 
     } 
     catch(MessagingException me){ 
      thrown = true; 
     } 

     if(!thrown) { 
      assertTrue("Expected exception not thrown.", false); 
     } 
    } 

    public void testMulitpleMulitpartMessages() throws MessagingException, IOException { 
     Properties props = new Properties(); 
     Session session = Session.getInstance(props, null); 
     String testMsg1 = "test"; 
     String testMsg2 = "test1"; 
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 

     // Step 1 - Create first MIME message 
     MimeMessage mesg = new MimeMessage(session); 
     Multipart mp = new MimeMultipart("mixed"); 
     //create a child part 
     BodyPart bodyPart = new MimeBodyPart(); 
     bodyPart.setContent(testMsg1, "application/x-special"); 
     bodyPart.setHeader("Content-Length", String.valueOf(testMsg1.length())); 
     DataSource ds = new ByteArrayDataSource(testMsg1, "application/x-special"); 
     bodyPart.setDataHandler(new DataHandler(ds)); 
     bodyPart.setHeader("Content-Transfer-Encoding", "8bit"); 
     // Add the child part to the multipart 
     mp.addBodyPart(bodyPart); 
     // Put the MultiPart into the Message 
     mesg.setContent(mp); 

     // Step 2 - write to a stream 
     mesg.writeTo(byteArrayOutputStream); 

     // Step 3 - Create second MIME message 
     MimeMessage mesg2 = new MimeMessage(session); 
     mp = new MimeMultipart("mixed"); 
     //create a child part 
     bodyPart = new MimeBodyPart(); 
     bodyPart.setContent(testMsg2, "application/x-special"); 
     bodyPart.setHeader("Content-Length", String.valueOf(testMsg2.length())); 
     ds = new ByteArrayDataSource(testMsg2, "application/x-special"); 
     bodyPart.setDataHandler(new DataHandler(ds)); 
     bodyPart.setHeader("Content-Transfer-Encoding", "8bit"); 
     // Add the child part to the multipart 
     mp.addBodyPart(bodyPart); 
     // Put the MultiPart into the Message 
     mesg2.setContent(mp); 

     // Step 4 - write to the same stream 
     mesg2.writeTo(byteArrayOutputStream); 

     // Step 6 - read the two messages back 
     ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); 
     BufferedInputStream bufferedInputStream = new BufferedInputStream(byteArrayInputStream); 
     List<MimeMessage> listMessages = new ArrayList<MimeMessage>(); 
     while (bufferedInputStream.available() > 0) { 
      //http://java.sun.com/products/javamail/javadocs/javax/mail/internet/MimeMessage.html#MimeMessage(javax.mail.Session,%20java.io.InputStream) 
      //The InputStream will be left positioned at the end of the data for the message. 
      //WHY does this not work? It reads the whole stream. 
      mesg = new MimeMessage(session, bufferedInputStream); 
      //output the message 
      listMessages.add(mesg); 
     } 

     assertEquals(2, listMessages.size()); 

     assertTrue(listMessages.get(0).equals(mesg)); 
     assertTrue(listMessages.get(1).equals(mesg2)); 
    } 
} 

Répondre

4

L'API JavaMail est un porc, et l'utiliser première est une tâche ingrate, en grande parce qu'il ne se comporte pas comme vous » d attendre.

Je recommanderais d'utiliser la couche API de Spring autour d'elle, c'est beaucoup moins stressant. Il ne masque pas complètement JavaMail, mais le rend plus prévisible et plus convivial pour les tests. JavaMail lira tout le flux, éventuellement en le tamponnant.

1

Je suis d'accord avec @skaffman, mais mon point de vue est qu'il est juste fortement optimisé sans commentaires quant à pourquoi, et cela le rend difficile à utiliser. La méthode MimeMessage.parse(InputStream) est ce dont vous avez besoin. Il lit le flux entier, sans le fermer, sauf si vous utilisez un SharedInputStream. Cela laissera l'InputStream positionné à la fin, comme vous le voyez. Le MimeMessage ne fait pas grand-chose pour interpréter les données dans le flux, donc je pense qu'il vous manque quelque chose de plus grand pour utiliser vos mots. Pourquoi attendez-vous qu'il interprète les données? Pouvez-vous simplement envoyer les messages en plusieurs parties que vous utilisez pour créer vos flux?