1 package org.apache.turbine.util.velocity;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 * <html>
230 * <!-- $mail.embed("http://server/border.gif","border.gif"); -->
231 * <img src=$mail.getCid("border.gif")>
232 * <p>This is your content
233 * <img src=$mail.getCid("border.gif")>
234 * </html>
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 }