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