parse outlook emails using outlook-message-parser library - java

I am trying to load emails from INBOX from remote mailbox and parse them to extract attachments and converted body in HTML format.
I use the below code snippet to parse using outlook message parser jar
ResultSuccess insertMessage(Message currentMsg) {
final OutlookMessageParser msgp = new OutlookMessageParser();
final OutlookMessage msg = parseMsg(currentMsg.getInputStream());
}
and the currentMsg is of Type javax.mail.Message
Code snippet of getting emails from server is as follows
Properties props = new Properties();
Message currentMessage;
Session session = Session.getInstance(props, null);
session.setDebug(debug);
store = session.getStore(PROTOCOL);
store.connect(host, username, password);
Message message[] = inboxfolder.getMessages();
Message copyMessage[] = new Message[1];
int n = message.length;
for (int j = 0; j < n; j++) {
currentMessage = message[j];
ResultSuccess result = insertMessage(currentMessage);
Exception details are as follows
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
org.apache.poi.poifs.filesystem.NotOLE2FileException: Invalid header signature; read 0x615F3430305F2D2D, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:151)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:117)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:285)
at org.simplejavamail.outlookmessageparser.OutlookMessageParser.parseMsg(OutlookMessageParser.java:133)
at com.email.Email_Parse.loadMessages(Email_Parse.java:38)
at com.email.Email_Parse.getMessages(Email_Parse.java:116)
at com.email.Email_Parse.main(Email_Parse.java:26)
However the issue doesn't occur when I try to load emails from local disk and parse them.
Any idea on how to resolve the issue?

I suppose you're using outlook-message-parser to parse the emails stored on disk.
Messages retrieved from the mail server are not in the Outlook file format (even if the remote server is an Microsoft Exchange server or Microsoft's Outlook email service) so outlook-message-parser won't be able to parse them.
You should use the JavaMail Api to retrieve the body of the message and its attachments.
This page has a description (with a few examples) of the steps needed to read a message with attachments. Here is an excerpt :
Q: How do I read a message with an attachment and save the
attachment?
A: As described above, a message with an attachment is
represented in MIME as a multipart message. In the simple case, the
results of the Message object's getContent method will be a
MimeMultipart object. The first body part of the multipart object wil
be the main text of the message. The other body parts will be
attachments. The msgshow.java demo program shows how to traverse all
the multipart objects in a message and extract the data of each of the
body parts. The getDisposition method will give you a hint as to
whether the body part should be displayed inline or should be
considered an attachment (but note that not all mailers provide this
information). So to save the contents of a body part in a file, use
the saveFile method of MimeBodyPart.
To save the data in a body part into a file (for example), use the
getInputStream method to access the attachment content and copy the
data to a FileOutputStream. Note that when copying the data you can
not use the available method to determine how much data is in the
attachment. Instead, you must read the data until EOF. The saveFile
method of MimeBodyPart will do this for you. However, you should not
use the results of the getFileName method directly to name the file to
be saved; doing so could cause you to overwrite files unintentionally,
including system files.
Note that there are also more complicated cases to be handled as well.
For example, some mailers send the main body as both plain text and
html. This will typically appear as a multipart/alternative content
(and a MimeMultipart object) in place of a simple text body part.
Also, messages that are digitally signed or encrypted are even more
complex. Handling all these cases can be challenging. Please refer to
the various MIME specifications and other resources listed on our main
page.
Emails are not always in html, sometimes they are just plain text. Most of the time they are "multipart". For example, an email can have an html part that will be displayed by email clients that support html (gmail, thunderbird ...) and another plain text part that can be used by other email clients that can't display html (think text-based email clients).
So before dumping the content of an email you have to check its content type (or if it has multiple part, check the content type of the parts).
For the html parts, dumping the content verbatim can give you the desired result depending on how images are referenced.
If an image is referenced using an http URL (like <img src="https://example.com/a.png"/>) no further work is necessary to display the result in a browser.
If an image is referenced using a Content-Id URL (like <img src="cid:image002.gif#01D44EB0.904DB790"/>) then you have to do extra work to be able to display the result correctly in a browser.
You have to look for the correct image in the email parts and decide how to include it in the final result.
For example, save it to disk and replace the reference in the html with its path on the disk so that <img src="cid:image002.gif#01D44EB0.904DB790"/> becomes something like this <img src="/path/to/saved/images/imagexyz.png"/>
Or convert it to base64 format and replace the reference in the html with a data URI so that <img src="cid:image002.gif#01D44EB0.904DB790"/> becomes something like this <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>.
I don't know if there is a java library that can do this automatically.
The JavaMail api website provides samples that you can read to learn how to use it. You can check msgshow.java from the samples to see how you can use the api to retrieve the content of a message.
Here is a simple example program that downloads the last message from a gmail inbox to a local directory (it may have bugs. don't forget to put your own account and password and replace "/tmp/messages" with a valid directory on your computer).
import javax.mail.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Properties;
public class MessageDownloader {
private File destDir;
public MessageDownloader(File destDir){
this.destDir = destDir;
}
public void download(Part message, String basename) throws MessagingException, IOException {
System.out.println("Type : " + message.getContentType());
if(message.isMimeType("text/plain")) {
downloadTextPart((String) message.getContent(), basename + ".txt");
}else if(message.isMimeType("text/html")) {
downloadTextPart((String) message.getContent(), basename + ".html");
}else if(message.isMimeType("image/*") || Part.ATTACHMENT.equalsIgnoreCase(message.getDisposition())){
downloadDataPart(message, basename);
}else if(message.isMimeType("multipart/*")){
downloadMultiPart((Multipart) message.getContent(), basename);
}else{
System.out.println("Unrecognized type");
}
}
private void downloadDataPart(Part dataPart, String basename) throws IOException, MessagingException {
File dataFile = new File(destDir, basename + "_" + dataPart.getFileName());
Files.copy(dataPart.getInputStream(), dataFile.toPath());
}
private void downloadTextPart(String textContent, String filename) throws MessagingException, IOException{
File textFile = new File(destDir, filename);
Files.writeString(textFile.toPath(), textContent);
}
private void downloadMultiPart(Multipart multiPartMessage, String basename) throws MessagingException, IOException {
for(int partIdx = 0; partIdx < multiPartMessage.getCount(); partIdx++){
BodyPart part = multiPartMessage.getBodyPart(partIdx);
download(part, String.format("%s_%d_", basename, partIdx));
}
}
public static void main(String[] args) throws MessagingException, IOException {
Store store = getStore();
Folder folder = store.getFolder("Inbox");
folder.open(Folder.READ_ONLY);
MessageDownloader msgDownloader = new MessageDownloader(new File("/tmp/messages"));
Message lastMessage = folder.getMessage(folder.getMessageCount()-1);
msgDownloader.download(lastMessage, "last_message");
folder.close();
store.close();
}
private static Store getStore() throws MessagingException {
Properties props = new Properties();
props.setProperty("mail.smtp.ssl.enable", "true");
Session session = Session.getInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", "account#gmail.com","password");
return store;
}
}

Related

Use Java Gmail API to send an email with multiple (large) attachments

I am trying to use the Google Gmail API (Java) to create an email that contains multiple attachments. Using the code below, I am able to send multiple attachments that are embedded within a MimeMessage if the attachments total less than 5MB (Google's threshold for simple file upload).
com.google.api.services.gmailGmail service = (... defined above ...)
javax.mail.internet.MimeMessage message = (... defined above with attachments embedded ...)
// Send the email
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
mimeMessage.writeTo(buffer);
byte[] bytes = buffer.toByteArray();
String encodedEmail = Base64.encodeBase64URLSafeString(bytes);
Message message = new Message();
message.setRaw(encodedEmail);
message = service.users().messages().send("me", message).execute();
However, I am unable to figure out how to correctly attach multiple files to an email using the Gmail Java API. The method below looks promising, but it appears to only accept 1 File/InputStream (mediaContent).
Gmail.Users.Messages.Send send(userId, Message content, AbstractInputStreamContent mediaContent)
Anyone know how to correctly implement a multi-file upload using the API?
As you correctly stated, the maximum attachment size for Simple file upload is 5 MB
Conclusion:
You need to to use Multipart upload or Resumable upload.
A sample sending an email with a multipart upload:
public static MimeMessage createEmailWithAttachment(String to, String from, String subject,
String bodyText,String filePath) throws MessagingException{
File file = new File(filePath);
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage email = new MimeMessage(session);
Multipart multipart = new MimeMultipart();
InternetAddress tAddress = new InternetAddress(to);
InternetAddress fAddress = new InternetAddress(from);
email.setFrom(fAddress);
email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress);
email.setSubject(subject);
if (file.exists()) {
source = new FileDataSource(filePath);
messageFilePart = new MimeBodyPart();
messageBodyPart = new MimeBodyPart();
try {
messageBodyPart.setText(bodyText);
messageFilePart.setDataHandler(new DataHandler(source));
messageFilePart.setFileName(file.getName());
multipart.addBodyPart(messageBodyPart);
multipart.addBodyPart(messageFilePart);
email.setContent(multipart);
} catch (MessagingException e) {
e.printStackTrace();
}
}else
email.setText(bodyText);
return email;
}
Here you can find many other useful samples for sending emails with the Gmail API in Java.
It turns out that my MimeMessage was generated correctly, however, if the attachments included in the MimeMessage are larger than 5MB, you need to use a different Gmail API send() method. The API docs are incredibly confusing because they appear to state that you need to make multiple calls to rest endpoints to upload multiple files. It turns out that the Gmail Java Api does all the for you based off the MimeMessage submitted.
Below is a code snippet that shows how to use the two methods: "simple upload" and "multipart upload".
com.google.api.services.gmailGmail service = (... defined above ...)
javax.mail.internet.MimeMessage message = (... defined above with attachments embedded ...)
/**
* Send email using Gmail API - dynamically uses simple or multipart send depending on attachments size
*
* #param mimeMessage MimeMessage (includes any attachments for the email)
* #param attachments the Set of files that were included in the MimeMessage (if any). Only used to calculate total size to see if we should use "simple" send or need to use multipart upload.
*/
void send(MimeMessage mimeMessage, #Nullable Set<File> attachments) throws Exception {
Message message = new Message();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
mimeMessage.writeTo(buffer);
// See if we need to use multipart upload
if (attachments!=null && computeTotalSizeOfAttachments(attachments) > BYTES_5MB) {
ByteArrayContent content = new ByteArrayContent("message/rfc822", buffer.toByteArray());
message = service.users().messages().send("me", null, content).execute();
// Otherwise, use "simple" send
} else {
String encodedEmail = Base64.encodeBase64URLSafeString(buffer.toByteArray());
message.setRaw(encodedEmail);
message = service.users().messages().send("me", message).execute();
}
System.out.println("Gmail Message: " + message.toPrettyString());
}

Extracting attachments from Outlook .msg files using ColdFusion

I am building a system where intranet users are allowed to drag and drop files into a div on our ColdFusion site, which after some validation will then automatically upload them to a file server. One of my requirements is: when the file which was uploaded is a .msg file (Outlook Email), extract any files which are attachments to that email and upload them individually. This is possible using the org.apache.poi.hsmf.MAPIMessage Java object.
With the following code I am able to see each attachment object listed out. I can then get their filenames and extensions and save each one to the local file system.
However, this does not work if the attachment is another .msg file. When I call getEmbeddedAttachmentObject() on an attached .msg file, it returns an object which contains only "undefined". Non .msg files return a binary object which I can then pass into the FileWrite() ColdFusion function. Further examination of the MAPIMessage object shows that it has a write() method, but upon calling it I get an error stating:
Note - writing is not yet supported for this file format, sorry.
This is backed up by the documentation on http://poi.apache.org as well.
To summarize, I can write each email message attachment to the file system without a problem, unless the attachment is another email message. Am I out of luck or is there another way to accomplish this?
<cfscript>
// Load test .msg into MAPIMessage object
MAPIMessage = createObject("java", "org.apache.poi.hsmf.MAPIMessage");
message = MAPIMessage.init('C:\Test\Test Email 1 Attachment.msg');
// Get array of attached files
attachments = message.getAttachmentFiles();
// If attachments were found
if(arrayLen(attachments) > 0) {
// Loop over each attachment
for (i=1; i LTE arrayLen(attachments); i++) {
// Dump the current attachment object
writeDump( attachments[i] );
// Get current attachment's binary data
local.data=attachments[i].getEmbeddedAttachmentObject();
// Dump binary data
writeDump( local.data );
// Get attachment's filename and extension
attachmentFileName = attachments[i].attachLongFileName.toString();
attachmentExtension = attachments[i].attachExtension.toString();
// Dump filename and extension
writeDump( attachmentFileName );
writeDump( attachmentExtension );
// Write attachment to local file system
FileWrite("#expandPath('/')##attachments[i].attachLongFileName.toString()#", local.data);
}
}
</cfscript>
After much research I found a solution to my problem. I was not able to save an embedded msg file using org.apache.poi.hsmf.MAPIMessage java object which ships with ColdFusion due to the not yet implemented write() method. Instead, I used a 3rd party tool called Aspose.Email for Java
Aspose is a paid product, and is the only way that I was able to accomplish what I needed to do.
Here is my implementation. This does everything I need it to.
local.msgStruct.attachments = [];
// Create MapiMessage from the passed in .msg file
MapiMessage = createObject("java", "com.aspose.email.MapiMessage");
message = MapiMessage.fromFile(ARGUMENTS.msgFile);
// Get attachments
attachments = message.getAttachments();
numberOfAttachments = attachments.size();
// If attachments exist
if(numberOfAttachments > 0) {
// Loop over attachments
for ( i = 0; i LT numberOfAttachments; i++) {
// Get current Attachment
currentAttachment = attachments.get_Item(i);
// Create struct of attachment info
local.attachmentInfo = {};
local.attachmentInfo.fileName = currentAttachment.getLongFileName();
local.attachmentInfo.fileExtension = currentAttachment.getExtension();
// If an attachmentDestination was specified
if(ARGUMENTS.attachmentDestination NEQ ''){
// Ignore inline image attchments (mostly email signature images)
if( NOT (left(local.attachmentInfo.fileName, 6) EQ 'image0' AND local.attachmentInfo.fileExtension EQ '.jpg') ){
// Get attachment object data (only defined for Outlook Messages, will return undefined object for other attachment types)
attachmentObjectData = currentAttachment.getObjectData();
// Check if attachment is an outlook message
if( isDefined('attachmentObjectData') AND attachmentObjectData.isOutlookMessage()){
isAttachmentOutlookMessage = 'YES';
} else {
isAttachmentOutlookMessage = 'NO';
}
////////////////////////////
// ATTACHMENT IS AN EMAIL //
////////////////////////////
if( isAttachmentOutlookMessage ){
// Get attachment as a MapiMessage
messageAttachment = currentAttachment.getObjectData().toMapiMessage();
// If an attachmentDestination was specified
if(ARGUMENTS.attachmentDestination NEQ ''){
// Set file path
local.attachmentInfo.filePath = ARGUMENTS.attachmentDestination;
// Set file path and file name
local.attachmentInfo.filePathAndFileName = ARGUMENTS.attachmentDestination & local.attachmentInfo.fileName;
// Save attachment to filesystem
messageAttachment.save(local.attachmentInfo.filePathAndFileName);
}
////////////////////////////////
// ATTACHMENT IS NOT AN EMAIL //
////////////////////////////////
} else {
// If an attachment destination was specified
if(ARGUMENTS.attachmentDestination NEQ ''){
// Set file path
local.attachmentInfo.filePath = ARGUMENTS.attachmentDestination;
// Set file path and file name
local.attachmentInfo.filePathAndFileName = ARGUMENTS.attachmentDestination & local.attachmentInfo.fileName;
// Save attachment to filesystem
currentAttachment.save(local.attachmentInfo.filePathAndFileName);
}
}
// Verify that the file was saved to the file system
local.attachmentInfo.savedToFileSystem = fileExists(ARGUMENTS.attachmentDestination & local.attachmentInfo.fileName);
// Add attachment info struct to array
arrayAppend(local.msgStruct.attachments,local.attachmentInfo);
} // End ignore inline image attachments
} // End loop over attachments
} // End if attachments exist

How to retrieve the Content-Type and the Content-Disposition from an outlook msg file using Apache POI-HSMF?

I need to write a Java program to extract all attachments from messages saved by Outlook 2016 in the native msg format. The program should skip inline images. Also some of the mails have multipart/alternative parts where the program should retrieve the "best" content-type, e.g. text/html over text/plain.
In order to do that, I need to find out the content-type and content-disposition of all parts and attachments of the message.
I tried the following:
public static void main(String[] args) throws IOException {
String mfile = "test/test2.msg";
MAPIMessage msg = new MAPIMessage(mfile);
AttachmentChunks[] attachments = msg.getAttachmentFiles();
if (attachments.length > 0) {
for (AttachmentChunks attachment : attachments) {
System.out.println("long file name = " + attachment.getAttachLongFileName());
System.out.println("content id = " + attachment.getAttachContentId());
System.out.println("mime tag = " + attachment.getAttachMimeTag());
System.out.println("embedded = " + attachment.isEmbeddedMessage());
}
}
msg.close();
}
The problem is, that the "mime tag" (i.e. the content-type) is returned only for some attachments and returns null for all others. The content-disposition seems to be totally missing.
For example, I get the following output on a mail saved by OL2016 (the mail contains a PDF attachment and an inline logo image):
long file name = Vertretungsvollmacht Übersiedlung.pdf
content id = null
mime tag = null
embedded = false
long file name = image001.jpg
content id = image001.jpg#01D2E697.12EC9370
mime tag = image/jpeg
embedded = false
Is there a way to get these attributes out of the msg files or is there a more complete & convenient way to achieve what I want in Java with some other library than Apache POI-HSMF?
In order to get the content-disposition (inline or attachment), I did the following:
String disposition = "attachment";
if (contentId != "")
if (body.contains(contentId.toString()))
disposition = "inline";
To obtain the content-type, I have derived it from the file extension of the attachment, e.g.:
String ext = fileNameOri.substring(fileNameOri.lastIndexOf(".") + 1);
switch (ext.toLowerCase()) {
case "xlsx":
ct = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
break;
}
A list of mime types can be obtained from e.g. https://wiki.selfhtml.org/wiki/MIME-Type/%C3%9Cbersicht
Of course, this should only be done in case AttachmentChunks.getAttachMimeTag() returns an empty string.
The fact that an attachment has a content-id tag does not mean it is an embedded image - Lotus Notes adds content-id to all attachments. The only valid check is to load the HTML body and figure out what the <img> tags refer to.

How do I email an HTML report (as an attachment) with images embedded?

I am creating a report with ExtentReports to be emailed out to team members outside of the domain. I use a screenshot method (below) to save screenshots of test failures. They are stored in a child folder to the ExtentReports HTML report.
I attach the report to an email, and in it, the images display fine for team members on the domain with folder permission. But I am at a loss for how to allow people outside of that folder's permissions, to see the images embedded in the report. This is the HTML for the image, directly referencing that file.
<img class="report-img" data-featherlight="file:///\\domain.local\files\QA\Projects\AutomationReports\ExtentScreens\1486487870116.jpg" src="file:///\\domain.local\files\QA\Projects\AutomationReports\ExtentScreens\1486487870116.jpg">
Here is my screenshot method.
public static String CaptureScreen(WebDriver driver) {
String ImagesPath = "\\\\domain.local\\files\\QA\\Projects\\AutomationReports\\ExtentScreens\\"
+ new Date().getTime();
TakesScreenshot oScn = (TakesScreenshot) driver;
File oScnShot = oScn.getScreenshotAs(OutputType.FILE);
File oDest = new File(ImagesPath + ".jpg");
// System.out.println(ImagesPath);
try {
FileUtils.copyFile(oScnShot, oDest);
} catch (IOException e) {
System.out.println(e.getMessage());
}
return ImagesPath + ".jpg";
}
I have 2 unrelated ideas on how to fix this. But I need some help getting started with either of them. I'm open to other suggestions.
Embed images directly into the HTML report or somehow send a folder containing screenshots with the HTML report. However, the HTML will still reference my original location and the images will be broken.
Share the folder containing images with Everyone, Guest, and Anonymous User, so people outside of the domain can open HTML that references this location. I don't know how to set these permissions, and I'm not even sure that doing so will allow an external user to view HTML referencing the location.
Please try with base64 encoding it will definitely work.
Also, please check your browser support.
Try this:
<img src="data:image/jpeg;base64,/9j/4AAQxxxxxxxx...." />
Depending on what browsers you need to support, you could embed your images in base64. like this :
<img src="data:image/jpeg;base64, LzlqLzRBQ...<!-- base64 data -->" />
Here is a tool to encode your images
You can embed base64 encoded images directly into HTML document.
<img src="data:image/jpeg;base64,/9j/4AAQxxxxxxxx...." />
You can create a multipart/report message with the images included as additional body parts in the message. The JavaMail FAQ includes this sample code:
Multipart multipart = new MimeMultipart("related");
MimeBodyPart htmlPart = new MimeBodyPart();
// messageBody contains html that references image
// using something like <img src="cid:XXX"> where
// "XXX" is an identifier that you make up to refer
// to the image
htmlPart.setText(messageBody, "utf-8", "html");
multipart.addBodyPart(htmlPart);
MimeBodyPart imgPart = new MimeBodyPart();
// imageFile is the file containing the image
imgPart.attachFile(imageFile);
// or, if the image is in a byte array in memory, use
// imgPart.setDataHandler(new DataHandler(
// new ByteArrayDataSource(bytes, "image/whatever")));
// "XXX" below matches "XXX" above in html code
imgPart.setContentID("<XXX>");
multipart.addBodyPart(imgPart);
message.setContent(multipart);
We should have a class file as below
public class GetScreenShort {
public static String capture(WebDriver driver,String screenShotName)
throws IOException
{
TakesScreenshot ts = (TakesScreenshot)driver;
String dest = ts.getScreenshotAs(OutputType.BASE64);
return "data:image/jpg;base64, " + dest ;
}
}
The same class has to be called as below
String screenShotPath = GetScreenShort.capture(webdriver,
"screenShotName");

Attachment Id of emails in java

I am currently working with java mail api . I need to list the attachment details also wants remove the attachment from some emails and forward it to others. So i'm trying to find out the Attachment ID. How can i do it? Any suggestion will be appreciate!!!
Does this help?
private void getAttachments(Part p, File inputFolder, List<String> fileNames) throws Exception{
String disp = p.getDisposition();
if (!p.isMimeType("multipart/*") ) {
if (disp == null || (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE)))) {
String fileName = p.getFileName();
File opFile = new File(inputFolder, fileName);
((MimeBodyPart) p).saveFile(opFile);
fileNames.add(fileName);
}
}
}else{
Multipart mp = (Multipart) p.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++){
getAttachments(mp.getBodyPart(i),inputFolder, fileNames);
}
}
}
There ain't anything as an attachment ID. What your mail client displays as a message with attached contents, is really a MIME Multipart and looks like this (sample source):
From: John Doe <example#example.com>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="XXXXboundary text"
This is a multipart message in MIME format.
--XXXXboundary text
Content-Type: text/plain
this is the body text
--XXXXboundary text
Content-Type: text/plain;
Content-Disposition: attachment; filename="test.txt"
this is the attachment text
--XXXXboundary text--
Important things to note:
Every part in a multipart has a Content-Type
Optionally, there can be a Content-Disposition header
Single parts can be themselves multipart
Note that there is indeed a Content-ID header, but I don't think it's what you are looking for: for example, it is used in multipart/related messages to embed image/*s and text from a text/html in the same email message. You have to understand how it works and if it's used in your input.
I think your best option is to examine the Content-Disposition and the Content-Type header. The rest is guesswork, and without actual requirement one can't help with the code.
Try using the Apache Commons Email package which has a MimeMessageParser class. With the parser you can get the content id (which could be used to identify the attachment) and attachments from the email message like so:
Session session = Session.getInstance(new Properties());
ByteArrayInputStream is = new ByteArrayInputStream(rawEmail.getBytes());
MimeMessage message = new MimeMessage(session, is);
MimeMessageParser parser = new MimeMessageParser(message);
// Once you have the parser, get the content ids and attachments:
List<DataSource> attachments = parser.getContentIds.stream
.map(id -> parser.findAttachmentByCid(id))
.filter(att -> att != null)
.collect(Collectors.toList());
I have created a list here for the sake of brevity, but instead, you could create a map with the contentId as the key and the DataSource as the value.
Take a look at some more examples for using the parser in java here, or some code I wrote for a scala project here.

Categories