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 import java.net.URL;
20
21 import java.util.Hashtable;
22
23 import org.apache.commons.lang.StringUtils;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import org.apache.commons.mail.EmailException;
29 import org.apache.commons.mail.HtmlEmail;
30
31 import org.apache.turbine.Turbine;
32 import org.apache.turbine.TurbineConstants;
33 import org.apache.turbine.services.velocity.TurbineVelocity;
34 import org.apache.turbine.util.RunData;
35
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 * @version $Id: VelocityHtmlEmail.java 264148 2005-08-29 14:21:04Z henning $
81 */
82 public class VelocityHtmlEmail extends HtmlEmail
83 {
84 /*** Logging */
85 private static Log log = LogFactory.getLog(VelocityHtmlEmail.class);
86
87 /***
88 * The html template to process, relative to VM's template
89 * directory.
90 */
91 private String htmlTemplate = null;
92
93 /***
94 * The text template to process, relative to VM's template
95 * directory.
96 */
97 private String textTemplate = null;
98
99 /*** The cached context object. */
100 private Context context = null;
101
102 /*** The map of embedded files. */
103 private Hashtable embmap = null;
104
105 /*** Address of outgoing mail server */
106 private String mailServer;
107
108 /***
109 * Constructor, sets the context object from the passed RunData object
110 *
111 * @param data A Turbine RunData object.
112 */
113 public VelocityHtmlEmail(RunData data)
114 {
115 this.context = TurbineVelocity.getContext(data);
116 embmap = new Hashtable();
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.context = context;
127 embmap = new Hashtable();
128 }
129
130 /***
131 * Set the HTML template for the mail. This is the Velocity
132 * template to execute for the HTML part. Path is relative to the
133 * VM templates directory.
134 *
135 * @param template A String.
136 * @return A VelocityHtmlEmail (self).
137 */
138 public VelocityHtmlEmail setHtmlTemplate(String template)
139 {
140 this.htmlTemplate = template;
141 return this;
142 }
143
144 /***
145 * Set the text template for the mail. This is the Velocity
146 * template to execute for the text part. Path is relative to the
147 * VM templates directory
148 *
149 * @param template A String.
150 * @return A VelocityHtmlEmail (self).
151 */
152 public VelocityHtmlEmail setTextTemplate(String template)
153 {
154 this.textTemplate = template;
155 return this;
156 }
157
158 /***
159 * Sets the address of the outgoing mail server. This method
160 * should be used when you need to override the value stored in
161 * TR.props.
162 *
163 * @param serverAddress host name of your outgoing mail server
164 */
165 public void setMailServer(String serverAddress)
166 {
167 this.mailServer = serverAddress;
168 }
169
170 /***
171 * Gets the host name of the outgoing mail server. If the server
172 * name has not been set by calling setMailServer(), the value
173 * from TR.props for mail.server will be returned. If TR.props
174 * has no value for mail.server, localhost will be returned.
175 *
176 * @return host name of the mail server.
177 */
178 public String getMailServer()
179 {
180 return StringUtils.isNotEmpty(mailServer) ? mailServer
181 : Turbine.getConfiguration().getString(
182 TurbineConstants.MAIL_SERVER_KEY,
183 TurbineConstants.MAIL_SERVER_DEFAULT);
184 }
185
186 /***
187 * Actually send the mail.
188 *
189 * @exception EmailException thrown if mail cannot be sent.
190 */
191 public String send() throws EmailException
192 {
193 context.put("mail", this);
194
195 try
196 {
197 if (htmlTemplate != null)
198 {
199 setHtmlMsg(
200 TurbineVelocity.handleRequest(context, htmlTemplate));
201 }
202 if (textTemplate != null)
203 {
204 setTextMsg(
205 TurbineVelocity.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 * <code><pre width="80">
226 * <html>
227 * <!-- $mail.embed("http://server/border.gif","border.gif"); -->
228 * <img src=$mail.getCid("border.gif")>
229 * <p>This is your content
230 * <img src=$mail.getCid("border.gif")>
231 * </html>
232 * </pre></code>
233 *
234 * @param surl A String.
235 * @param name A String.
236 * @return A String with the cid of the embedded file.
237 * @exception VelocityEmailException
238 * @see HtmlEmail#embed(URL surl, String name) embed.
239 */
240 public String embed(String surl, String name) throws VelocityEmailException
241 {
242 String cid = "";
243 try
244 {
245 URL url = new URL(surl);
246 cid = embed(url, name);
247 }
248 catch (Exception e)
249 {
250 log.error("cannot embed " + surl + ": ", e);
251 }
252 return cid;
253 }
254
255 /***
256 * Get the cid of an embedded file.
257 *
258 * @param filename A String.
259 * @return A String with the cid of the embedded file.
260 * @see #embed(String surl, String name) embed.
261 */
262 public String getCid(String filename)
263 {
264 String cid = (String) embmap.get(filename);
265 return "cid:" + cid;
266 }
267
268 }