JavaMail - How to download attachments in e-mails
- Details
- Written by Nam Ha Minh
- Last Updated on 09 July 2019   |   Print Email
In this tutorial, I will guide you how to write Java code to download attachments from emails programmatically, using JavaMail API.
The article Receive e-mail messages from a POP3-IMAP server describes necessary steps to download e-mail messages from mail server, but only basic information of a message is retrieved, such as header fields (from, to, cc, subject…) and body message. However, the attachment is skipped. So this article is a complement which focuses on how to download attachments in an e-mail message.
A message may contain one or several attachments. As discussed in the article Send e-mail with attachment in Java, if a message contains attachments, its content must be of type MultiPart, and the part contains a file must be of type MimeBodyPart. So it’s important to determine if a message may contain attachments using the following code:
// suppose 'message' is an object of type Message String contentType = message.getContentType(); if (contentType.contains("multipart")) { // this message may contain attachment }
Then we must iterate through each part in the multipart to identify which part contains the attachment, as follows:
Multipart multiPart = (Multipart) message.getContent(); for (int i = 0; i < multiPart.getCount(); i++) { MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(i); if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) { // this part is attachment // code to save attachment... } }
The MimeBodyPart class provides methods for retrieving and storing attached file, but the way is different between JavaMail 1.3 and JavaMail 1.4.
In JavaMail 1.3, we have to read bytes from an InputStream which can be obtained from the method getInputStream() of the class MimeBodyPart, and write those bytes into an OutputStream, for example:
// save an attachment from a MimeBodyPart to a file String destFilePath = "D:/Attachment/" + part.getFileName(); FileOutputStream output = new FileOutputStream(destFilePath); InputStream input = part.getInputStream(); byte[] buffer = new byte[4096]; int byteRead; while ((byteRead = input.read(buffer)) != -1) { output.write(buffer, 0, byteRead); } output.close();
In JavaMail 1.4, the MimeBodyPart class introduces two convenient methods that save us a lot of time:
- void saveFile(File file)
- void saveFile(String file)
So saving attachment from a part to a file is as easy as:
part.saveFile("D:/Attachment/" + part.getFileName());
or:
part.saveFile(new File(part.getFileName()));
And following is code of sample program that connects to a mail server via POP3 protocol, downloads new messages and save attachments to files on disk, if any. And it follows JavaMail 1.4 approach:
package net.codejava.mail; import java.io.File; import java.io.IOException; import java.util.Properties; import javax.mail.Address; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.NoSuchProviderException; import javax.mail.Part; import javax.mail.Session; import javax.mail.Store; import javax.mail.internet.MimeBodyPart; /** * This program demonstrates how to download e-mail messages and save * attachments into files on disk. * * @author www.codejava.net * */ public class EmailAttachmentReceiver { private String saveDirectory; /** * Sets the directory where attached files will be stored. * @param dir absolute path of the directory */ public void setSaveDirectory(String dir) { this.saveDirectory = dir; } /** * Downloads new messages and saves attachments to disk if any. * @param host * @param port * @param userName * @param password */ public void downloadEmailAttachments(String host, String port, String userName, String password) { Properties properties = new Properties(); // server setting properties.put("mail.pop3.host", host); properties.put("mail.pop3.port", port); // SSL setting properties.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); properties.setProperty("mail.pop3.socketFactory.fallback", "false"); properties.setProperty("mail.pop3.socketFactory.port", String.valueOf(port)); Session session = Session.getDefaultInstance(properties); try { // connects to the message store Store store = session.getStore("pop3"); store.connect(userName, password); // opens the inbox folder Folder folderInbox = store.getFolder("INBOX"); folderInbox.open(Folder.READ_ONLY); // fetches new messages from server Message[] arrayMessages = folderInbox.getMessages(); for (int i = 0; i < arrayMessages.length; i++) { Message message = arrayMessages[i]; Address[] fromAddress = message.getFrom(); String from = fromAddress[0].toString(); String subject = message.getSubject(); String sentDate = message.getSentDate().toString(); String contentType = message.getContentType(); String messageContent = ""; // store attachment file name, separated by comma String attachFiles = ""; if (contentType.contains("multipart")) { // content may contain attachments Multipart multiPart = (Multipart) message.getContent(); int numberOfParts = multiPart.getCount(); for (int partCount = 0; partCount < numberOfParts; partCount++) { MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(partCount); if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) { // this part is attachment String fileName = part.getFileName(); attachFiles += fileName + ", "; part.saveFile(saveDirectory + File.separator + fileName); } else { // this part may be the message content messageContent = part.getContent().toString(); } } if (attachFiles.length() > 1) { attachFiles = attachFiles.substring(0, attachFiles.length() - 2); } } else if (contentType.contains("text/plain") || contentType.contains("text/html")) { Object content = message.getContent(); if (content != null) { messageContent = content.toString(); } } // print out details of each message System.out.println("Message #" + (i + 1) + ":"); System.out.println("\t From: " + from); System.out.println("\t Subject: " + subject); System.out.println("\t Sent Date: " + sentDate); System.out.println("\t Message: " + messageContent); System.out.println("\t Attachments: " + attachFiles); } // disconnect folderInbox.close(false); store.close(); } catch (NoSuchProviderException ex) { System.out.println("No provider for pop3."); ex.printStackTrace(); } catch (MessagingException ex) { System.out.println("Could not connect to the message store"); ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } /** * Runs this program with Gmail POP3 server */ public static void main(String[] args) { String host = "pop.gmail.com"; String port = "995"; String userName = "your_email"; String password = "your_password"; String saveDirectory = "E:/Attachment"; EmailAttachmentReceiver receiver = new EmailAttachmentReceiver(); receiver.setSaveDirectory(saveDirectory); receiver.downloadEmailAttachments(host, port, userName, password); } }
The program above will save attachments into a specified directory, and print out details of each received message, including file names of the attachments.
NOTES:
You need to use JavaMail jar files. If you use Maven, add the following dependency to the pom.xml file:
<dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency>
This will add the javax.mail-VERSION.jar and activation-VERSION.jar to the project's classpath. If you have to add them manually, download from JavaMail Project page.
Other JavaMail Tutorials:
- How to send plain text email using JavaMail
- How to send email in HTML format using JavaMail
- How to send email with attachments using JavaMail
- How to insert images into email for sending with JavaMail
- How to receive emails from server using JavaMail
- How to search email messages using JavaMail
- How to delete emails programmatically using JavaMail
Comments
// this part may be the message content
messageContent = part.getContent().toString();
Thanks for nice post. i want to retrieve email messageID using folderInbox.search(), Can you guide me to achieve this?
I have a problem with recieved pdf file. I always get a encrypted name when I call the getFileName method.
Do you have any solution for this ?