View Javadoc
1   package org.apache.turbine.util.velocity;
2   
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21   */
22  
23  
24  import java.net.URL;
25  import java.util.Hashtable;
26  
27  import org.apache.commons.lang.StringUtils;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.commons.mail.EmailException;
31  import org.apache.commons.mail.HtmlEmail;
32  import org.apache.turbine.Turbine;
33  import org.apache.turbine.TurbineConstants;
34  import org.apache.turbine.services.TurbineServices;
35  import org.apache.turbine.services.velocity.VelocityService;
36  import org.apache.velocity.context.Context;
37  
38  /**
39   * This is a simple class for sending html email from within Velocity.
40   * Essentially, the bodies (text and html) of the email are a Velocity
41   * Context objects.  The beauty of this is that you can send email
42   * from within your Velocity template or from your business logic in
43   * your Java code.  The body of the email is just a Velocity template
44   * so you can use all the template functionality of Velocity within
45   * your emails!
46   *
47   * <p>This class allows you to send HTML email with embedded content
48   * and/or with attachments.  You can access the VelocityHtmlEmail
49   * instance within your templates trough the <code>$mail</code>
50   * Velocity variable.
51   * <p><code>VelocityHtmlEmail   myEmail= new VelocityHtmlEmail(data);<br>
52   *                              context.put("mail", myMail);</code>
53   * <b>or</b>
54   *    <code>VelocityHtmlEmail   myEmail= new VelocityHtmlEmail(context);<br>
55   *                              context.put("mail", myMail);</code>
56   *
57   *
58   * <p>The templates should be located under your Template turbine
59   * directory.
60   *
61   * <p>This class wraps the HtmlEmail class from commons-email.  Thus, it uses
62   * the JavaMail API and also depends on having the mail.server property
63   * set in the TurbineResources.properties file.  If you want to use
64   * this class outside of Turbine for general processing that is also
65   * possible by making sure to set the path to the
66   * TurbineResources.properties.  See the
67   * TurbineResourceService.setPropertiesFileName() method for more
68   * information.
69   *
70   * <p>This class is basically a conversion of the WebMacroHtmlEmail
71   * written by Regis Koenig
72   *
73   * <p>You can turn on debugging for the JavaMail API by calling
74   * setDebug(true).  The debugging messages will be written to System.out.
75   *
76   * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
77   * @author <a href="mailto:A.Schild@aarboard.ch">Andre Schild</a>
78   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
79   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
80   * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
81   * @version $Id: VelocityHtmlEmail.java 1773378 2016-12-09 13:19:59Z tv $
82   */
83  public class VelocityHtmlEmail extends HtmlEmail
84  {
85      /** Logging */
86      private static Log log = LogFactory.getLog(VelocityHtmlEmail.class);
87  
88      /**
89       * The html template to process, relative to VM's template
90       * directory.
91       */
92      private String htmlTemplate = null;
93  
94      /**
95       * The text template to process, relative to VM's template
96       * directory.
97       */
98      private String textTemplate = null;
99  
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 }