Package org.apache.cocoon.mail

Source Code of org.apache.cocoon.mail.MailMessageSender

/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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 org.apache.cocoon.mail;

import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;

import org.apache.cocoon.mail.datasource.FilePartDataSource;
import org.apache.cocoon.mail.datasource.SourceDataSource;
import org.apache.cocoon.servlet.multipart.Part;

import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

/**
* A helper class used by the {@link org.apache.cocoon.acting.Sendmail}
* and the <code>sendmail.xsl</code> logicsheet for sending an email message.
*
* <h3>Configuration</h3>
* <table><tbody>
* <tr><th>smtp-host</th><td>SMTP server to use sending mail.</td><td>opt</td><td>String</td><td><code>localhost</code></td></tr>
* <tr><th>smtp-user</th><td>User name for authentication</td><td>opt</td><td>String</td></tr>
* <tr><th>smtp-password</th><td>Password for authentication</td><td>opt</td><td>String</td></tr>
* </tbody></table>
*
* @author <a href="mailto:frank.ridderbusch@gmx.de">Frank Ridderbusch</a>
* @author <a href="mailto:haul@apache.org">Christian Haul</a>
* @since 2.1
* @version CVS $Id: MailMessageSender.java 155031 2005-02-23 17:32:37Z vgritsenko $
*/
public class MailMessageSender
        extends AbstractLogEnabled
        implements MailSender, Configurable, Serviceable, Initializable, Component {

    private ServiceManager manager;

    private Session session;

    private String smtpHost;
    private String smtpUser;
    private String smtpPswd;

    private String from;
    private String to;
    private String replyTo;
    private String cc;
    private String bcc;
    private String subject;
    private String charset;
    private String src;
    private String srcMimeType;
    private String body;
    private List attachments;
    private Exception exception;

    /**
     * Helper class for attachment data.
     * @author haul
     * @since 2.1
     */
    private static class Attachment {
        private Object obj = null;
        private String type = null;
        private String name = null;
        protected boolean isURL = false;

        /**
         * Create a new attachment object encapsulating obj.
         * @param obj attachment
         */
        public Attachment(Object obj) {
            this(obj, null, null);
        }

        /**
         * Create a new attachment object encapsulating obj
         * @param obj attachment
         * @param type override mime type
         * @param name override attachment name
         */
        public Attachment(Object obj, String type, String name) {
            this(obj, type, name, false);
        }

        /**
         * Create a new attachment object encapsulating obj
         * @param obj attachment
         * @param type override mime type
         * @param name override attachment name
         * @param isURI obj is an instance of String and contains a URL
         */
        public Attachment(Object obj, String type, String name, boolean isURI) {
            this.obj = obj;
            this.type = type;
            this.name = name;
            this.isURL = isURI;
            if (isNullOrEmpty(this.type))
                this.type = null;
            if (isNullOrEmpty(this.name))
                this.name = null;
        }

        /**
         * Check String for null or empty.
         * @param str
         * @return true if str is null, empty string, or equals "null"
         */
        private boolean isNullOrEmpty(String str) {
            return (str == null || "".equals(str) || "null".equals(str));
        }

        /**
         * Is the encapsulated object a URL?
         * @return true if URL
         */
        public boolean isURL() {
            return this.isURL;
        }

        /**
         * Return attachment name. The argument overrides the stored name.
         * @param name
         * @return stored name or otherwise parameter
         */
        public String getName(String name) {
            return (this.name == null ? name : this.name);
        }

        /**
         * Return attachment type. The argument overrides the stored type.
         * @param type  attachment type
         * @return stored type or otherwise parameter
         */
        public String getType(String type) {
            return (this.type == null ? type : this.type);
        }

        /**
         * Returns encapsulated object
         */
        public Object getObject() {
            return this.obj;
        }
    }

    public MailMessageSender() {
    }

    /**
     * Creates a new instance of MailMessageSender
     * Keep constructor for backwards compatibility.
     * @param smtpHost The host name or ip-address of a host to accept
     *                 the email for delivery.
     * @deprecated Since 2.1.5. Please use {@link MailSender} component instead.
     */
    public MailMessageSender(String smtpHost) {
        smtpHost = smtpHost.trim();
        setSmtpHost(smtpHost);
        initialize();
    }

    public void service(ServiceManager manager) {
        this.manager = manager;
    }

    /* (non-Javadoc)
     * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
     */
    public void configure(Configuration config) throws ConfigurationException {
        this.smtpHost = config.getChild("smtp-host").getValue(null);
        this.smtpUser = config.getChild("smtp-user").getValue(null);
        this.smtpPswd = config.getChild("smtp-password").getValue(null);
    }

    /* (non-Javadoc)
     * @see org.apache.avalon.framework.activity.Initializable#initialize()
     */
    public void initialize() {
        initSession();
        this.attachments = new ArrayList();
    }

    private void initSession() {
        Properties properties = new Properties();
        if (smtpHost == null || smtpHost.equals("") || smtpHost.equals("null")) {
            properties.put("mail.smtp.host", "127.0.0.1");
        } else {
            properties.put("mail.smtp.host", smtpHost);
        }

        if (smtpUser == null || smtpUser.equals("") || smtpUser.equals("null")) {
            this.session = Session.getInstance(properties);
        } else {
            properties.put("mail.smtp.auth", "true");
            this.session = Session.getInstance(properties, new Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(smtpUser, smtpPswd);
                }
            });
        }
    }

    /* (non-Javadoc)
     * @see org.apache.cocoon.mail.MailSender#setSmtpHost(java.lang.String)
     */
    public void setSmtpHost(String hostname) {
        this.smtpHost = hostname;
        initSession();
    }

    public void setSmtpHost(String hostname, String username, String password) {
        this.smtpUser = username;
        this.smtpPswd = password;
        setSmtpHost(hostname);
    }


    /**
     * Assemble the message from the defined fields and send it.
     * @throws AddressException when problems with email addresses are found
     * @throws MessagingException when message could not be send.
     */
    public void send() throws AddressException, MessagingException {
        SourceResolver resolver = null;
        try {
            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
            doSend(resolver);
        } catch(ServiceException se) {
            throw new CascadingRuntimeException("Cannot get Source Resolver to send mail", se);
        } finally {
            this.manager.release(resolver);
        }
    }

    /**
     * Assemble the message from the defined fields and send it.
     * @throws AddressException when problems with email addresses are found
     * @throws MessagingException when message could not be send.
     * @deprecated Since 2.1.5. Use {@link #send()} which doesn't require passing the source resolver
     */
    public void send(org.apache.cocoon.environment.SourceResolver resolver)
    throws AddressException, MessagingException {
        // resolver is automatically down-casted
        doSend(resolver);
    }

    private void doSend(SourceResolver resolver)
    throws AddressException, MessagingException {
        final List sourcesList = new ArrayList();

        final MimeMessage message = new MimeMessage(this.session);

        if (this.from == null) {
            throw new AddressException("No from address");
        } else {
            try {
                message.setFrom(new InternetAddress(this.from));
            } catch (AddressException e) {
                throw new AddressException("Invalid from address: " + this.from + ": " +
                                           e.getMessage());
            }
        }

        if (this.to == null) {
            throw new AddressException("no to address");
        } else {
            try {
                message.setRecipients(RecipientType.TO,
                                      InternetAddress.parse(this.to));
            } catch (AddressException e) {
                throw new AddressException("Invalid to address: " + this.to + ": " +
                                           e.getMessage());
            }
        }

        if (this.replyTo != null) {
            try {
                message.setReplyTo(InternetAddress.parse(this.replyTo));
            } catch (AddressException e) {
                throw new AddressException("Invalid replyTo address: " + this.replyTo + ": " +
                                           e.getMessage());
            }
        }

        if (this.cc != null) {
            try {
                message.setRecipients(RecipientType.CC,
                                      InternetAddress.parse(this.cc));
            } catch (AddressException e) {
                throw new AddressException("Invalid cc address: " + this.cc + ": " +
                                           e.getMessage());
            }
        }

        if (this.bcc != null) {
            try {
                message.setRecipients(RecipientType.BCC,
                                      InternetAddress.parse(this.bcc));
            } catch (AddressException e) {
                throw new AddressException("Invalid bcc address: " + this.bcc + ": " +
                                           e.getMessage());
            }
        }

        if (this.subject != null) {
            message.setSubject(this.subject);
        }

        message.setSentDate(new Date());

        Attachment a = null;
        try {
            if (this.attachments.isEmpty()) {
                if (this.src != null) {
                    DataSource ds = null;

                    Source source = resolver.resolveURI(this.src);
                    sourcesList.add(source);
                    if (source.exists()) {
                        ds =
                            new SourceDataSource(
                                source,
                                (this.srcMimeType == null
                                    ? source.getMimeType()
                                    : this.srcMimeType),
                                this.src.substring(this.src.lastIndexOf('/') + 1));
                    }

                    message.setDataHandler(new DataHandler(ds));

                } else if (this.body != null) {
                    if (this.charset != null) {
                        message.setText(this.body, this.charset);
                    } else {
                        message.setText(this.body);
                    }
                }
            } else {
                Multipart multipart = new MimeMultipart();
                BodyPart bodypart = new MimeBodyPart();
                multipart.addBodyPart(bodypart);
                message.setContent(multipart);

                if (this.src != null) {
                    DataSource ds = null;

                    Source source = resolver.resolveURI(this.src);
                    sourcesList.add(source);
                    if (source.exists()) {
                        ds =
                            new SourceDataSource(
                                source,
                                (this.srcMimeType == null
                                    ? source.getMimeType()
                                    : this.srcMimeType),
                                this.src.substring(this.src.lastIndexOf('/') + 1));
                    }

                    bodypart.setDataHandler(new DataHandler(ds));
                    bodypart.setFileName(ds.getName());

                } else if (this.body != null) {
                    bodypart.setText(this.body);
                }

                for (Iterator i = this.attachments.iterator(); i.hasNext();) {
                    a = (Attachment) i.next();
                    DataSource ds = null;
                    if (a.isURL) {
                        String name = (String) a.getObject();
                        Source src = resolver.resolveURI(name);
                        sourcesList.add(src);
                        if (src.exists()) {
                            ds =
                                new SourceDataSource(
                                    src,
                                    a.getType(src.getMimeType()),
                                    a.getName(name.substring(name.lastIndexOf('/') + 1)));
                        }
                    } else {
                        if (a.getObject() instanceof Part) {
                            Part part = (Part) a.getObject();
                            ds =
                                new FilePartDataSource(
                                    part,
                                    a.getType(part.getMimeType()),
                                    a.getName(part.getUploadName()));
                        } else {
                            // TODO: other classes?
                            throw new AddressException("Not yet supported: " + a.getObject());
                        }
                    }

                    bodypart = new MimeBodyPart();
                    bodypart.setDataHandler(new DataHandler(ds));
                    bodypart.setFileName(ds.getName());
                    multipart.addBodyPart(bodypart);
                }
            }

            message.saveChanges();
            Transport.send(message);
        } catch (MessagingException me) {
            throw new MessagingException(me.getMessage());
        } catch (MalformedURLException e) {
            throw new AddressException("Malformed attachment URL: " +
                                       a.getObject() + " error " + e.getMessage());
        } catch (IOException e) {
            throw new AddressException("IOException accessing attachment URL: " +
                                       a.getObject() + " error " + e.getMessage());
        } finally {
            if (sourcesList != null) {
                for (Iterator j = sourcesList.iterator(); j.hasNext();) {
                    resolver.release((Source) j.next());
                }
            }
        }
    }

    /**
     * Invokes the {@link #send()} method but catches any exception thrown. This
     * method is intended to be used from the sendmail logicsheet.
     * @return true when successful
     */
    public boolean sendIt() {
        this.exception = null;
        try {
            send();
        } catch (Exception e) {
            this.exception = e;
        }
        return exception == null;
    }

    /**
     * Invokes the {@link #send(org.apache.cocoon.environment.SourceResolver)}
     * method but catches any exception thrown. This
     * method is intended to be used from the sendmail logicsheet.
     *
     * @return true when successful
     * @deprecated Since 2.1.5. Use {@link #sendIt()} which doesn't require passing the source resolver
     */
    public boolean sendIt(org.apache.cocoon.environment.SourceResolver resolver) {
        this.exception = null;
        try {
            send(resolver);
        } catch (Exception e) {
            this.exception = e;
        }
        return exception == null;
    }

    /**
     * Accesses any Exception caught by
     * {@link #sendIt(org.apache.cocoon.environment.SourceResolver)}.
     *
     * @return AddressException or MessagingException
     */
    public Exception getException() {
        return this.exception;
    }


    /**
     * Set the <CODE>from</CODE> address of the message.
     * @param from The address the message appears to be from.
     */
    public void setFrom(String from) {
        if (!("".equals(from) || "null".equals(from))) {
            this.from = from.trim();
        }
    }

    /**
     * Sets the destination address(es) for the message. The address
     * is in the format, that
     * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
     * (one or more email addresses separated by a commas).
     * @param to the destination address(es)
     * @see javax.mail.internet.InternetAddress#parse(String)
     */
    public void setTo(String to) {
        if (!("".equals(to) || "null".equals(to))) {
            this.to = to.trim();
        }
    }

    /**
     * Sets the reply-to address(es) for the message. The address
     * is in the format, that
     * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
     * (one or more email addresses separated by a commas).
     * @param replyTo the address(es) that replies should be sent to
     * @see javax.mail.internet.InternetAddress#parse(String)
     */
    public void setReplyTo(String replyTo) {
        if (!("".equals(replyTo) || "null".equals(replyTo))) {
            this.replyTo = replyTo.trim();
        }
    }

    /**
     * Sets the address(es), which should receive a carbon copy of the
     * message. The address is in the format, that
     * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
     * (one or more email addresses separated by a commas).
     * @param cc the address(es), which should receive a carbon copy.
     * @see javax.mail.internet.InternetAddress#parse(String)
     */
    public void setCc(String cc) {
        if (!("".equals(cc) || "null".equals(cc))) {
            this.cc = cc.trim();
        }
    }

    /**
     * Sets the address(es), which should receive a black carbon copy of
     * the message. The address is in the format, that
     * {@link javax.mail.internet.InternetAddress#parse(String)} can handle
     * (one or more email addresses separated by a commas).
     * @param bcc the address(es), which should receive a black carbon copy.
     * @see javax.mail.internet.InternetAddress#parse(String)
     */
    public void setBcc(String bcc) {
        if (!("".equals(bcc) || "null".equals(bcc))) {
            this.bcc = bcc.trim();
        }
    }

    /**
     * Sets the character set for encoding the message. This has no effect,
     * if any attachments are send in the message.
     * @param charset the character set to be used for enbcoding the message
     */
    public void setCharset(String charset) {
        if (!("".equals(charset) || "null".equals(charset))) {
            this.charset = charset.trim();
        }
    }

    /**
     * Sets the subject line of the message.
     * @param subject the subject line of the message
     */
    public void setSubject(String subject) {
        if (!("".equals(subject) || "null".equals(subject))) {
            this.subject = subject;
        }
    }

    /**
     * Sets the body text of the email message.
     * If both a text body and a body read from a source are set,
     * only the latter will be used.
     *
     * @param body The body text of the email message
     */
    public void setBody(String body) {
        if (!("".equals(body) || "null".equals(body))) {
            this.body = body;
        }
    }

    /**
     * Sets the body source URL of the email message.
     * If both a text body and a body read from a source are set,
     * only the latter will be used.
     *
     * @param src The body source URL of the email message
     */
    public void setBodyFromSrc(String src) {
        if (!("".equals(src) || "null".equals(src))) {
            this.src = src;
        }
    }

    /**
     * Sets the optional body source Mime Type of the email message.
     * @param srcMimeType The optional body source Mime Type of the email message
     */
    public void setBodyFromSrcMimeType(String srcMimeType) {
        if (!("".equals(srcMimeType) || "null".equals(srcMimeType))) {
            this.srcMimeType = srcMimeType;
        }
    }

    /**
     * Add an attachement to the message to be send. The attachment can
     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
     * {@link org.apache.cocoon.servlet.multipart.Part} or its
     * subclasses.
     * @param attachment to be send with the message
     * @see org.apache.excalibur.source.Source
     */
    public void addAttachment(Object attachment) {
        if (attachment != null) {
            attachments.add(new Attachment(attachment));
        }
    }

    /**
     * Add an attachement to the message to be send. The attachment can
     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
     * {@link org.apache.cocoon.servlet.multipart.Part} or its
     * subclasses.
     * @param attachment to be send with the message
     * @param type mime type (optional)
     * @param name attachment name (optional)
     * @see org.apache.excalibur.source.Source
     */
    public void addAttachment(Object attachment, String type, String name) {
        if (attachment != null) {
            attachments.add(new Attachment(attachment, type, name));
        }
    }

    /**
     * Add an attachement to the message to be send. The attachment can
     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
     * {@link org.apache.cocoon.servlet.multipart.Part} or its
     * subclasses.
     * @param url URL to attach to the message
     * @see org.apache.excalibur.source.Source
     */
    public void addAttachmentURL(String url) {
        if (url != null) {
            attachments.add(new Attachment(url, null, null, true));
        }
    }

    /**
     * Add an attachement to the message to be send. The attachment can
     * be of type <CODE>org.apache.excalibur.source.Source</CODE> or
     * {@link org.apache.cocoon.servlet.multipart.Part} or its
     * subclasses.
     * @param url URL to attach to the message
     * @param type mime type (optional)
     * @param name attachment name (optional)
     * @see org.apache.excalibur.source.Source
     */
    public void addAttachmentURL(String url, String type, String name) {
        if (url != null) {
            attachments.add(new Attachment(url, type, name, true));
        }
    }
}
TOP

Related Classes of org.apache.cocoon.mail.MailMessageSender

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.