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 javax.mail.MessagingException;
24
25 import org.apache.commons.lang.StringUtils;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 import org.apache.commons.mail.HtmlEmail;
31
32 import org.apache.turbine.Turbine;
33 import org.apache.turbine.TurbineConstants;
34 import org.apache.turbine.services.velocity.TurbineVelocity;
35 import org.apache.turbine.util.RunData;
36
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 * @version $Id: VelocityHtmlEmail.java,v 1.12.2.2 2004/05/20 03:28:01 seade Exp $
82 */
83 public class VelocityHtmlEmail extends HtmlEmail
84 {
85 /*** Logging */
86 private static Log log = LogFactory.getLog(VelocityHtmlEmail.class);
87
88 /***
89 * The html template to process, relative to VM's template
90 * directory.
91 */
92 private String htmlTemplate = null;
93
94 /***
95 * The text template to process, relative to VM's template
96 * directory.
97 */
98 private String textTemplate = null;
99
100 /*** The cached context object. */
101 private Context context = null;
102
103 /*** The map of embedded files. */
104 private Hashtable embmap = null;
105
106 /*** Address of outgoing mail server */
107 private String mailServer;
108
109 /***
110 * Constructor, sets the context object from the passed RunData object
111 *
112 * @param data A Turbine RunData object.
113 */
114 public VelocityHtmlEmail(RunData data)
115 {
116 this.context = TurbineVelocity.getContext(data);
117 embmap = new Hashtable();
118 }
119
120 /***
121 * Constructor, sets the context object.
122 *
123 * @param context A Velocity context object.
124 */
125 public VelocityHtmlEmail(Context context)
126 {
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 * @exception MessagingException thrown if mail cannot be sent.
191 */
192 public void send() throws MessagingException
193 {
194 context.put("mail", this);
195
196 try
197 {
198 if (htmlTemplate != null)
199 {
200 setHtmlMsg(
201 TurbineVelocity.handleRequest(context, htmlTemplate));
202 }
203 if (textTemplate != null)
204 {
205 setTextMsg(
206 TurbineVelocity.handleRequest(context, textTemplate));
207 }
208 }
209 catch (Exception e)
210 {
211 throw new MessagingException("Cannot parse velocity template", e);
212 }
213 setHostName(getMailServer());
214 super.send();
215 }
216
217 /***
218 * Embed a file in the mail. The file can be referenced through
219 * its Content-ID. This function also registers the CID in an
220 * internal map, so the embedded file can be referenced more than
221 * once by using the getCid() function. This may be useful in a
222 * template.
223 *
224 * <p>Example of template:
225 *
226 * <code><pre width="80">
227 * <html>
228 * <!-- $mail.embed("http://server/border.gif","border.gif"); -->
229 * <img src=$mail.getCid("border.gif")>
230 * <p>This is your content
231 * <img src=$mail.getCid("border.gif")>
232 * </html>
233 * </pre></code>
234 *
235 * @param surl A String.
236 * @param name A String.
237 * @return A String with the cid of the embedded file.
238 * @exception VelocityEmailException
239 * @see HtmlEmail#embed(URL surl, String name) embed.
240 */
241 public String embed(String surl, String name) throws VelocityEmailException
242 {
243 String cid = "";
244 try
245 {
246 URL url = new URL(surl);
247 cid = embed(url, name);
248 }
249 catch (Exception e)
250 {
251 log.error("cannot embed " + surl + ": ", e);
252 }
253 return cid;
254 }
255
256 /***
257 * Get the cid of an embedded file.
258 *
259 * @param filename A String.
260 * @return A String with the cid of the embedded file.
261 * @see #embed(String surl, String name) embed.
262 */
263 public String getCid(String filename)
264 {
265 String cid = (String) embmap.get(filename);
266 return "cid:" + cid;
267 }
268
269 }