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.pipeline.PipelineData;
35 import org.apache.turbine.services.velocity.TurbineVelocity;
36 import org.apache.turbine.util.RunData;
37 import org.apache.velocity.context.Context;
38
39 /**
40 * This is a simple class for sending html email from within Velocity.
41 * Essentially, the bodies (text and html) of the email are a Velocity
42 * Context objects. The beauty of this is that you can send email
43 * from within your Velocity template or from your business logic in
44 * your Java code. The body of the email is just a Velocity template
45 * so you can use all the template functionality of Velocity within
46 * your emails!
47 *
48 * <p>This class allows you to send HTML email with embedded content
49 * and/or with attachments. You can access the VelocityHtmlEmail
50 * instance within your templates trough the <code>$mail</code>
51 * Velocity variable.
52 * <p><code>VelocityHtmlEmail myEmail= new VelocityHtmlEmail(data);<br>
53 * context.put("mail", myMail);</code>
54 * <b>or</b>
55 * <code>VelocityHtmlEmail myEmail= new VelocityHtmlEmail(context);<br>
56 * context.put("mail", myMail);</code>
57 *
58 *
59 * <p>The templates should be located under your Template turbine
60 * directory.
61 *
62 * <p>This class wraps the HtmlEmail class from commons-email. Thus, it uses
63 * the JavaMail API and also depends on having the mail.server property
64 * set in the TurbineResources.properties file. If you want to use
65 * this class outside of Turbine for general processing that is also
66 * possible by making sure to set the path to the
67 * TurbineResources.properties. See the
68 * TurbineResourceService.setPropertiesFileName() method for more
69 * information.
70 *
71 * <p>This class is basically a conversion of the WebMacroHtmlEmail
72 * written by Regis Koenig
73 *
74 * <p>You can turn on debugging for the JavaMail API by calling
75 * setDebug(true). The debugging messages will be written to System.out.
76 *
77 * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
78 * @author <a href="mailto:A.Schild@aarboard.ch">Andre Schild</a>
79 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
80 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
81 * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
82 * @version $Id: VelocityHtmlEmail.java 929479 2010-03-31 11:24:21Z tv $
83 */
84 public class VelocityHtmlEmail extends HtmlEmail
85 {
86 /** Logging */
87 private static Log log = LogFactory.getLog(VelocityHtmlEmail.class);
88
89 /**
90 * The html template to process, relative to VM's template
91 * directory.
92 */
93 private String htmlTemplate = null;
94
95 /**
96 * The text template to process, relative to VM's template
97 * directory.
98 */
99 private String textTemplate = null;
100
101 /** The cached context object. */
102 private Context context = null;
103
104 /** The map of embedded files. */
105 private Hashtable embmap = null;
106
107 /** Address of outgoing mail server */
108 private String mailServer;
109
110 /**
111 * Constructor, sets the context object from the passed RunData object
112 * @deprecated use PipelineData version instead
113 * @param data A Turbine RunData object.
114 */
115 public VelocityHtmlEmail(RunData data)
116 {
117 this.context = TurbineVelocity.getContext(data);
118 embmap = new Hashtable();
119 }
120
121 /**
122 * Constructor, sets the context object from the passed RunData object
123 *
124 * @param data A Turbine RunData object.
125 */
126 public VelocityHtmlEmail(PipelineData pipelineData)
127 {
128 this.context = TurbineVelocity.getContext(pipelineData);
129 embmap = new Hashtable();
130 }
131
132 /**
133 * Constructor, sets the context object.
134 *
135 * @param context A Velocity context object.
136 */
137 public VelocityHtmlEmail(Context context)
138 {
139 this.context = context;
140 embmap = new Hashtable();
141 }
142
143 /**
144 * Set the HTML template for the mail. This is the Velocity
145 * template to execute for the HTML 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 setHtmlTemplate(String template)
152 {
153 this.htmlTemplate = template;
154 return this;
155 }
156
157 /**
158 * Set the text template for the mail. This is the Velocity
159 * template to execute for the text part. Path is relative to the
160 * VM templates directory
161 *
162 * @param template A String.
163 * @return A VelocityHtmlEmail (self).
164 */
165 public VelocityHtmlEmail setTextTemplate(String template)
166 {
167 this.textTemplate = template;
168 return this;
169 }
170
171 /**
172 * Sets the address of the outgoing mail server. This method
173 * should be used when you need to override the value stored in
174 * TR.props.
175 *
176 * @param serverAddress host name of your outgoing mail server
177 */
178 public void setMailServer(String serverAddress)
179 {
180 this.mailServer = serverAddress;
181 }
182
183 /**
184 * Gets the host name of the outgoing mail server. If the server
185 * name has not been set by calling setMailServer(), the value
186 * from TR.props for mail.server will be returned. If TR.props
187 * has no value for mail.server, localhost will be returned.
188 *
189 * @return host name of the mail server.
190 */
191 public String getMailServer()
192 {
193 return StringUtils.isNotEmpty(mailServer) ? mailServer
194 : Turbine.getConfiguration().getString(
195 TurbineConstants.MAIL_SERVER_KEY,
196 TurbineConstants.MAIL_SERVER_DEFAULT);
197 }
198
199 /**
200 * Actually send the mail.
201 *
202 * @exception EmailException thrown if mail cannot be sent.
203 */
204 public String send() throws EmailException
205 {
206 context.put("mail", this);
207
208 try
209 {
210 if (htmlTemplate != null)
211 {
212 setHtmlMsg(
213 TurbineVelocity.handleRequest(context, htmlTemplate));
214 }
215 if (textTemplate != null)
216 {
217 setTextMsg(
218 TurbineVelocity.handleRequest(context, textTemplate));
219 }
220 }
221 catch (Exception e)
222 {
223 throw new EmailException("Cannot parse velocity template", e);
224 }
225 setHostName(getMailServer());
226 return super.send();
227 }
228
229 /**
230 * Embed a file in the mail. The file can be referenced through
231 * its Content-ID. This function also registers the CID in an
232 * internal map, so the embedded file can be referenced more than
233 * once by using the getCid() function. This may be useful in a
234 * template.
235 *
236 * <p>Example of template:
237 *
238 * <code><pre width="80">
239 * <html>
240 * <!-- $mail.embed("http://server/border.gif","border.gif"); -->
241 * <img src=$mail.getCid("border.gif")>
242 * <p>This is your content
243 * <img src=$mail.getCid("border.gif")>
244 * </html>
245 * </pre></code>
246 *
247 * @param surl A String.
248 * @param name A String.
249 * @return A String with the cid of the embedded file.
250 *
251 * @see HtmlEmail#embed(URL surl, String name) embed.
252 */
253 public String embed(String surl, String name)
254 {
255 String cid = "";
256 try
257 {
258 URL url = new URL(surl);
259 cid = embed(url, name);
260 }
261 catch (Exception e)
262 {
263 log.error("cannot embed " + surl + ": ", e);
264 }
265 return cid;
266 }
267
268 /**
269 * Get the cid of an embedded file.
270 *
271 * @param filename A String.
272 * @return A String with the cid of the embedded file.
273 * @see #embed(String surl, String name) embed.
274 */
275 public String getCid(String filename)
276 {
277 String cid = (String) embmap.get(filename);
278 return "cid:" + cid;
279 }
280
281 }