Skip to content

Commit

Permalink
JAMES-1794 Handle attachments in alternative part
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphael Ouazana committed Jul 11, 2016
1 parent b87c939 commit 03be8a4
Show file tree
Hide file tree
Showing 3 changed files with 401 additions and 11 deletions.
Expand Up @@ -45,7 +45,7 @@


public class MessageParser { public class MessageParser {


private static final String MULTIPART_ALTERNATIVE = "multipart/alternative"; private static final String TEXT_MEDIA_TYPE = "text";
private static final String CONTENT_TYPE = "Content-Type"; private static final String CONTENT_TYPE = "Content-Type";
private static final String CONTENT_ID = "Content-ID"; private static final String CONTENT_ID = "Content-ID";
private static final String CONTENT_DISPOSITION = "Content-Disposition"; private static final String CONTENT_DISPOSITION = "Content-Disposition";
Expand All @@ -60,7 +60,8 @@ public List<MessageAttachment> retrieveAttachments(InputStream fullContent) thro
.getBody(); .getBody();
try { try {
if (body instanceof Multipart) { if (body instanceof Multipart) {
return listAttachments((Multipart)body); Multipart multipartBody = (Multipart)body;
return listAttachments(multipartBody, Context.fromSubType(multipartBody.getSubType()));
} else { } else {
return ImmutableList.of(); return ImmutableList.of();
} }
Expand All @@ -69,14 +70,14 @@ public List<MessageAttachment> retrieveAttachments(InputStream fullContent) thro
} }
} }


private List<MessageAttachment> listAttachments(Multipart multipart) throws IOException { private List<MessageAttachment> listAttachments(Multipart multipart, Context context) throws IOException {
ImmutableList.Builder<MessageAttachment> attachments = ImmutableList.builder(); ImmutableList.Builder<MessageAttachment> attachments = ImmutableList.builder();
MessageWriter messageWriter = new DefaultMessageWriter(); MessageWriter messageWriter = new DefaultMessageWriter();
for (Entity entity : multipart.getBodyParts()) { for (Entity entity : multipart.getBodyParts()) {
if (isMultipart(entity) && !isMainBody(entity)) { if (isMultipart(entity)) {
attachments.addAll(listAttachments((Multipart) entity.getBody())); attachments.addAll(listAttachments((Multipart) entity.getBody(), Context.fromEntity(entity)));
} else { } else {
if (isAttachment(entity)) { if (isAttachment(entity, context)) {
attachments.add(retrieveAttachment(messageWriter, entity)); attachments.add(retrieveAttachment(messageWriter, entity));
} }
} }
Expand Down Expand Up @@ -152,10 +153,6 @@ private boolean isMultipart(Entity entity) {
return entity.isMultipart() && entity.getBody() instanceof Multipart; return entity.isMultipart() && entity.getBody() instanceof Multipart;
} }


private boolean isMainBody(Entity entity) {
return entity.getMimeType().equalsIgnoreCase(MULTIPART_ALTERNATIVE);
}

private boolean isInline(Optional<ContentDispositionField> contentDispositionField) { private boolean isInline(Optional<ContentDispositionField> contentDispositionField) {
return contentDispositionField.transform(new Function<ContentDispositionField, Boolean>() { return contentDispositionField.transform(new Function<ContentDispositionField, Boolean>() {
@Override @Override
Expand All @@ -165,7 +162,10 @@ public Boolean apply(ContentDispositionField field) {
}).or(false); }).or(false);
} }


private boolean isAttachment(Entity part) { private boolean isAttachment(Entity part, Context context) {
if (context == Context.BODY && isTextPart(part)) {
return false;
}
return Optional.fromNullable(part.getDispositionType()) return Optional.fromNullable(part.getDispositionType())
.transform(new Function<String, Boolean>() { .transform(new Function<String, Boolean>() {


Expand All @@ -176,9 +176,51 @@ public Boolean apply(String dispositionType) {
}).isPresent(); }).isPresent();
} }


private boolean isTextPart(Entity part) {
Optional<ContentTypeField> contentTypeField = getContentTypeField(part);
if (contentTypeField.isPresent()) {
String mediaType = contentTypeField.get().getMediaType();
if (mediaType != null && mediaType.equals(TEXT_MEDIA_TYPE)) {
return true;
}
}
return false;
}

private byte[] getBytes(MessageWriter messageWriter, Body body) throws IOException { private byte[] getBytes(MessageWriter messageWriter, Body body) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
messageWriter.writeBody(body, out); messageWriter.writeBody(body, out);
return out.toByteArray(); return out.toByteArray();
} }

private static enum Context {
BODY,
OTHER;

private static final String ALTERNATIVE_SUB_TYPE = "alternative";
private static final String MULTIPART_ALTERNATIVE = "multipart/" + ALTERNATIVE_SUB_TYPE;

public static Context fromEntity(Entity entity) {
if (isMultipartAlternative(entity)) {
return BODY;
}
return OTHER;
}

public static Context fromSubType(String subPart) {
if (isAlternative(subPart)) {
return BODY;
}
return OTHER;
}

private static boolean isMultipartAlternative(Entity entity) {
return entity.getMimeType().equalsIgnoreCase(MULTIPART_ALTERNATIVE);
}

private static boolean isAlternative(String subPart) {
return subPart.equalsIgnoreCase(ALTERNATIVE_SUB_TYPE);
}

}
} }
Expand Up @@ -161,4 +161,11 @@ public void getAttachementsShouldRetrieveHtmlAttachementsWhenSome() throws Excep


assertThat(attachments).hasSize(1); assertThat(attachments).hasSize(1);
} }

@Test
public void getAttachementsShouldRetrieveAttachmentsWhenSomeAreInTheMultipartAlternative() throws Exception {
List<MessageAttachment> attachments = testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/invitationEmailFromOP.eml"));

assertThat(attachments).hasSize(6);
}
} }

0 comments on commit 03be8a4

Please sign in to comment.