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