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