如何发送一封邮件作为另一封邮件的附件在Java中,而不保存到磁盘

问题描述:

我想发送邮件作为附件在另一封邮件使用javax api。截至目前,我先保存在磁盘上的邮件,然后使用下面的代码将其连接到另一个电子邮件: -如何发送一封邮件作为另一封邮件的附件在Java中,而不保存到磁盘

 MimeMessage generateMailMessage = new MimeMessage(getMailSession); 
     generateMailMessage.setFrom(new InternetAddress("[email protected]")); 
     String mailSubject = properties.getProperty("mail.subject"); 
     generateMailMessage 
       .setSubject(mailSubject); 
     generateMailMessage.setContent(emailBody, "text/html"); 
     generateMailMessage.addRecipient(Message.RecipientType.TO, 
       new InternetAddress(properties.getProperty("message.recipienttype.to"))); 
     generateMailMessage.addRecipient(Message.RecipientType.CC, 
       new InternetAddress(recipientEmail)); 


     File file = new File(properties.getProperty("mail.draft.folder")+"mail.eml"); 
     FileOutputStream fos = new FileOutputStream(chatFile); 
     generateMailMessage.writeTo(fos); 

     Session getMailSession1 = Session.getDefaultInstance(mailServerProperties, null); 

     MimeMessage generateMailMessage1 = new MimeMessage(getMailSession1); 
     generateMailMessage1 
       .setSubject("Attachment"); 

     generateMailMessage1.addRecipient(Message.RecipientType.TO, 
       new InternetAddress("[email protected]")); 


     Multipart multipart = new MimeMultipart(); 
     MimeBodyPart messageBodyPart = new MimeBodyPart(); 
     messageBodyPart.setDescription("hahdsa"); 
     DataSource source = new FileDataSource(file); 
     messageBodyPart.setDataHandler(new DataHandler(source)); 
     messageBodyPart.setFileName("mail.eml"); 
     multipart.addBodyPart(messageBodyPart); 
     generateMailMessage1.setContent(multipart); 


     transport = getMailSession1.getTransport("smtp"); 
     if(!transport.isConnected()) 
      transport.connect(properties.getProperty("mail.host"), 
       Integer.parseInt((String) properties.get("mail.smtp.port")), "[email protected]", 
       (String) properties.get("mail.password")); 



     transport.sendMessage(generateMailMessage1, generateMailMessage1.getAllRecipients()); 
     transport.close(); 

有什么办法,我可以做的同样的事情,但不保存连接电子邮件。我已经搜索出来,但发现要附加的文件可以存储在内存中,但无法将邮件保存在内存中。

请建议。

感谢

+1

你可以使用'java.io.File'来创建一个临时文件(并在它自己之后清理),像这样https://stackoverflow.com/a/7083754/16959 –

你可以写一个附加的电子邮件不进FileOutputStream但进入ByteArrayOutputStream,所以电子邮件会留在RAM中。然后你可以将流转换为字节数组并发送它。像这样的东西(这是不低于纯Java代码,没有任何异常处理,关闭流,等等,它只是描述了一个思路伪代码):

... 
ByteArrayOutputStream emailOutputStream = new ByteArrayOutputStream(); 
generateMailMessage.writeTo(emailOutputStream); 
... 
MimeBodyPart messageBodyPart = new MimeBodyPart(); 
... 
byte[] email = emailOutputSteam.toByteArray(); 
messageBodyPart.setDataHandler(email); 
... 

唯一要担心的是有关如何安装电子邮件数据到消息正文。我不熟悉您使用的电子邮件API。可能是指定一个字节数组作为MimeBodyPart.setDataHandler()方法的参数,可能不会。但很可能MimeBodyPart.setDataHandler()方法可以接受一个流(大多数Java库不仅可以从文件读取,也可以从输入流读取)。在这种情况下ByteArrayInputStream会有所帮助,就像如下图所示:

... 
ByteArrayOutputStream emailOutputStream = new ByteArrayOutputStream(); 
generateMailMessage.writeTo(emailOutputStream); 
... 
MimeBodyPart messageBodyPart = new MimeBodyPart(); 
... 
ByteArrayInputStream emailInputStream = ByteArrayInputStream(emailOutputSteam.toByteArray()); 
messageBodyPart.setDataHandler(emailInputStream); 
... 

UPDATE

哦,我知道了... setDataHandler()接受DataHandler。并且DataHandler接受DataSource

但让我们看看DataSource's Javadoc。已经提供了两种实现:FileDataSourceURLDataSource。实现从字节数组获取数据的新数据源并不困难。只有很少的方法需要实施。再一次,下面的代码大大简化了。但它带来了数据流是通用概念的想法。一旦你实现DataSource接口DataHandler类甚至不会注意到实际数据是采取RAM(或数据库,或其他):

public class ByteArrayInputStreamDataSource { 

    private ByteArrayInputStream stream; 

    public ByteArrayInputStreamDataSource(byte[] data) { 
     this.stream = new ByteArrayInputStream(data); 
    } 

    public String getContentType() { 
     return "Your content MIME type, perhaps, it will be text/html ..."; 
    } 

    public InputStream getInputStream() { 
     return stream; 
    }  

    public String getName() { 
     return "Some meaningful name"; 
    } 

    public OutputStream getOutputStream() { 
     throw new UnsupportedOperationException("Modification of the datasource is not allowed."); 
    } 

    public void close() { 
     // This method is not required by DataSource interface. 
     // But once we deal with stream generally it will be better 
     // to put here logic that closes the stream gracefully. 
     // As for ByteArrayInputStream there is no need to close it 
     // according to Javadoc: 
     // https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html#close() 
    } 
} 

因此,我们的自定义数据源可以采用这样的:

... 
ByteArrayOutputStream emailOutputStream = new ByteArrayOutputStream(); 
generateMailMessage.writeTo(emailOutputStream); 
... 
MimeBodyPart messageBodyPart = new MimeBodyPart(); 
... 
DataSource byteArraySource = new ByteArrayInputStream(emailOutputStream.toByteArray()); 
messageBodyPart.setDataHandler(new DataHandler(byteArraySource)); 
... 
+1

setDataHandler接受DataHandler而不是ByteArrayInputStream 。 – Manish

+0

@Manish,我已经更新了有关您评论的答案。希望这会有所帮助。 – flaz14