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 org.apache.commons.lang.StringUtils;
23 import org.apache.commons.lang.WordUtils;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.commons.mail.EmailException;
27 import org.apache.commons.mail.SimpleEmail;
28 import org.apache.turbine.Turbine;
29 import org.apache.turbine.TurbineConstants;
30 import org.apache.turbine.services.velocity.TurbineVelocity;
31 import org.apache.velocity.context.Context;
32
33 /***
34 * This is a simple class for sending email from within Velocity.
35 * Essentially, the body of the email is processed with a
36 * Velocity Context object.
37 * The beauty of this is that you can send email from within your
38 * Velocity template or from your business logic in your Java code.
39 * The body of the email is just a Velocity template so you can use
40 * all the template functionality of Velocity within your emails!
41 *
42 * <p>Example Usage (This all needs to be on one line in your
43 * template):
44 *
45 * <p>Setup your context:
46 *
47 * <p><code>context.put ("VelocityEmail", new VelocityEmail() );</code>
48 *
49 * <p>Then, in your template:
50 *
51 * <pre>
52 * $VelocityEmail.setTo("Jon Stevens", "jon@latchkey.com")
53 * .setFrom("Mom", "mom@mom.com").setSubject("Eat dinner")
54 * .setTemplate("email/momEmail.vm")
55 * .setContext($context)
56 * </pre>
57 *
58 * The email/momEmail.wm template will then be parsed with the
59 * Context that was defined with setContext().
60 *
61 * <p>If you want to use this class from within your Java code all you
62 * have to do is something like this:
63 *
64 * <pre>
65 * VelocityEmail ve = new VelocityEmail();
66 * ve.setTo("Jon Stevens", "jon@latchkey.com");
67 * ve.setFrom("Mom", "mom@mom.com").setSubject("Eat dinner");
68 * ve.setContext(context);
69 * ve.setTemplate("email/momEmail.vm")
70 * ve.send();
71 * </pre>
72 *
73 * <p>(Note that when used within a Velocity template, the send method
74 * will be called for you when Velocity tries to convert the
75 * VelocityEmail to a string by calling toString()).</p>
76 *
77 * <p>If you need your email to be word-wrapped, you can add the
78 * following call to those above:
79 *
80 * <pre>
81 * ve.setWordWrap (60);
82 * </pre>
83 *
84 * <p>This class is just a wrapper around the SimpleEmail class from
85 * commons-mail using the JavaMail API.
86 * Thus, it depends on having the
87 * mail.server property set in the TurbineResources.properties file.
88 * If you want to use this class outside of Turbine for general
89 * processing that is also possible by making sure to set the path to
90 * the TurbineResources.properties. See the
91 * TurbineConfig class for more information.</p>
92 *
93 * <p>You can turn on debugging for the JavaMail API by calling
94 * setDebug(true). The debugging messages will be written to System.out.
95 *
96 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
97 * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
98 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
99 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
100 * @version $Id: VelocityEmail.java 534527 2007-05-02 16:10:59Z tv $
101 */
102 public class VelocityEmail extends SimpleEmail
103 {
104 /*** Logging */
105 private static Log log = LogFactory.getLog(VelocityEmail.class);
106
107 /*** The column to word-wrap at. <code>0</code> indicates no wrap. */
108 private int wordWrap = 0;
109
110 /*** Address of outgoing mail server */
111 private String mailServer;
112
113 /*** The template to process, relative to Velocity template directory. */
114 private String template = null;
115
116 /*** Velocity context */
117 private Context context = null;
118
119 /***
120 * Constructor
121 */
122 public VelocityEmail()
123 {
124 }
125
126 /***
127 * Constructor
128 */
129 public VelocityEmail(Context context)
130 {
131 this.context = context;
132 }
133
134 /***
135 * To: toName, toEmail
136 *
137 * @param toName A String with the TO toName.
138 * @param toEmail A String with the TO toEmail.
139 * @deprecated use addTo(email,name) instead
140 * @throws EmailException email address could not be parsed
141 * @return A VelocityEmail (self).
142 */
143 public VelocityEmail setTo(String toName, String toEmail)
144 throws EmailException
145 {
146 addTo(toEmail,toName);
147 return this;
148 }
149
150 /***
151 * Velocity template to execute. Path is relative to the Velocity
152 * templates directory.
153 *
154 * @param template relative path of the template to parse including the
155 * filename.
156 * @return A VelocityEmail (self).
157 */
158 public VelocityEmail setTemplate(String template)
159 {
160 this.template = template;
161 return this;
162 }
163
164 /***
165 * Set the column at which long lines of text should be word-
166 * wrapped. Setting to zero turns off word-wrap (default).
167 *
168 * NOTE: don't use tabs in your email template document,
169 * or your word-wrapping will be off for the lines with tabs
170 * in them.
171 *
172 * @param wordWrap The column at which to wrap long lines.
173 * @return A VelocityEmail (self).
174 */
175 public VelocityEmail setWordWrap(int wordWrap)
176 {
177 this.wordWrap = wordWrap;
178 return this;
179 }
180
181 /***
182 * Set the context object that will be merged with the
183 * template.
184 *
185 * @param context A Velocity context object.
186 * @return A VelocityEmail (self).
187 */
188 public VelocityEmail setContext(Context context)
189 {
190 this.context = context;
191 return this;
192 }
193
194 /***
195 * Get the context object that will be merged with the
196 * template.
197 *
198 * @return A Context (self).
199 */
200 public Context getContext()
201 {
202 return this.context;
203 }
204
205 /***
206 * Sets the address of the outgoing mail server. This method
207 * should be used when you need to override the value stored in
208 * TR.props.
209 *
210 * @param serverAddress host name of your outgoing mail server
211 */
212 public void setMailServer(String serverAddress)
213 {
214 this.mailServer = serverAddress;
215 }
216
217 /***
218 * Gets the host name of the outgoing mail server. If the server
219 * name has not been set by calling setMailServer(), the value
220 * from TR.props for mail.server will be returned. If TR.props
221 * has no value for mail.server, localhost will be returned.
222 *
223 * @return host name of the mail server.
224 */
225 public String getMailServer()
226 {
227 return StringUtils.isNotEmpty(mailServer) ? mailServer
228 : Turbine.getConfiguration().getString(
229 TurbineConstants.MAIL_SERVER_KEY,
230 TurbineConstants.MAIL_SERVER_DEFAULT);
231 }
232
233 /***
234 * This method sends the email.
235 * <p>If the mail server was not set by calling, setMailServer()
236 * the value of mail.server will be used from TR.props. If that
237 * value was not set, localhost is used.
238 *
239 * @throws EmailException Failure during merging the velocity
240 * template or sending the email.
241 */
242 public String send() throws EmailException
243 {
244 String body = null;
245 try
246 {
247
248 body = TurbineVelocity.handleRequest(context, template);
249 }
250 catch (Exception e)
251 {
252 throw new EmailException(
253 "Could not render velocitty template", e);
254 }
255
256
257 if (wordWrap > 0)
258 {
259 body = WordUtils.wrap(body, wordWrap,
260 System.getProperty("line.separator"), false);
261 }
262
263 setMsg(body);
264 setHostName(getMailServer());
265 return super.send();
266 }
267
268 /***
269 * The method toString() calls send() for ease of use within a
270 * Velocity template (see example usage above).
271 *
272 * @return An empty string.
273 */
274 public String toString()
275 {
276 try
277 {
278 send();
279 }
280 catch (Exception e)
281 {
282 log.error("VelocityEmail error", e);
283 }
284 return "";
285 }
286 }