    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
    023
    024import java.net.URL;
    025import java.util.Hashtable;
    026
    027import org.apache.commons.lang.StringUtils;
    028import org.apache.commons.logging.Log;
    029import org.apache.commons.logging.LogFactory;
    030import org.apache.commons.mail.EmailException;
    031import org.apache.commons.mail.HtmlEmail;
    032import org.apache.turbine.Turbine;
    033import org.apache.turbine.TurbineConstants;
    034import org.apache.turbine.pipeline.PipelineData;
    035import org.apache.turbine.services.velocity.TurbineVelocity;
    036import org.apache.velocity.context.Context;
    037
    038/**
    039 * This is a simple class for sending html email from within Velocity.
    040 * Essentially, the bodies (text and html) of the email are a Velocity
    041 * Context objects.  The beauty of this is that you can send email
    042 * from within your Velocity template or from your business logic in
    043 * your Java code.  The body of the email is just a Velocity template
    044 * so you can use all the template functionality of Velocity within
    045 * your emails!
    046 *
    047 * <p>This class allows you to send HTML email with embedded content
    048 * and/or with attachments.  You can access the VelocityHtmlEmail
    049 * instance within your templates trough the <code>$mail</code>
    050 * Velocity variable.
    051 * <p><code>VelocityHtmlEmail   myEmail= new VelocityHtmlEmail(data);<br>
    052 *                              context.put("mail", myMail);</code>
    053 * <b>or</b>
    054 *    <code>VelocityHtmlEmail   myEmail= new VelocityHtmlEmail(context);<br>
    055 *                              context.put("mail", myMail);</code>
    056 *
    057 *
    058 * <p>The templates should be located under your Template turbine
    059 * directory.
    060 *
    061 * <p>This class wraps the HtmlEmail class from commons-email.  Thus, it uses
    062 * the JavaMail API and also depends on having the mail.server property
    063 * set in the TurbineResources.properties file.  If you want to use
    064 * this class outside of Turbine for general processing that is also
    065 * possible by making sure to set the path to the
    066 * TurbineResources.properties.  See the
    067 * TurbineResourceService.setPropertiesFileName() method for more
    068 * information.
    069 *
    070 * <p>This class is basically a conversion of the WebMacroHtmlEmail
    071 * written by Regis Koenig
    072 *
    073 * <p>You can turn on debugging for the JavaMail API by calling
    074 * setDebug(true).  The debugging messages will be written to System.out.
    075 *
    076 * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
    077 * @author <a href="mailto:A.Schild@aarboard.ch">Andre Schild</a>
    078 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    079 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    080 * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
    081 * @version $Id: VelocityHtmlEmail.java 1706239 2015-10-01 13:18:35Z tv $
    082 */
    083public class VelocityHtmlEmail extends HtmlEmail
    084{
    085    /** Logging */
    086    private static Log log = LogFactory.getLog(VelocityHtmlEmail.class);
    087
    088    /**
    089     * The html template to process, relative to VM's template
    090     * directory.
    091     */
    092    private String htmlTemplate = null;
    093
    094    /**
    095     * The text template to process, relative to VM's template
    096     * directory.
    097     */
    098    private String textTemplate = null;
    099
    100    /** The cached context object. */
    101    private Context context = null;
    102
    103    /** The map of embedded files. */
    104    private Hashtable<String, String> embmap = null;
    105
    106    /** Address of outgoing mail server */
    107    private String mailServer;
    108
    109    /**
    110     * Constructor, sets the context object from the passed {@link PipelineData} object
    111     *
    112     * @param pipelineData A Turbine {@link PipelineData} object.
    113     */
    114    public VelocityHtmlEmail(PipelineData pipelineData)
    115    {
    116        this(TurbineVelocity.getContext(pipelineData));
    117    }
    118
    119    /**
    120     * Constructor, sets the context object.
    121     *
    122     * @param context A Velocity context object.
    123     */
    124    public VelocityHtmlEmail(Context context)
    125    {
    126        this.context = context;
    127        embmap = new Hashtable<String, String>();
    128    }
    129
    130    /**
    131     * Set the HTML template for the mail.  This is the Velocity
    132     * template to execute for the HTML part.  Path is relative to the
    133     * VM templates directory.
    134     *
    135     * @param template A String.
    136     * @return A VelocityHtmlEmail (self).
    137     */
    138    public VelocityHtmlEmail setHtmlTemplate(String template)
    139    {
    140        this.htmlTemplate = template;
    141        return this;
    142    }
    143
    144    /**
    145     * Set the text template for the mail.  This is the Velocity
    146     * template to execute for the text part.  Path is relative to the
    147     * VM templates directory
    148     *
    149     * @param template A String.
    150     * @return A VelocityHtmlEmail (self).
    151     */
    152    public VelocityHtmlEmail setTextTemplate(String template)
    153    {
    154        this.textTemplate = template;
    155        return this;
    156    }
    157
    158    /**
    159     * Sets the address of the outgoing mail server.  This method
    160     * should be used when you need to override the value stored in
    161     * TR.props.
    162     *
    163     * @param serverAddress host name of your outgoing mail server
    164     */
    165    public void setMailServer(String serverAddress)
    166    {
    167        this.mailServer = serverAddress;
    168    }
    169
    170    /**
    171     * Gets the host name of the outgoing mail server.  If the server
    172     * name has not been set by calling setMailServer(), the value
    173     * from TR.props for mail.server will be returned.  If TR.props
    174     * has no value for mail.server, localhost will be returned.
    175     *
    176     * @return host name of the mail server.
    177     */
    178    public String getMailServer()
    179    {
    180        return StringUtils.isNotEmpty(mailServer) ? mailServer
    181                : Turbine.getConfiguration().getString(
    182                TurbineConstants.MAIL_SERVER_KEY,
    183                TurbineConstants.MAIL_SERVER_DEFAULT);
    184    }
    185
    186    /**
    187     * Actually send the mail.
    188     *
    189     * @exception EmailException thrown if mail cannot be sent.
    190     */
    191    @Override
    192    public String send() throws EmailException
    193    {
    194        context.put("mail", this);
    195
    196        try
    197        {
    198            if (htmlTemplate != null)
    199            {
    200                setHtmlMsg(
    201                        TurbineVelocity.handleRequest(context, htmlTemplate));
    202            }
    203            if (textTemplate != null)
    204            {
    205                setTextMsg(
    206                        TurbineVelocity.handleRequest(context, textTemplate));
    207            }
    208        }
    209        catch (Exception e)
    210        {
    211            throw new EmailException("Cannot parse velocity template", e);
    212        }
    213        setHostName(getMailServer());
    214        return super.send();
    215    }
    216
    217    /**
    218     * Embed a file in the mail.  The file can be referenced through
    219     * its Content-ID.  This function also registers the CID in an
    220     * internal map, so the embedded file can be referenced more than
    221     * once by using the getCid() function.  This may be useful in a
    222     * template.
    223     *
    224     * <p>Example of template:
    225     *
    226     * <code><pre width="80">
    227     * &lt;html&gt;
    228     * &lt;!-- $mail.embed("http://server/border.gif","border.gif"); --&gt;
    229     * &lt;img src=$mail.getCid("border.gif")&gt;
    230     * &lt;p&gt;This is your content
    231     * &lt;img src=$mail.getCid("border.gif")&gt;
    232     * &lt;/html&gt;
    233     * </pre></code>
    234     *
    235     * @param surl A String.
    236     * @param name A String.
    237     * @return A String with the cid of the embedded file.
    238     *
    239     * @see HtmlEmail#embed(URL surl, String name) embed.
    240     */
    241    @Override
    242    public String embed(String surl, String name)
    243    {
    244        String cid = "";
    245        try
    246        {
    247            URL url = new URL(surl);
    248            cid = super.embed(url, name);
    249            embmap.put(name, cid);
    250        }
    251        catch (Exception e)
    252        {
    253            log.error("cannot embed " + surl + ": ", e);
    254        }
    255        return cid;
    256    }
    257
    258    /**
    259     * Get the cid of an embedded file.
    260     *
    261     * @param filename A String.
    262     * @return A String with the cid of the embedded file.
    263     * @see #embed(String surl, String name) embed.
    264     */
    265    public String getCid(String filename)
    266    {
    267        String cid = embmap.get(filename);
    268        return "cid:" + cid;
    269    }
    270
    271}