View Javadoc

1   package org.apache.turbine.util.velocity;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.net.URL;
23  
24  import java.util.Hashtable;
25  
26  import org.apache.commons.lang.StringUtils;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  import org.apache.commons.mail.EmailException;
32  import org.apache.commons.mail.HtmlEmail;
33  
34  import org.apache.turbine.Turbine;
35  import org.apache.turbine.TurbineConstants;
36  import org.apache.turbine.services.velocity.TurbineVelocity;
37  import org.apache.turbine.util.RunData;
38  
39  import org.apache.velocity.context.Context;
40  
41  /***
42   * This is a simple class for sending html email from within Velocity.
43   * Essentially, the bodies (text and html) of the email are a Velocity
44   * Context objects.  The beauty of this is that you can send email
45   * from within your Velocity template or from your business logic in
46   * your Java code.  The body of the email is just a Velocity template
47   * so you can use all the template functionality of Velocity within
48   * your emails!
49   *
50   * <p>This class allows you to send HTML email with embedded content
51   * and/or with attachments.  You can access the VelocityHtmlEmail
52   * instance within your templates trough the <code>$mail</code>
53   * Velocity variable.
54   * <p><code>VelocityHtmlEmail   myEmail= new VelocityHtmlEmail(data);<br>
55   *                              context.put("mail", myMail);</code>
56   * <b>or</b>
57   *    <code>VelocityHtmlEmail   myEmail= new VelocityHtmlEmail(context);<br>
58   *                              context.put("mail", myMail);</code>
59   *
60   *
61   * <p>The templates should be located under your Template turbine
62   * directory.
63   *
64   * <p>This class wraps the HtmlEmail class from commons-email.  Thus, it uses
65   * the JavaMail API and also depends on having the mail.server property
66   * set in the TurbineResources.properties file.  If you want to use
67   * this class outside of Turbine for general processing that is also
68   * possible by making sure to set the path to the
69   * TurbineResources.properties.  See the
70   * TurbineResourceService.setPropertiesFileName() method for more
71   * information.
72   *
73   * <p>This class is basically a conversion of the WebMacroHtmlEmail
74   * written by Regis Koenig
75   *
76   * <p>You can turn on debugging for the JavaMail API by calling
77   * setDebug(true).  The debugging messages will be written to System.out.
78   *
79   * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
80   * @author <a href="mailto:A.Schild@aarboard.ch">Andre Schild</a>
81   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
82   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
83   * @version $Id: VelocityHtmlEmail.java 659576 2008-05-23 16:00:15Z seade $
84   */
85  public class VelocityHtmlEmail extends HtmlEmail
86  {
87      /*** Logging */
88      private static Log log = LogFactory.getLog(VelocityHtmlEmail.class);
89  
90      /***
91       * The html template to process, relative to VM's template
92       * directory.
93       */
94      private String htmlTemplate = null;
95  
96      /***
97       * The text template to process, relative to VM's template
98       * directory.
99       */
100     private String textTemplate = null;
101 
102     /*** The cached context object. */
103     private Context context = null;
104 
105     /*** The map of embedded files. */
106     private Hashtable embmap = null;
107 
108     /*** Address of outgoing mail server */
109     private String mailServer;
110 
111     /***
112      * Constructor, sets the context object from the passed RunData object
113      *
114      * @param data A Turbine RunData object.
115      */
116     public VelocityHtmlEmail(RunData data)
117     {
118         this.context = TurbineVelocity.getContext(data);
119         embmap = new Hashtable();
120     }
121 
122     /***
123      * Constructor, sets the context object.
124      *
125      * @param context A Velocity context object.
126      */
127     public VelocityHtmlEmail(Context context)
128     {
129         this.context = context;
130         embmap = new Hashtable();
131     }
132 
133     /***
134      * Set the HTML template for the mail.  This is the Velocity
135      * template to execute for the HTML part.  Path is relative to the
136      * VM templates directory.
137      *
138      * @param template A String.
139      * @return A VelocityHtmlEmail (self).
140      */
141     public VelocityHtmlEmail setHtmlTemplate(String template)
142     {
143         this.htmlTemplate = template;
144         return this;
145     }
146 
147     /***
148      * Set the text template for the mail.  This is the Velocity
149      * template to execute for the text part.  Path is relative to the
150      * VM templates directory
151      *
152      * @param template A String.
153      * @return A VelocityHtmlEmail (self).
154      */
155     public VelocityHtmlEmail setTextTemplate(String template)
156     {
157         this.textTemplate = template;
158         return this;
159     }
160 
161     /***
162      * Sets the address of the outgoing mail server.  This method
163      * should be used when you need to override the value stored in
164      * TR.props.
165      *
166      * @param serverAddress host name of your outgoing mail server
167      */
168     public void setMailServer(String serverAddress)
169     {
170         this.mailServer = serverAddress;
171     }
172 
173     /***
174      * Gets the host name of the outgoing mail server.  If the server
175      * name has not been set by calling setMailServer(), the value
176      * from TR.props for mail.server will be returned.  If TR.props
177      * has no value for mail.server, localhost will be returned.
178      *
179      * @return host name of the mail server.
180      */
181     public String getMailServer()
182     {
183         return StringUtils.isNotEmpty(mailServer) ? mailServer
184                 : Turbine.getConfiguration().getString(
185                 TurbineConstants.MAIL_SERVER_KEY,
186                 TurbineConstants.MAIL_SERVER_DEFAULT);
187     }
188 
189     /***
190      * Actually send the mail.
191      *
192      * @exception EmailException thrown if mail cannot be sent.
193      */
194     public String send() throws EmailException
195     {
196         context.put("mail", this);
197 
198         try
199         {
200             if (htmlTemplate != null)
201             {
202                 setHtmlMsg(
203                         TurbineVelocity.handleRequest(context, htmlTemplate));
204             }
205             if (textTemplate != null)
206             {
207                 setTextMsg(
208                         TurbineVelocity.handleRequest(context, textTemplate));
209             }
210         }
211         catch (Exception e)
212         {
213             throw new EmailException("Cannot parse velocity template", e);
214         }
215         setHostName(getMailServer());
216         return super.send();
217     }
218 
219     /***
220      * Embed a file in the mail.  The file can be referenced through
221      * its Content-ID.  This function also registers the CID in an
222      * internal map, so the embedded file can be referenced more than
223      * once by using the getCid() function.  This may be useful in a
224      * template.
225      *
226      * <p>Example of template:
227      *
228      * <code><pre width="80">
229      * &lt;html&gt;
230      * &lt;!-- $mail.embed("http://server/border.gif","border.gif"); --&gt;
231      * &lt;img src=$mail.getCid("border.gif")&gt;
232      * &lt;p&gt;This is your content
233      * &lt;img src=$mail.getCid("border.gif")&gt;
234      * &lt;/html&gt;
235      * </pre></code>
236      *
237      * @param surl A String.
238      * @param name A String.
239      * @return A String with the cid of the embedded file.
240      * @exception EmailException
241      * @see HtmlEmail#embed(URL surl, String name) embed.
242      */
243     public String embed(String surl, String name) throws EmailException
244     {
245         String cid = "";
246         try
247         {
248             URL url = new URL(surl);
249             cid = embed(url, name);
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 = (String) embmap.get(filename);
268         return "cid:" + cid;
269     }
270 
271 }