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