/******************************************************************************* * Copyright (c) 2011 - 2012 Siamak Haschemi & Benjamin Haupt * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package de.bht.fpa.mail.s000000.common.mail.imapsync; import static de.bht.fpa.mail.s000000.common.mail.model.builder.Builders.newAttachmentBuilder; import static de.bht.fpa.mail.s000000.common.mail.model.builder.Builders.newMessageBuilder; import static de.bht.fpa.mail.s000000.common.mail.model.builder.Builders.newRecipientBuilder; import static de.bht.fpa.mail.s000000.common.mail.model.builder.Builders.newSenderBuilder; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.mail.Address; import javax.mail.BodyPart; import javax.mail.Flags; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.UIDFolder; import javax.mail.internet.InternetAddress; import org.apache.commons.codec.binary.Base64; import com.sun.mail.imap.IMAPFolder; import de.bht.fpa.mail.s000000.common.mail.model.Importance; import de.bht.fpa.mail.s000000.common.mail.model.Message; import de.bht.fpa.mail.s000000.common.mail.model.RecipientType; import de.bht.fpa.mail.s000000.common.mail.model.builder.MessageBuilder; /** * This class is responsible for converting Java Mail Message Objects (coming * from IMAP or POP3 accounts) to our own {@link Message} objects. * * @author Siamak Haschemi */ public final class MessageConverter { private static final String X_PRIORITY = "X-Priority"; private static final Pattern X_PRIORITY_VALUE_PATTERN = Pattern.compile("(\\d).*"); private static final int X_PRIORITY_HIGH_END = 4; private static final int X_PRIORITY_HIGH_START = 2; private static final Map<RecipientType, javax.mail.Message.RecipientType> recipientType = new HashMap<RecipientType, javax.mail.Message.RecipientType>(); public MessageConverter() { recipientType.put(RecipientType.TO, javax.mail.Message.RecipientType.TO); recipientType.put(RecipientType.CC, javax.mail.Message.RecipientType.CC); recipientType.put(RecipientType.BCC, javax.mail.Message.RecipientType.BCC); } /** * Converts a javax {@link javax.mail.Message} to a {@link Message}. * * @param uidFolder * the {@link UIDFolder} (i.e. the {@link IMAPFolder} to obtain the * UID of the message from * @param javaMailMessage * the {@link javax.mail.Message} to convert * @return the converted {@link Message}, or <code>null</code> if conversion * failed. * @throws MessageConversionException */ public Message convertJavaxMessage(UIDFolder uidFolder, javax.mail.Message javaMailMessage) throws MessageConversionException { try { // @formatter:off MessageBuilder messageBuilder = newMessageBuilder(); messageBuilder .id(convertId(uidFolder, javaMailMessage)) .subject(convertSubject(javaMailMessage)) .received(convertReceived(javaMailMessage)) .sent(convertSent(javaMailMessage)) .read(convertRead(javaMailMessage)) .importance(convertImportance(javaMailMessage)); convertContent(javaMailMessage.getContent(), messageBuilder); convertRecipients(javaMailMessage, messageBuilder); convertSender(javaMailMessage, messageBuilder); return messageBuilder.build(); // @formatter:on } catch (Exception e) { throw new MessageConversionException("Could not convert message " + javaMailMessage, e); } } private static long convertId(UIDFolder uidFolder, javax.mail.Message javaMailMessage) throws MessagingException { return uidFolder.getUID(javaMailMessage); } private static String convertSubject(javax.mail.Message javaMailMessage) throws MessagingException { return javaMailMessage.getSubject(); } private static Date convertReceived(javax.mail.Message javaMailMessage) throws MessagingException { return javaMailMessage.getReceivedDate(); } private static Date convertSent(javax.mail.Message javaMailMessage) throws MessagingException { return javaMailMessage.getSentDate(); } private static boolean convertRead(javax.mail.Message javaMailMessage) throws MessagingException { return javaMailMessage.isSet(Flags.Flag.SEEN); } private static void convertSender(javax.mail.Message javaMailMessage, MessageBuilder messageBuilder) throws MessagingException { Address[] from = javaMailMessage.getFrom(); if (from == null || from.length <= 0) { return; } Address firstFrom = from[0]; if (!(firstFrom instanceof InternetAddress)) { return; } InternetAddress internetAddress = (InternetAddress) firstFrom; messageBuilder.sender(newSenderBuilder().email(internetAddress.getAddress()) .personal(internetAddress.getPersonal())); } private static void convertRecipients(javax.mail.Message javaMailMessage, MessageBuilder messageBuilder) throws MessagingException { for (RecipientType type : RecipientType.values()) { addRecipients(messageBuilder, type, javaMailMessage.getRecipients(recipientType.get(type))); } } private static void addRecipients(MessageBuilder messageBuilder, RecipientType recipientType, Address[] recipients) { if (recipients == null) { return; } for (Address address : recipients) { if (!(address instanceof InternetAddress)) { continue; } InternetAddress internetAddress = (InternetAddress) address; // @formatter:off messageBuilder.recipient( newRecipientBuilder() .email(internetAddress.getAddress()) .personal(internetAddress.getPersonal()) .type(recipientType) ); // @formatter:on } } private static Importance convertImportance(javax.mail.Message javaMailMessage) throws MessagingException { Importance handleImportanceBasedOnXPriority = handleImportanceBasedOnXPriority(javaMailMessage); if (handleImportanceBasedOnXPriority != null) { return handleImportanceBasedOnXPriority; } Importance handleImportanceBasedOnXMSMailPriority = handleImportanceBasedOnXMSMailPriority(javaMailMessage); if (handleImportanceBasedOnXMSMailPriority != null) { return handleImportanceBasedOnXMSMailPriority; } Importance handleImportance = handleImportance(javaMailMessage); if (handleImportance != null) { return handleImportance; } return Importance.NORMAL; } private static Importance handleImportance(javax.mail.Message javaMailMessage) throws MessagingException { String[] header = javaMailMessage.getHeader("Importance"); if (header == null) { return null; } for (String entry : header) { if (entry.equals("high")) { return Importance.HIGH; } if (entry.equals("normal")) { return Importance.NORMAL; } if (entry.equals("low")) { return Importance.LOW; } } return null; } private static Importance handleImportanceBasedOnXMSMailPriority(javax.mail.Message javaMailMessage) throws MessagingException { String[] header = javaMailMessage.getHeader("X-MSMail-Priority"); if (header == null) { return null; } for (String entry : header) { if (entry.equals("High")) { return Importance.HIGH; } if (entry.equals("Normal")) { return Importance.NORMAL; } if (entry.equals("Low")) { return Importance.LOW; } } return null; } private static Importance handleImportanceBasedOnXPriority(javax.mail.Message javaMailMessage) throws MessagingException { String[] header = javaMailMessage.getHeader(X_PRIORITY); if (header == null) { return null; } for (String entry : header) { Matcher matcher = X_PRIORITY_VALUE_PATTERN.matcher(entry); if (!matcher.matches()) { continue; } Integer flag = Integer.valueOf(matcher.group(1)); if (flag < X_PRIORITY_HIGH_START) { return Importance.HIGH; } if (X_PRIORITY_HIGH_START <= flag && flag <= X_PRIORITY_HIGH_END) { return Importance.NORMAL; } if (flag > X_PRIORITY_HIGH_END) { return Importance.LOW; } } return null; } private static void convertContent(Object content, MessageBuilder messageBuilder) throws MessagingException, IOException { handleContent(content, null, messageBuilder); } private static void handleContent(Object content, BodyPart bodyPart, MessageBuilder messageBuilder) throws MessagingException, IOException { if (content instanceof String) { handleText(content, messageBuilder); } else if (content instanceof Multipart) { handleMultipart((Multipart) content, messageBuilder); } else if (content instanceof InputStream) { handleInputStream((InputStream) content, bodyPart, messageBuilder); } } private static void handleInputStream(InputStream content, BodyPart bodyPart, MessageBuilder messageBuilder) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { int thisLine; while ((thisLine = content.read()) != -1) { bos.write(thisLine); } bos.flush(); byte[] bytes = bos.toByteArray(); bos.close(); String encodeBase64String = new String(Base64.encodeBase64(bytes)); // @formatter:off messageBuilder.attachment( newAttachmentBuilder() .fileName(bodyPart.getFileName()) .body(encodeBase64String) ); // @formatter:on } catch (Exception e) { // ignore return; } } private static void handleText(Object content, MessageBuilder messageBuilder) { messageBuilder.text((String) content); } private static void handleMultipart(Multipart content, MessageBuilder messageBuilder) throws MessagingException, IOException { for (int i = 0; i < content.getCount(); i++) { BodyPart bodyPart = content.getBodyPart(i); handleContent(bodyPart.getContent(), bodyPart, messageBuilder); } } }