    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.services.TurbineServices;
    035import org.apache.turbine.services.velocity.VelocityService;
    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 1773378 2016-12-09 13:19:59Z 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
    111     */
    112    public VelocityHtmlEmail()
    113    {
    114        super();
    115    }
    116
    117    /**
    118     * Constructor, sets the context object.
    119     *
    120     * @param context A Velocity context object.
    121     */
    122    public VelocityHtmlEmail(Context context)
    123    {
    124        this();
    125        this.context = context;
    126        embmap = new Hashtable<String, String>();
    127    }
    128
    129    /**
    130     * Set the HTML template for the mail.  This is the Velocity
    131     * template to execute for the HTML part.  Path is relative to the
    132     * VM templates directory.
    133     *
    134     * @param template A String.
    135     * @return A VelocityHtmlEmail (self).
    136     */
    137    public VelocityHtmlEmail setHtmlTemplate(String template)
    138    {
    139        this.htmlTemplate = template;
    140        return this;
    141    }
    142
    143    /**
    144     * Set the text template for the mail.  This is the Velocity
    145     * template to execute for the text part.  Path is relative to the
    146     * VM templates directory
    147     *
    148     * @param template A String.
    149     * @return A VelocityHtmlEmail (self).
    150     */
    151    public VelocityHtmlEmail setTextTemplate(String template)
    152    {
    153        this.textTemplate = template;
    154        return this;
    155    }
    156
    157    /**
    158     * Sets the address of the outgoing mail server.  This method
    159     * should be used when you need to override the value stored in
    160     * TR.props.
    161     *
    162     * @param serverAddress host name of your outgoing mail server
    163     */
    164    public void setMailServer(String serverAddress)
    165    {
    166        this.mailServer = serverAddress;
    167    }
    168
    169    /**
    170     * Gets the host name of the outgoing mail server.  If the server
    171     * name has not been set by calling setMailServer(), the value
    172     * from TR.props for mail.server will be returned.  If TR.props
    173     * has no value for mail.server, localhost will be returned.
    174     *
    175     * @return host name of the mail server.
    176     */
    177    public String getMailServer()
    178    {
    179        return StringUtils.isNotEmpty(mailServer) ? mailServer
    180                : Turbine.getConfiguration().getString(
    181                TurbineConstants.MAIL_SERVER_KEY,
    182                TurbineConstants.MAIL_SERVER_DEFAULT);
    183    }
    184
    185    /**
    186     * Actually send the mail.
    187     *
    188     * @throws EmailException thrown if mail cannot be sent.
    189     */
    190    @Override
    191    public String send() throws EmailException
    192    {
    193        context.put("mail", this);
    194
    195        try
    196        {
    197            VelocityService velocityService = (VelocityService)TurbineServices.getInstance().getService(VelocityService.SERVICE_NAME);
    198
    199            if (htmlTemplate != null)
    200            {
    201                setHtmlMsg(velocityService.handleRequest(context, htmlTemplate));
    202            }
    203            if (textTemplate != null)
    204            {
    205                setTextMsg(velocityService.handleRequest(context, textTemplate));
    206            }
    207        }
    208        catch (Exception e)
    209        {
    210            throw new EmailException("Cannot parse velocity template", e);
    211        }
    212        setHostName(getMailServer());
    213        return super.send();
    214    }
    215
    216    /**
    217     * Embed a file in the mail.  The file can be referenced through
    218     * its Content-ID.  This function also registers the CID in an
    219     * internal map, so the embedded file can be referenced more than
    220     * once by using the getCid() function.  This may be useful in a
    221     * template.
    222     *
    223     * <p>Example of template:
    224     *
    225     * <pre>
    226     * &lt;html&gt;
    227     * &lt;!-- $mail.embed("http://server/border.gif","border.gif"); --&gt;
    228     * &lt;img src=$mail.getCid("border.gif")&gt;
    229     * &lt;p&gt;This is your content
    230     * &lt;img src=$mail.getCid("border.gif")&gt;
    231     * &lt;/html&gt;
    232     * </pre>
    233     *
    234     * @param surl A String.
    235     * @param name A String.
    236     * @return A String with the cid of the embedded file.
    237     *
    238     * @see HtmlEmail#embed(URL surl, String name) embed.
    239     */
    240    @Override
    241    public String embed(String surl, String name)
    242    {
    243        String cid = "";
    244        try
    245        {
    246            URL url = new URL(surl);
    247            cid = super.embed(url, name);
    248            embmap.put(name, cid);
    249        }
    250        catch (Exception e)
    251        {
    252            log.error("cannot embed " + surl + ": ", e);
    253        }
    254        return cid;
    255    }
    256
    257    /**
    258     * Get the cid of an embedded file.
    259     *
    260     * @param filename A String.
    261     * @return A String with the cid of the embedded file.
    262     * @see #embed(String surl, String name) embed.
    263     */
    264    public String getCid(String filename)
    265    {
    266        String cid = embmap.get(filename);
    267        return "cid:" + cid;
    268    }
    269
    270}