001package org.apache.turbine.util.velocity; 002 003 004/* 005 * Licensed to the Apache Software Foundation (ASF) under one 006 * or more contributor license agreements. See the NOTICE file 007 * distributed with this work for additional information 008 * regarding copyright ownership. The ASF licenses this file 009 * to you under the Apache License, Version 2.0 (the 010 * "License"); you may not use this file except in compliance 011 * with the License. You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, 016 * software distributed under the License is distributed on an 017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 018 * KIND, either express or implied. See the License for the 019 * specific language governing permissions and limitations 020 * under the License. 021 */ 022 023import org.apache.commons.lang.StringUtils; 024import org.apache.commons.lang.WordUtils; 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027import org.apache.commons.mail.EmailException; 028import org.apache.commons.mail.SimpleEmail; 029import org.apache.turbine.Turbine; 030import org.apache.turbine.TurbineConstants; 031import org.apache.turbine.services.velocity.TurbineVelocity; 032import org.apache.velocity.context.Context; 033 034/** 035 * This is a simple class for sending email from within Velocity. 036 * Essentially, the body of the email is processed with a 037 * Velocity Context object. 038 * The beauty of this is that you can send email from within your 039 * Velocity template or from your business logic in your Java code. 040 * The body of the email is just a Velocity template so you can use 041 * all the template functionality of Velocity within your emails! 042 * 043 * <p>Example Usage (This all needs to be on one line in your 044 * template): 045 * 046 * <p>Setup your context: 047 * 048 * <p><code>context.put ("VelocityEmail", new VelocityEmail() );</code> 049 * 050 * <p>Then, in your template: 051 * 052 * <pre> 053 * $VelocityEmail.setTo("Jon Stevens", "jon@latchkey.com") 054 * .setFrom("Mom", "mom@mom.com").setSubject("Eat dinner") 055 * .setTemplate("email/momEmail.vm") 056 * .setContext($context) 057 * </pre> 058 * 059 * The email/momEmail.wm template will then be parsed with the 060 * Context that was defined with setContext(). 061 * 062 * <p>If you want to use this class from within your Java code all you 063 * have to do is something like this: 064 * 065 * <pre> 066 * VelocityEmail ve = new VelocityEmail(); 067 * ve.setTo("Jon Stevens", "jon@latchkey.com"); 068 * ve.setFrom("Mom", "mom@mom.com").setSubject("Eat dinner"); 069 * ve.setContext(context); 070 * ve.setTemplate("email/momEmail.vm") 071 * ve.send(); 072 * </pre> 073 * 074 * <p>(Note that when used within a Velocity template, the send method 075 * will be called for you when Velocity tries to convert the 076 * VelocityEmail to a string by calling toString()).</p> 077 * 078 * <p>If you need your email to be word-wrapped, you can add the 079 * following call to those above: 080 * 081 * <pre> 082 * ve.setWordWrap (60); 083 * </pre> 084 * 085 * <p>This class is just a wrapper around the SimpleEmail class from 086 * commons-mail using the JavaMail API. 087 * Thus, it depends on having the 088 * mail.server property set in the TurbineResources.properties file. 089 * If you want to use this class outside of Turbine for general 090 * processing that is also possible by making sure to set the path to 091 * the TurbineResources.properties. See the 092 * TurbineConfig class for more information.</p> 093 * 094 * <p>You can turn on debugging for the JavaMail API by calling 095 * setDebug(true). The debugging messages will be written to System.out. 096 * 097 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> 098 * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a> 099 * @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 */ 103public 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}