1

I am trying to send a mail as attachment in another mail using javax api. As of now I am saving the mail first on the disk and then attaching it to the another email using the following code:-

        MimeMessage generateMailMessage = new MimeMessage(getMailSession);
        generateMailMessage.setFrom(new InternetAddress("abc@a.com"));
        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("manish@xyz.com"));


        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")), "abc@xyz.com",
                (String) properties.get("mail.password"));



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

Is there any way that i can do the same thing without saving the attached email. I have searched out but found that files to be attached can be stored in memory but found nowhere to save the mail in memory.

Please suggest.

Thanks

Manish
  • 1,274
  • 3
  • 22
  • 59
  • 1
    You could use `java.io.File`'s ability to create a temporary file (and clean up after itself) with something like this https://stackoverflow.com/a/7083754/16959 – Jason Sperske Jun 02 '17 at 06:47

1 Answers1

0

You can write an attached e-mail not into FileOutputStream but into ByteArrayOutputStream, so the e-mail will stay in RAM. Then you can convert the stream to array of bytes and send it. Something like this (it's not a pure Java code below, there is no exception handling, closing the streams, etc, it's just a pseudo code that illustrates the idea):

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

The only concern is about how to attach e-mail data to message body. I'm not familiar with the e-mail API that you use. May be it's possible to specify an array of bytes as parameter for MimeBodyPart.setDataHandler() method, may be not. But it's very likely that MimeBodyPart.setDataHandler() method can accept a steam (BTW most of Java libraries can read not only from files but from input streams as well). In such case ByteArrayInputStream will help, like illustrated below:

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

UPDATE

Oh, I see... setDataHandler() accepts DataHandler. And DataHandler accepts DataSource!

But lets look at DataSource's Javadoc. There are two implementations provided already: FileDataSource and URLDataSource. It's not difficult to implement new data source that takes data from array of bytes. Only few methods have to be implemented. Again, the code below is drastically simplified. But it brings the idea that data streams is universal concept. Once you've implemented DataSource interface DataHandler class will not even notice that actually data is taken for RAM (or database, or whatever):

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()
    }
}

So our custom data source can be used like this:

...
ByteArrayOutputStream emailOutputStream = new ByteArrayOutputStream();
generateMailMessage.writeTo(emailOutputStream);
...
MimeBodyPart messageBodyPart = new MimeBodyPart();
...
DataSource byteArraySource = new ByteArrayInputStream(emailOutputStream.toByteArray());
messageBodyPart.setDataHandler(new DataHandler(byteArraySource));
...
flaz14
  • 826
  • 1
  • 13
  • 25