How to send ZipInputStream as attachment via java mail?

4.9k views Asked by At

I have a ZipInputStream. How can we send the ZipInputStream as an attachment (data.zip) via java mail?

I had seen some solution like using ByteArrayDatasource but since the MimeBodyPart receives InputStream as one constructor and we have an InputStream handy, I would like to know how to solve this issue without using ByteArrayDataSource.

2

There are 2 answers

1
Daniel Hernández On

I think you have made a wrong question, what you really want it is:

How can I attach a zip file into a email?

right? You cannot attach any object type you are waiting to attach a InputStream (ZipInputStream in this case) a InputStream is a Stream that allow to read bytes 1 by 1, or by a buffer.

You can use apache commons library commons-io to get a byte array and write those bytes in the filesystem

ZipInputStream zis = ...get your stream
byte[] zipbytes = IOUtils.toByteArray(zis);
FileOutputStream fos = new FileOutputStream(new File("/path/temp.zip"));
fos.write(zipbytes);
fos.close();

And I found here in the forums just to copy paste how you can attach the email:

final String username = "[email protected]";
    final String password = "your.password";

    Properties props = new Properties();
    props.put("mail.smtp.auth", true);
    props.put("mail.smtp.starttls.enable", true);
    props.put("mail.smtp.host", "smtp.gmail.com");
    props.put("mail.smtp.port", "587");

    Session session = Session.getInstance(props,
            new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });

    try {

        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress("[email protected]"));
        message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse("[email protected]"));
        message.setSubject("Testing Subject");
        message.setText("PFA");

        MimeBodyPart messageBodyPart = new MimeBodyPart();

        Multipart multipart = new MimeMultipart();

        messageBodyPart = new MimeBodyPart();
        String fileName = "attachmentName.zip"
        DataSource source = new FileDataSource(new File("/path/temp.zip"));
        messageBodyPart.setDataHandler(new DataHandler(source));
        messageBodyPart.setFileName(fileName);
        multipart.addBodyPart(messageBodyPart);

        message.setContent(multipart);

        System.out.println("Sending");

        Transport.send(message);

        System.out.println("Done");

    } catch (MessagingException e) {
        e.printStackTrace();
}
2
Bill Shannon On

Writing the data to a file and then attaching the file will definitely work, and if you don't know how large the data might be than that's a reasonable choice. Otherwise, ByteArrayDataSource will allow you to keep the data in memory, although it will make a copy of the data first. There are more complicated answers that might have better performance, but those are the two simple approaches.

However, if all you have is a ZipInputStream, I'm not sure there's a way to read the raw zip format data, so I don't think you can use either of these approaches directly. You either need direct access to the zip file, or you need a real InputStream that contains the zip format data.

(And no, you don't pass the InputStream to the MimeBodyPart constructor since it's not a MIME format entity; you use it to construct a DataSource of some sort, from which you construct a DataHandler, which you set on the MimeBodyPart.)