    001package 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
    023import org.apache.commons.lang.StringUtils;
    024import org.apache.commons.lang.WordUtils;
    025import org.apache.commons.logging.Log;
    026import org.apache.commons.logging.LogFactory;
    027import org.apache.commons.mail.EmailException;
    028import org.apache.commons.mail.SimpleEmail;
    029import org.apache.turbine.Turbine;
    030import org.apache.turbine.TurbineConstants;
    031import org.apache.turbine.services.velocity.TurbineVelocity;
    032import 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 1706239 2015-10-01 13:18:35Z tv $
    102 */
    103public 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     * @param context the velocity context to use
    131     */
    132    public VelocityEmail(Context context)
    133    {
    134        this();
    135        this.context = context;
    136    }
    137
    138    /**
    139     * To: toName, toEmail
    140     *
    141     * @param toName A String with the TO toName.
    142     * @param toEmail A String with the TO toEmail.
    143     * @deprecated use addTo(email,name) instead
    144     * @throws EmailException email address could not be parsed
    145     * @return A VelocityEmail (self).
    146     */
    147    @Deprecated
    148    public VelocityEmail setTo(String toName, String toEmail)
    149            throws EmailException
    150    {
    151        addTo(toEmail,toName);
    152        return this;
    153    }
    154
    155    /**
    156     * Velocity template to execute. Path is relative to the Velocity
    157     * templates directory.
    158     *
    159     * @param template relative path of the template to parse including the
    160     *                 filename.
    161     * @return A VelocityEmail (self).
    162     */
    163    public VelocityEmail setTemplate(String template)
    164    {
    165        this.template = template;
    166        return this;
    167    }
    168
    169    /**
    170     * Set the column at which long lines of text should be word-
    171     * wrapped. Setting to zero turns off word-wrap (default).
    172     *
    173     * NOTE: don't use tabs in your email template document,
    174     * or your word-wrapping will be off for the lines with tabs
    175     * in them.
    176     *
    177     * @param wordWrap The column at which to wrap long lines.
    178     * @return A VelocityEmail (self).
    179     */
    180    public VelocityEmail setWordWrap(int wordWrap)
    181    {
    182        this.wordWrap = wordWrap;
    183        return this;
    184    }
    185
    186    /**
    187     * Set the context object that will be merged with the
    188     * template.
    189     *
    190     * @param context A Velocity context object.
    191     * @return A VelocityEmail (self).
    192     */
    193    public VelocityEmail setContext(Context context)
    194    {
    195        this.context = context;
    196        return this;
    197    }
    198
    199    /**
    200     * Get the context object that will be merged with the
    201     * template.
    202     *
    203     * @return A Context (self).
    204     */
    205    public Context getContext()
    206    {
    207        return this.context;
    208    }
    209
    210    /**
    211     * Sets the address of the outgoing mail server.  This method
    212     * should be used when you need to override the value stored in
    213     * TR.props.
    214     *
    215     * @param serverAddress host name of your outgoing mail server
    216     */
    217    public void setMailServer(String serverAddress)
    218    {
    219        this.mailServer = serverAddress;
    220    }
    221
    222    /**
    223     * Gets the host name of the outgoing mail server.  If the server
    224     * name has not been set by calling setMailServer(), the value
    225     * from TR.props for mail.server will be returned.  If TR.props
    226     * has no value for mail.server, localhost will be returned.
    227     *
    228     * @return host name of the mail server.
    229     */
    230    public String getMailServer()
    231    {
    232        return StringUtils.isNotEmpty(mailServer) ? mailServer
    233                : Turbine.getConfiguration().getString(
    234                TurbineConstants.MAIL_SERVER_KEY,
    235                TurbineConstants.MAIL_SERVER_DEFAULT);
    236    }
    237
    238    /**
    239     * This method sends the email.
    240     * <p>If the mail server was not set by calling, setMailServer()
    241     * the value of mail.server will be used from TR.props.  If that
    242     * value was not set, localhost is used.
    243     *
    244     * @throws EmailException Failure during merging the velocity
    245     * template or sending the email.
    246     */
    247    @Override
    248    public String send() throws EmailException
    249    {
    250        String body = null;
    251        try
    252        {
    253            // Process the template.
    254            body = TurbineVelocity.handleRequest(context, template);
    255        }
    256        catch (Exception e)
    257        {
    258            throw new EmailException(
    259                    "Could not render velocitty template", e);
    260        }
    261
    262        // If the caller desires word-wrapping, do it here
    263        if (wordWrap > 0)
    264        {
    265            body = WordUtils.wrap(body, wordWrap,
    266                    System.getProperty("line.separator"), false);
    267        }
    268
    269        setMsg(body);
    270        setHostName(getMailServer());
    271        return super.send();
    272    }
    273
    274    /**
    275     * The method toString() calls send() for ease of use within a
    276     * Velocity template (see example usage above).
    277     *
    278     * @return An empty string.
    279     */
    280    @Override
    281    public String toString()
    282    {
    283        try
    284        {
    285            send();
    286        }
    287        catch (Exception e)
    288        {
    289            log.error("VelocityEmail error", e);
    290        }
    291        return "";
    292    }
    293}