org.alfresco.email.server.impl.subetha.SubethaEmailMessage.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.email.server.impl.subetha.SubethaEmailMessage.java

Source

/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.email.server.impl.subetha;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.internet.MimeMessage.RecipientType;

import org.alfresco.service.cmr.email.EmailMessage;
import org.alfresco.service.cmr.email.EmailMessageException;
import org.alfresco.service.cmr.email.EmailMessagePart;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/* 
 * TODO There's a lot of metadata extraction going on in this class that 
 * is duplicated by RFC822MetadataExtracter
 */

/**
 * Concrete representation of an email message as implemented for the SubEtha mail server.
 * 
 * @since 2.2
 */

public class SubethaEmailMessage implements EmailMessage {
    private static final String ERR_FAILED_TO_CREATE_MIME_MESSAGE = "email.server.err.failed_to_create_mime_message";
    private static final String ERR_EXTRACTING_FROM_ADDRESS = "email.server.err.extracting_from_address";
    private static final String ERR_NO_FROM_ADDRESS = "email.server.err.no_from_address";
    private static final String ERR_EXTRACTING_TO_ADDRESS = "email.server.err.extracting_to_address";
    private static final String ERR_NO_TO_ADDRESS = "email.server.err.no_to_address";
    private static final String ERR_EXTRACTING_SUBJECT = "email.server.err.extracting_subject";
    private static final String ERR_EXTRACTING_SENT_DATE = "email.server.err.extracting_sent_date";
    private static final String ERR_PARSE_MESSAGE = "email.server.err.parse_message";

    private static final long serialVersionUID = -3735187524926395261L;

    private static final Log log = LogFactory.getLog(SubethaEmailMessage.class);

    private static final String MIME_PLAIN_TEXT = "text/plain";
    private static final String MIME_HTML_TEXT = "text/html";
    private static final String MIME_XML_TEXT = "text/xml";
    private static final String MIME_APPLICATION = "application/*";
    private static final String MIME_IMAGE = "image/*";
    private static final String MIME_MULTIPART = "multipart/*";
    private static final String MIME_RFC822 = "message/rfc822";
    private static final String FILENAME_ATTACHMENT_PREFIX = "Attachment";

    private String from;
    private String to;
    private String subject;
    private List<String> cc;
    private Date sentDate;
    private EmailMessagePart body;
    private EmailMessagePart[] attachments;
    transient private int bodyNumber = 0;
    transient private int attachmentNumber = 0;
    transient private List<EmailMessagePart> attachmentList = new LinkedList<EmailMessagePart>();

    protected SubethaEmailMessage() {
        super();
    }

    public SubethaEmailMessage(MimeMessage mimeMessage) {
        processMimeMessage(mimeMessage);
    }

    public SubethaEmailMessage(InputStream dataInputStream) {
        MimeMessage mimeMessage = null;
        try {
            mimeMessage = new MimeMessage(Session.getDefaultInstance(System.getProperties()), dataInputStream);
        } catch (MessagingException e) {
            throw new EmailMessageException(ERR_FAILED_TO_CREATE_MIME_MESSAGE, e.getMessage());
        }

        processMimeMessage(mimeMessage);
    }

    private void processMimeMessage(MimeMessage mimeMessage) {
        if (from == null) {
            Address[] addresses = null;
            try {
                addresses = mimeMessage.getFrom();
            } catch (MessagingException e) {
                throw new EmailMessageException(ERR_EXTRACTING_FROM_ADDRESS, e.getMessage());
            }
            if (addresses == null || addresses.length == 0) {
                //throw new EmailMessageException(ERR_NO_FROM_ADDRESS);
            } else {
                if (addresses[0] instanceof InternetAddress) {
                    from = ((InternetAddress) addresses[0]).getAddress();
                } else {
                    from = addresses[0].toString();
                }
            }
        }

        if (to == null) {
            Address[] addresses = null;
            try {
                addresses = mimeMessage.getAllRecipients();
            } catch (MessagingException e) {
                throw new EmailMessageException(ERR_EXTRACTING_TO_ADDRESS, e.getMessage());
            }
            if (addresses == null || addresses.length == 0) {
                //throw new EmailMessageException(ERR_NO_TO_ADDRESS);
            } else {
                if (addresses[0] instanceof InternetAddress) {
                    to = ((InternetAddress) addresses[0]).getAddress();
                } else {
                    to = addresses[0].toString();
                }
            }
        }

        if (cc == null) {
            try {
                ArrayList<String> list = new ArrayList<String>();

                Address[] cca = mimeMessage.getRecipients(RecipientType.CC);

                if (cca != null) {
                    for (Address a : cca) {
                        list.add(a.toString());
                    }
                }
                cc = list;
            } catch (MessagingException e) {
                // Do nothing - this is not a show-stopper.
                cc = null;
            }
        }

        try {
            subject = mimeMessage.getSubject();
            //subject = encodeSubject(mimeMessage.getSubject());
        } catch (MessagingException e) {
            throw new EmailMessageException(ERR_EXTRACTING_SUBJECT, e.getMessage());
        }
        //if (subject == null)
        //{
        //    subject = ""; // Just anti-null stub :)
        //}

        try {
            sentDate = mimeMessage.getSentDate();
        } catch (MessagingException e) {
            throw new EmailMessageException(ERR_EXTRACTING_SENT_DATE, e.getMessage());
        }
        if (sentDate == null) {
            sentDate = new Date(); // Just anti-null stub :)
        }

        parseMessagePart(mimeMessage);
        attachments = new EmailMessagePart[attachmentList.size()];
        attachmentList.toArray(attachments);
        attachmentList = null;
    }

    private void parseMessagePart(Part messagePart) {
        try {
            if (messagePart.isMimeType(MIME_PLAIN_TEXT) || messagePart.isMimeType(MIME_HTML_TEXT)) {
                if (log.isDebugEnabled()) {
                    log.debug("Text or HTML part was found. ContentType: " + messagePart.getContentType());
                }
                addBody(messagePart);
            } else if (messagePart.isMimeType(MIME_XML_TEXT)) {
                if (log.isDebugEnabled()) {
                    log.debug("XML part was found.");
                }
                addAttachment(messagePart);
            } else if (messagePart.isMimeType(MIME_APPLICATION)) {
                if (log.isDebugEnabled()) {
                    log.debug("Application part was found.");
                }
                addAttachment(messagePart);
            } else if (messagePart.isMimeType(MIME_IMAGE)) {
                if (log.isDebugEnabled()) {
                    log.debug("Image part was found.");
                }
                addAttachment(messagePart);
            } else if (messagePart.isMimeType(MIME_MULTIPART)) {
                // if multipart, this method will be called recursively
                // for each of its parts
                Multipart mp = (Multipart) messagePart.getContent();
                int count = mp.getCount();

                if (log.isDebugEnabled()) {
                    log.debug("MULTIPART with " + count + " part(s) found. Processin each part...");
                }
                for (int i = 0; i < count; i++) {
                    BodyPart bp = mp.getBodyPart(i);
                    if (bp.getContent() instanceof MimeMultipart) {
                        // It's multipart.  Recurse.
                        parseMessagePart(bp);
                    } else {
                        // It's the body
                        addBody(bp);
                    }
                }

                if (log.isDebugEnabled()) {
                    log.debug("MULTIPART processed.");
                }

            } else if (messagePart.isMimeType(MIME_RFC822)) {
                // if rfc822, call this method with its content as the part
                if (log.isDebugEnabled()) {
                    log.debug("MIME_RFC822 part found. Processing inside part...");
                }

                parseMessagePart((Part) messagePart.getContent());

                if (log.isDebugEnabled()) {
                    log.debug("MIME_RFC822 processed.");
                }

            } else {
                // if all else fails, put this in the attachments map.
                // Actually we don't know what it is.
                if (log.isDebugEnabled()) {
                    log.debug("Unrecognized part was found. Put it into attachments.");
                }
                addAttachment(messagePart);
            }
        } catch (IOException e) {
            throw new EmailMessageException(ERR_PARSE_MESSAGE, e.getMessage());
        } catch (MessagingException e) {
            throw new EmailMessageException(ERR_PARSE_MESSAGE, e.getMessage());
        }
    }

    private void addBody(Part messagePart) throws MessagingException {
        if (body != null) {
            attachmentList.add(new SubethaEmailMessagePart(messagePart,
                    getPartFileName(getSubject() + " (part " + ++bodyNumber + ")", messagePart)));
            if (log.isInfoEnabled()) {
                log.info(String.format("Attachment \"%s\" has been added.",
                        attachmentList.get(attachmentList.size() - 1).getFileName()));
            }
        } else {
            body = new SubethaEmailMessagePart(messagePart, getPartFileName(getSubject(), messagePart));
            if (log.isDebugEnabled()) {
                log.debug("Body has been added.");
            }
        }

    }

    /**
     * Method adds a message part to the attachments list
     * 
     * @param messagePart A part of message
     * @throws EmailMessageException
     * @throws MessagingException
     */
    private void addAttachment(Part messagePart) throws MessagingException {
        String fileName = getPartFileName(FILENAME_ATTACHMENT_PREFIX + attachmentNumber, messagePart);
        attachmentList.add(new SubethaEmailMessagePart(messagePart, fileName));
        if (log.isDebugEnabled()) {
            log.debug("Attachment added: " + fileName);
        }
    }

    /**
     * Method extracts file name from a message part for saving its as aa attachment. If the file name can't be extracted, it will be generated based on defaultPrefix parameter.
     * 
     * @param defaultPrefix This prefix fill be used for generating file name.
     * @param messagePart A part of message
     * @return File name.
     * @throws MessagingException
     */
    private String getPartFileName(String defaultPrefix, Part messagePart) throws MessagingException {
        String fileName = messagePart.getFileName();
        if (fileName != null) {
            try {
                fileName = MimeUtility.decodeText(fileName);
            } catch (UnsupportedEncodingException ex) {
                // Nothing to do :)
            }
        } else {
            fileName = defaultPrefix;
            if (messagePart.isMimeType(MIME_PLAIN_TEXT))
                fileName += ".txt";
            else if (messagePart.isMimeType(MIME_HTML_TEXT))
                fileName += ".html";
            else if (messagePart.isMimeType(MIME_XML_TEXT))
                fileName += ".xml";
            else if (messagePart.isMimeType(MIME_IMAGE))
                fileName += ".gif";
        }
        return fileName;
    }

    public void setRmiRegistry(String rmiRegistryHost, int rmiRegistryPort) {
        if (body instanceof SubethaEmailMessagePart) {
            ((SubethaEmailMessagePart) body).setRmiRegistry(rmiRegistryHost, rmiRegistryPort);
        }

        for (EmailMessagePart attachment : attachments) {
            if (attachment instanceof SubethaEmailMessagePart) {
                ((SubethaEmailMessagePart) attachment).setRmiRegistry(rmiRegistryHost, rmiRegistryPort);
            }
        }
    }

    public List<String> getCC() {
        return cc;
    }

    public String getFrom() {
        return from;
    }

    public String getTo() {
        return to;
    }

    public Date getSentDate() {
        return sentDate;
    }

    public String getSubject() {
        return subject;
    }

    public EmailMessagePart getBody() {
        return body;
    }

    public EmailMessagePart[] getAttachments() {
        return attachments;
    }

}