Search code examples
javaemailemail-attachments

How to send any type of attachment using java mail api?


I am able to send mails with only text files attached and i am using file path. I want a code to send any type of attachment using file inputstream

I am able to send mails with only text files attached and i am using file.

messageBodyPart = new MimeBodyPart();
         String filename = "/home/manisha/file.txt";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         multipart.addBodyPart(messageBodyPart);

I expect the code to send any type of attachment using java api.


Solution

  • It turns out that a ByteArrayDataSource can be used to send a stream of any type. You will need to specify the mime type in addition to the stream as there is no way it can know the type without it. If the InputStream represents a jpeg image, you would use "image/jpeg" as the type passed to ByteArrayDataSource.

    Know that ByteArrayDataSource will completely read the InputStream into a byte array for processing. If the InputStream is very large, that could consume a large amount of memory. Then again, most email systems limit attachment size.

    Please note that this code is not production ready and requires error / exception handling.

        messageBodyPart = new MimeBodyPart();
        String filename = "/home/manisha/file.txt";
        //
        // FileInputStream is just for the example. You can use other InputStreams as well.
        //
        InputStream inputStream = new FileInputStream(filename);
    
        DataSource source;
        try (InputStream inputStream = new FileInputStream(filename)) {
            source = new ByteArrayDataSource(inputStream, "text/plain;charset=UTF-8");
        }
        messageBodyPart.setDataHandler(new DataHandler(source));
        messageBodyPart.setFileName(filename);
        multipart.addBodyPart(messageBodyPart);
    
        // Send the complete message parts
        message.setContent(multipart);
    

    [EDIT] Here is some code to test that your InputStream has data. You can call it with the source above to print out the number of bytes in your input stream.

    private static void printDataSourceByteCount(DataSource source) throws IOException {
        try (InputStream is = source.getInputStream()) {
    
            long totalBytesRead = 0;
            byte [] buffer = new byte[2048];
            int bytesRead = is.read(buffer);
            while(bytesRead > 0) {
                totalBytesRead += bytesRead;
                bytesRead = is.read(buffer);
            }
            System.out.println(String.format("Read %d bytes", totalBytesRead));
        }
    }
    

    [EDIT] And here is my fully functioning example that uses a test pdf. A text file works as well as long as you change the mime type to "text/plain".

    public static void main(String[] args) {
    
        // Recipient's email ID needs to be mentioned.
        String to = "<to email>";
    
        // Sender's email ID needs to be mentioned
        String from = "<from email>";
    
        final String username = "<email server username>";// change accordingly
        final String password = "<email server password>";// change accordingly
    
        // Set to your email server
        String host = "mail.acme.com";
    
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "false");
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", "25");
    
        // Get the Session object.
        Session session = Session.getInstance(props, new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });
    
        try {
            // Create a default MimeMessage object.
            Message message = new MimeMessage(session);
    
            // Set From: header field of the header.
            message.setFrom(new InternetAddress(from));
    
            // Set To: header field of the header.
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
    
            // Set Subject: header field
            message.setSubject("Testing Subject");
    
            // Create the message part
            BodyPart messageBodyPart = new MimeBodyPart();
    
            // Now set the actual message
            messageBodyPart.setText("Hello. Attached is a very important PDF.");
    
            // Create a multipar message
            Multipart multipart = new MimeMultipart();
    
            // Set text message part
            multipart.addBodyPart(messageBodyPart);
    
            // Part two is attachment
            messageBodyPart = new MimeBodyPart();
            String filename = "/Users/rick/Tmp/test.pdf";
    
            DataSource source;
            try (InputStream inputStream = new FileInputStream(filename)) {
                source = new ByteArrayDataSource(inputStream, "application/pdf");
            }
    
            printDataSourceByteCount(source);
    
            messageBodyPart.setDataHandler(new DataHandler(source));
            messageBodyPart.setFileName("SecretsOfTheUniverse.pdf");
            multipart.addBodyPart(messageBodyPart);
    
            // Send the complete message parts
            message.setContent(multipart);
    
            // Send message
            Transport.send(message);
    
            System.out.println("Sent message successfully....");
    
        } catch (MessagingException e) {
            // TODO handle the error
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            // TODO handle the error
            e.printStackTrace();
        } catch (IOException e) {
            // TODO handle the error
            e.printStackTrace();
        }
    }