Package com.alibaba.citrus.service.mail.builder

Source Code of com.alibaba.citrus.service.mail.builder.MailBuilder

/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.citrus.service.mail.builder;

import static com.alibaba.citrus.service.mail.MailConstant.*;
import static com.alibaba.citrus.service.mail.builder.MailAddressType.*;
import static com.alibaba.citrus.util.ArrayUtil.*;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.BasicConstant.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static com.alibaba.citrus.util.ObjectUtil.*;
import static com.alibaba.citrus.util.StringUtil.*;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import com.alibaba.citrus.service.mail.MailService;
import com.alibaba.citrus.service.mail.util.MailUtil;
import com.alibaba.citrus.util.ToStringBuilder;
import com.alibaba.citrus.util.ToStringBuilder.MapBuilder;

/**
* 创建一个javamail对象的工具类。
* <p>
* <code>MailBuilder</code>对象是有状态的,不能被多个线程同时使用。
* </p>
*
* @author Michael Zhou
*/
public class MailBuilder implements Cloneable {
    private           MailService            mailService;
    private final     Set<InternetAddress>[] addresses;
    private final     Map<String, Object>    attributes;
    private           String                 id;
    private           String                 charset;
    private           String                 subject;
    private           Date                   sentDate;
    private           MailContent            content;
    private transient Session                session;

    @SuppressWarnings("unchecked")
    public MailBuilder() {
        this.addresses = (Set<InternetAddress>[]) new Set<?>[MailAddressType.values().length];
        this.attributes = createHashMap();
    }

    /** 深度复制一个mail builder。 */
    @Override
    public MailBuilder clone() {
        MailBuilder copy = new MailBuilder();

        copy.mailService = mailService;
        copy.id = id;
        copy.charset = charset;

        for (int i = 0; i < addresses.length; i++) {
            Set<InternetAddress> addrSet = addresses[i];

            if (addrSet != null && !addrSet.isEmpty()) {
                copy.addresses[i] = createLinkedHashSet(addrSet);
            }
        }

        copy.attributes.putAll(attributes);
        copy.subject = subject;
        copy.sentDate = sentDate;

        if (content != null) {
            copy.setContent(content.clone());
        }

        return copy;
    }

    /** 取得此mail builder所属的service。 */
    public MailService getMailService() {
        return mailService;
    }

    /** 设置此mail builder所属的service。 */
    public void setMailService(MailService mailService) {
        this.mailService = mailService;
    }

    /** 取得mail builder的ID。 */
    public String getId() {
        return id;
    }

    /** 设置mail builder的ID。 */
    public void setId(String id) {
        this.id = trimToNull(id);
    }

    /**
     * 取得当前mail builder的session。
     * <p>
     * 只有在build阶段方可得到此值。
     * </p>
     */
    public Session getSession() {
        return assertNotNull(session, ExceptionType.ILLEGAL_STATE, "Not in build time");
    }

    /** 取得邮件的主题。 */
    public String getSubject() {
        return subject;
    }

    /** 设置邮件的主题。 */
    public void setSubject(String subject) {
        this.subject = trimToNull(subject);
    }

    /** 取得生成邮件时使用的编码字符集。如果未指定,则返回默认字符集<code>UTF-8</code>。 */
    public String getCharacterEncoding() {
        return getDefaultCharsetIfNull(charset);
    }

    /** 设置生成邮件时使用的编码字符集。 */
    public void setCharacterEncoding(String javaCharset) {
        javaCharset = trimToNull(javaCharset);

        String oldCharset = getCharacterEncoding();
        String newCharset = getDefaultCharsetIfNull(javaCharset);

        if (!oldCharset.equals(newCharset)) {
            this.charset = javaCharset;
            updateAddressCharset(newCharset);
        }
    }

    private void updateAddressCharset(String newCharset) {
        String mimeCharset = MimeUtility.mimeCharset(newCharset);

        for (Set<InternetAddress> addrSet : addresses) {
            if (addrSet != null) {
                for (InternetAddress addr : addrSet) {
                    try {
                        addr.setPersonal(addr.getPersonal(), mimeCharset);
                    } catch (UnsupportedEncodingException e) {
                        invalidCharset(newCharset, e);
                    }
                }
            }
        }
    }

    private static String getDefaultCharsetIfNull(String charset) {
        return defaultIfNull(charset, DEFAULT_CHARSET);
    }

    /** 取得指定类型的所有地址。如果未设置该类型的地址,则返回空数组。 */
    public InternetAddress[] getAddresses(MailAddressType addrType) {
        Set<InternetAddress> addrSet = getAddressSet(addrType, false);

        if (addrSet == null) {
            return new InternetAddress[0];
        } else {
            return addrSet.toArray(new InternetAddress[addrSet.size()]);
        }
    }

    /** 添加邮件地址。 */
    public void addAddress(MailAddressType addrType, String addrList) throws InvalidAddressException {
        if (isEmpty(addrList)) {
            return;
        }

        InternetAddress[] addrs;
        String javaCharset = getCharacterEncoding();

        try {
            addrs = MailUtil.parse(addrList, javaCharset);
        } catch (AddressException e) {
            throw new InvalidAddressException("Invalid mail address: " + addrList, e);
        } catch (UnsupportedEncodingException e) {
            invalidCharset(javaCharset, e);
            return;
        }

        Set<InternetAddress> addrSet = getAddressSet(addrType, true);

        for (InternetAddress addr : addrs) {
            addrSet.add(addr);
        }
    }

    /**
     * 设置邮件地址。
     * <p>
     * 和<code>addAddress</code>方法不同,该方法清除原有的地址。
     * </p>
     */
    public void setAddress(MailAddressType addrType, String addr) throws InvalidAddressException {
        getAddressSet(addrType, true).clear();
        addAddress(addrType, addr);
    }

    /** 取得邮件内容。 */
    public MailContent getContent() {
        return content;
    }

    /**
     * 取得指定ID的content。
     * <p>
     * 如果content未指定ID,则无法找到。
     * </p>
     * <p>
     * 如果和ID对应的content实例未找到,则返回<code>null</code>
     * </p>
     */
    public MailContent getContent(String id) {
        return findContent(trimToNull(id), content);
    }

    /** 设置邮件内容。 */
    public void setContent(MailContent content) {
        MailContent oldContent = this.content;

        this.content = content;
        this.content.setMailBuilder(this);

        if (oldContent != null) {
            oldContent.setMailBuilder(null);
        }
    }

    /** 取得发信日期,如果未设置,则取得当前时间。 */
    public Date getSentDate() {
        if (sentDate == null) {
            sentDate = new Date();
        }

        return sentDate;
    }

    /** 设置发信日期。 */
    public void setSentDate(Date sentDate) {
        this.sentDate = sentDate;
    }

    /** 取得绑定的对象。 */
    public Object getAttribute(String key) {
        return attributes.get(key);
    }

    /** 取得attributes的key集合。 */
    public Set<String> getAttributeKeys() {
        return attributes.keySet();
    }

    /** 绑定指定的对象。 */
    public void setAttribute(String key, Object object) {
        if (object == null) {
            attributes.remove(key);
        } else {
            attributes.put(key, object);
        }
    }

    /** 批量绑定对象。 */
    public void setAttributes(Map<String, Object> attrs) {
        attributes.putAll(attrs);
    }

    /** 转换成javamail邮件对象。 */
    public MimeMessage getMessage(Session session) throws MailBuilderException {
        this.session = assertNotNull(session, "session");

        MimeMessage message = new MimeMessage(session);

        try {
            if (content != null) {
                content.render(message);
            } else {
                message.setContent(EMPTY_STRING, "text/plain");
            }
        } catch (MessagingException e) {
            throw new MailBuilderException("Failed to render content", e);
        }

        try {
            // from addresses
            message.addFrom(getAddresses(FROM));

            // recipients addresses
            message.setRecipients(Message.RecipientType.TO, getAddresses(TO));
            message.setRecipients(Message.RecipientType.CC, getAddresses(CC));
            message.setRecipients(Message.RecipientType.BCC, getAddresses(BCC));

            // reply to addresses
            message.setReplyTo(getAddresses(REPLY_TO));

            // subject
            message.setSubject(MailUtil.encodeHeader(getSubject(), getCharacterEncoding()));

            // sent date
            message.setSentDate(getSentDate());
        } catch (MessagingException e) {
            throw new MailBuilderException("Failed to create javamail message", e);
        } catch (UnsupportedEncodingException e) {
            invalidCharset(getCharacterEncoding(), e);
            return null;
        }

        return message;
    }

    /** 将javamail邮件对象转换成文本形式,其格式为标准的<code>.eml</code>格式。 */
    public String getMessageAsString(Session session) throws MailBuilderException {
        Message message = getMessage(session);

        try {
            return MailUtil.toString(message, getCharacterEncoding());
        } catch (UnsupportedEncodingException e) {
            invalidCharset(getCharacterEncoding(), e);
            return null;
        } catch (MessagingException e) {
            throw new MailBuilderException(e);
        }
    }

    /** 将javamail邮件对象输出到指定流中。 */
    public void writeTo(OutputStream ostream, Session session) throws MailBuilderException, IOException {
        Message message = getMessage(session);

        try {
            message.writeTo(ostream);
        } catch (MessagingException e) {
            throw new MailBuilderException(e);
        }
    }

    /**
     * 取得指定类型的邮件地址集合。
     * <p>
     * 如果该类型地址不存在,返回<code>null</code>。假如<code>create==true</code>,则会自动创建集合。
     * </p>
     */
    private Set<InternetAddress> getAddressSet(MailAddressType addrType, boolean create) {
        assertNotNull(addrType, "addressType");

        int index = addrType.ordinal();
        assertTrue(index < addresses.length, "internal state inconsistent");

        Set<InternetAddress> addrSet = addresses[index];

        if (addrSet == null && create) {
            addrSet = createLinkedHashSet();
            addresses[index] = addrSet;
        }

        return addrSet;
    }

    /** 递归查找指定ID的content。 */
    private MailContent findContent(String id, MailContent content) {
        MailContent result = null;

        if (id != null && content != null) {
            String contentId = content.getId();

            if (id.equals(contentId)) {
                result = content;
            } else if (content instanceof Multipart) {
                for (MailContent subcontent : ((Multipart) content).getContents()) {
                    result = findContent(id, subcontent);

                    if (result != null) {
                        break;
                    }
                }
            }
        }

        return result;
    }

    private void invalidCharset(String charset, UnsupportedEncodingException e) {
        StringBuilder message = new StringBuilder();
        String id = getId();

        message.append("Invalid charset \"").append(charset).append("\"");

        if (!isEmpty(id)) {
            message.append(" specified at mail (id=\"").append(id).append("\")");
        }

        throw new MailBuilderException(message.toString(), e);
    }

    @Override
    public String toString() {
        MapBuilder mb = new MapBuilder();

        if (getId() != null) {
            mb.append("id", getId());
        }

        mb.append("subject", getSubject());
        mb.append("charset", getCharacterEncoding());
        mb.append("sentDate", sentDate); // don't use getSentDate()

        for (MailAddressType addrType : MailAddressType.values()) {
            InternetAddress[] addrs = getAddresses(addrType);

            if (isEmptyArray(addrs)) {
                mb.append(addrType.name(), EMPTY_STRING);
            } else if (addrs.length == 1) {
                mb.append(addrType.name(), addrs[0]);
            } else {
                mb.append(addrType.name(), addrs);
            }
        }

        mb.append("attributes", attributes);
        mb.append("content", content);

        return new ToStringBuilder().append(getClass().getSimpleName()).append(mb).toString();
    }
}
TOP

Related Classes of com.alibaba.citrus.service.mail.builder.MailBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.