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 1078552 2011-03-06 19:58:46Z 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 */ 131 public VelocityEmail(Context context) 132 { 133 this(); 134 this.context = context; 135 } 136 137 /** 138 * To: toName, toEmail 139 * 140 * @param toName A String with the TO toName. 141 * @param toEmail A String with the TO toEmail. 142 * @deprecated use addTo(email,name) instead 143 * @throws EmailException email address could not be parsed 144 * @return A VelocityEmail (self). 145 */ 146 @Deprecated 147 public VelocityEmail setTo(String toName, String toEmail) 148 throws EmailException 149 { 150 addTo(toEmail,toName); 151 return this; 152 } 153 154 /** 155 * Velocity template to execute. Path is relative to the Velocity 156 * templates directory. 157 * 158 * @param template relative path of the template to parse including the 159 * filename. 160 * @return A VelocityEmail (self). 161 */ 162 public VelocityEmail setTemplate(String template) 163 { 164 this.template = template; 165 return this; 166 } 167 168 /** 169 * Set the column at which long lines of text should be word- 170 * wrapped. Setting to zero turns off word-wrap (default). 171 * 172 * NOTE: don't use tabs in your email template document, 173 * or your word-wrapping will be off for the lines with tabs 174 * in them. 175 * 176 * @param wordWrap The column at which to wrap long lines. 177 * @return A VelocityEmail (self). 178 */ 179 public VelocityEmail setWordWrap(int wordWrap) 180 { 181 this.wordWrap = wordWrap; 182 return this; 183 } 184 185 /** 186 * Set the context object that will be merged with the 187 * template. 188 * 189 * @param context A Velocity context object. 190 * @return A VelocityEmail (self). 191 */ 192 public VelocityEmail setContext(Context context) 193 { 194 this.context = context; 195 return this; 196 } 197 198 /** 199 * Get the context object that will be merged with the 200 * template. 201 * 202 * @return A Context (self). 203 */ 204 public Context getContext() 205 { 206 return this.context; 207 } 208 209 /** 210 * Sets the address of the outgoing mail server. This method 211 * should be used when you need to override the value stored in 212 * TR.props. 213 * 214 * @param serverAddress host name of your outgoing mail server 215 */ 216 public void setMailServer(String serverAddress) 217 { 218 this.mailServer = serverAddress; 219 } 220 221 /** 222 * Gets the host name of the outgoing mail server. If the server 223 * name has not been set by calling setMailServer(), the value 224 * from TR.props for mail.server will be returned. If TR.props 225 * has no value for mail.server, localhost will be returned. 226 * 227 * @return host name of the mail server. 228 */ 229 public String getMailServer() 230 { 231 return StringUtils.isNotEmpty(mailServer) ? mailServer 232 : Turbine.getConfiguration().getString( 233 TurbineConstants.MAIL_SERVER_KEY, 234 TurbineConstants.MAIL_SERVER_DEFAULT); 235 } 236 237 /** 238 * This method sends the email. 239 * <p>If the mail server was not set by calling, setMailServer() 240 * the value of mail.server will be used from TR.props. If that 241 * value was not set, localhost is used. 242 * 243 * @throws EmailException Failure during merging the velocity 244 * template or sending the email. 245 */ 246 @Override 247 public String send() throws EmailException 248 { 249 String body = null; 250 try 251 { 252 // Process the template. 253 body = TurbineVelocity.handleRequest(context, template); 254 } 255 catch (Exception e) 256 { 257 throw new EmailException( 258 "Could not render velocitty template", e); 259 } 260 261 // If the caller desires word-wrapping, do it here 262 if (wordWrap > 0) 263 { 264 body = WordUtils.wrap(body, wordWrap, 265 System.getProperty("line.separator"), false); 266 } 267 268 setMsg(body); 269 setHostName(getMailServer()); 270 return super.send(); 271 } 272 273 /** 274 * The method toString() calls send() for ease of use within a 275 * Velocity template (see example usage above). 276 * 277 * @return An empty string. 278 */ 279 @Override 280 public String toString() 281 { 282 try 283 { 284 send(); 285 } 286 catch (Exception e) 287 { 288 log.error("VelocityEmail error", e); 289 } 290 return ""; 291 } 292 }