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.lang3.StringUtils; 24 import org.apache.commons.mail.EmailException; 25 import org.apache.commons.mail.SimpleEmail; 26 import org.apache.commons.text.WordUtils; 27 import org.apache.logging.log4j.LogManager; 28 import org.apache.logging.log4j.Logger; 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$ 103 */ 104 public class VelocityEmail extends SimpleEmail 105 { 106 /** Logging */ 107 private static final Logger log = LogManager.getLogger(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 (EmailException e) 290 { 291 log.error("VelocityEmail error", e); 292 } 293 return ""; 294 } 295 }