    001    package org.apache.turbine.util.velocity;
    002
    003
    004    /*
    005     * Licensed to the Apache Software Foundation (ASF) under one
    006     * or more contributor license agreements.  See the NOTICE file
    007     * distributed with this work for additional information
    008     * regarding copyright ownership.  The ASF licenses this file
    009     * to you under the Apache License, Version 2.0 (the
    010     * "License"); you may not use this file except in compliance
    011     * with the License.  You may obtain a copy of the License at
    012     *
    013     *   http://www.apache.org/licenses/LICENSE-2.0
    014     *
    015     * Unless required by applicable law or agreed to in writing,
    016     * software distributed under the License is distributed on an
    017     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    018     * KIND, either express or implied.  See the License for the
    019     * specific language governing permissions and limitations
    020     * under the License.
    021     */
    022
    023    import org.apache.commons.lang.StringUtils;
    024    import org.apache.commons.lang.WordUtils;
    025    import org.apache.commons.logging.Log;
    026    import org.apache.commons.logging.LogFactory;
    027    import org.apache.commons.mail.EmailException;
    028    import org.apache.commons.mail.SimpleEmail;
    029    import org.apache.turbine.Turbine;
    030    import org.apache.turbine.TurbineConstants;
    031    import org.apache.turbine.services.velocity.TurbineVelocity;
    032    import org.apache.velocity.context.Context;
    033
    034    /**
    035     * This is a simple class for sending email from within Velocity.
    036     * Essentially, the body of the email is processed with a
    037     * Velocity Context object.
    038     * The beauty of this is that you can send email from within your
    039     * Velocity template or from your business logic in your Java code.
    040     * The body of the email is just a Velocity template so you can use
    041     * all the template functionality of Velocity within your emails!
    042     *
    043     * <p>Example Usage (This all needs to be on one line in your
    044     * template):
    045     *
    046     * <p>Setup your context:
    047     *
    048     * <p><code>context.put ("VelocityEmail", new VelocityEmail() );</code>
    049     *
    050     * <p>Then, in your template:
    051     *
    052     * <pre>
    053     * $VelocityEmail.setTo("Jon Stevens", "jon@latchkey.com")
    054     *     .setFrom("Mom", "mom@mom.com").setSubject("Eat dinner")
    055     *     .setTemplate("email/momEmail.vm")
    056     *     .setContext($context)
    057     * </pre>
    058     *
    059     * The email/momEmail.wm template will then be parsed with the
    060     * Context that was defined with setContext().
    061     *
    062     * <p>If you want to use this class from within your Java code all you
    063     * have to do is something like this:
    064     *
    065     * <pre>
    066     * VelocityEmail ve = new VelocityEmail();
    067     * ve.setTo("Jon Stevens", "jon@latchkey.com");
    068     * ve.setFrom("Mom", "mom@mom.com").setSubject("Eat dinner");
    069     * ve.setContext(context);
    070     * ve.setTemplate("email/momEmail.vm")
    071     * ve.send();
    072     * </pre>
    073     *
    074     * <p>(Note that when used within a Velocity template, the send method
    075     * will be called for you when Velocity tries to convert the
    076     * VelocityEmail to a string by calling toString()).</p>
    077     *
    078     * <p>If you need your email to be word-wrapped, you can add the
    079     * following call to those above:
    080     *
    081     * <pre>
    082     * ve.setWordWrap (60);
    083     * </pre>
    084     *
    085     * <p>This class is just a wrapper around the SimpleEmail class from
    086     * commons-mail using the JavaMail API.
    087     * Thus, it depends on having the
    088     * mail.server property set in the TurbineResources.properties file.
    089     * If you want to use this class outside of Turbine for general
    090     * processing that is also possible by making sure to set the path to
    091     * the TurbineResources.properties.  See the
    092     * TurbineConfig class for more information.</p>
    093     *
    094     * <p>You can turn on debugging for the JavaMail API by calling
    095     * setDebug(true).  The debugging messages will be written to System.out.
    096     *
    097     * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
    098     * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
    099     * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    100     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    101     * @version $Id: VelocityEmail.java 1078552 2011-03-06 19:58:46Z tv $
    102     */
    103    public class VelocityEmail extends SimpleEmail
    104    {
    105        /** Logging */
    106        private static Log log = LogFactory.getLog(VelocityEmail.class);
    107
    108        /** The column to word-wrap at.  <code>0</code> indicates no wrap. */
    109        private int wordWrap = 0;
    110
    111        /** Address of outgoing mail server */
    112        private String mailServer;
    113
    114        /** The template to process, relative to Velocity template directory. */
    115        private String template = null;
    116
    117        /** Velocity context */
    118        private Context context = null;
    119
    120        /**
    121         * Constructor
    122         */
    123        public VelocityEmail()
    124        {
    125            super();
    126        }
    127
    128        /**
    129         * Constructor
    130         */
    131        public VelocityEmail(Context context)
    132        {
    133            this();
    134            this.context = context;
    135        }
    136
    137        /**
    138         * To: toName, toEmail
    139         *
    140         * @param toName A String with the TO toName.
    141         * @param toEmail A String with the TO toEmail.
    142         * @deprecated use addTo(email,name) instead
    143         * @throws EmailException email address could not be parsed
    144         * @return A VelocityEmail (self).
    145         */
    146        @Deprecated
    147        public VelocityEmail setTo(String toName, String toEmail)
    148                throws EmailException
    149        {
    150            addTo(toEmail,toName);
    151            return this;
    152        }
    153
    154        /**
    155         * Velocity template to execute. Path is relative to the Velocity
    156         * templates directory.
    157         *
    158         * @param template relative path of the template to parse including the
    159         *                 filename.
    160         * @return A VelocityEmail (self).
    161         */
    162        public VelocityEmail setTemplate(String template)
    163        {
    164            this.template = template;
    165            return this;
    166        }
    167
    168        /**
    169         * Set the column at which long lines of text should be word-
    170         * wrapped. Setting to zero turns off word-wrap (default).
    171         *
    172         * NOTE: don't use tabs in your email template document,
    173         * or your word-wrapping will be off for the lines with tabs
    174         * in them.
    175         *
    176         * @param wordWrap The column at which to wrap long lines.
    177         * @return A VelocityEmail (self).
    178         */
    179        public VelocityEmail setWordWrap(int wordWrap)
    180        {
    181            this.wordWrap = wordWrap;
    182            return this;
    183        }
    184
    185        /**
    186         * Set the context object that will be merged with the
    187         * template.
    188         *
    189         * @param context A Velocity context object.
    190         * @return A VelocityEmail (self).
    191         */
    192        public VelocityEmail setContext(Context context)
    193        {
    194            this.context = context;
    195            return this;
    196        }
    197
    198        /**
    199         * Get the context object that will be merged with the
    200         * template.
    201         *
    202         * @return A Context (self).
    203         */
    204        public Context getContext()
    205        {
    206            return this.context;
    207        }
    208
    209        /**
    210         * Sets the address of the outgoing mail server.  This method
    211         * should be used when you need to override the value stored in
    212         * TR.props.
    213         *
    214         * @param serverAddress host name of your outgoing mail server
    215         */
    216        public void setMailServer(String serverAddress)
    217        {
    218            this.mailServer = serverAddress;
    219        }
    220
    221        /**
    222         * Gets the host name of the outgoing mail server.  If the server
    223         * name has not been set by calling setMailServer(), the value
    224         * from TR.props for mail.server will be returned.  If TR.props
    225         * has no value for mail.server, localhost will be returned.
    226         *
    227         * @return host name of the mail server.
    228         */
    229        public String getMailServer()
    230        {
    231            return StringUtils.isNotEmpty(mailServer) ? mailServer
    232                    : Turbine.getConfiguration().getString(
    233                    TurbineConstants.MAIL_SERVER_KEY,
    234                    TurbineConstants.MAIL_SERVER_DEFAULT);
    235        }
    236
    237        /**
    238         * This method sends the email.
    239         * <p>If the mail server was not set by calling, setMailServer()
    240         * the value of mail.server will be used from TR.props.  If that
    241         * value was not set, localhost is used.
    242         *
    243         * @throws EmailException Failure during merging the velocity
    244         * template or sending the email.
    245         */
    246        @Override
    247        public String send() throws EmailException
    248        {
    249            String body = null;
    250            try
    251            {
    252                // Process the template.
    253                body = TurbineVelocity.handleRequest(context, template);
    254            }
    255            catch (Exception e)
    256            {
    257                throw new EmailException(
    258                        "Could not render velocitty template", e);
    259            }
    260
    261            // If the caller desires word-wrapping, do it here
    262            if (wordWrap > 0)
    263            {
    264                body = WordUtils.wrap(body, wordWrap,
    265                        System.getProperty("line.separator"), false);
    266            }
    267
    268            setMsg(body);
    269            setHostName(getMailServer());
    270            return super.send();
    271        }
    272
    273        /**
    274         * The method toString() calls send() for ease of use within a
    275         * Velocity template (see example usage above).
    276         *
    277         * @return An empty string.
    278         */
    279        @Override
    280        public String toString()
    281        {
    282            try
    283            {
    284                send();
    285            }
    286            catch (Exception e)
    287            {
    288                log.error("VelocityEmail error", e);
    289            }
    290            return "";
    291        }
    292    }