001 package 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 023 024 import java.net.URL; 025 import java.util.Hashtable; 026 027 import org.apache.commons.lang.StringUtils; 028 import org.apache.commons.logging.Log; 029 import org.apache.commons.logging.LogFactory; 030 import org.apache.commons.mail.EmailException; 031 import org.apache.commons.mail.HtmlEmail; 032 import org.apache.turbine.Turbine; 033 import org.apache.turbine.TurbineConstants; 034 import org.apache.turbine.pipeline.PipelineData; 035 import org.apache.turbine.services.velocity.TurbineVelocity; 036 import org.apache.turbine.util.RunData; 037 import org.apache.velocity.context.Context; 038 039 /** 040 * This is a simple class for sending html email from within Velocity. 041 * Essentially, the bodies (text and html) of the email are a Velocity 042 * Context objects. The beauty of this is that you can send email 043 * from within your Velocity template or from your business logic in 044 * your Java code. The body of the email is just a Velocity template 045 * so you can use all the template functionality of Velocity within 046 * your emails! 047 * 048 * <p>This class allows you to send HTML email with embedded content 049 * and/or with attachments. You can access the VelocityHtmlEmail 050 * instance within your templates trough the <code>$mail</code> 051 * Velocity variable. 052 * <p><code>VelocityHtmlEmail myEmail= new VelocityHtmlEmail(data);<br> 053 * context.put("mail", myMail);</code> 054 * <b>or</b> 055 * <code>VelocityHtmlEmail myEmail= new VelocityHtmlEmail(context);<br> 056 * context.put("mail", myMail);</code> 057 * 058 * 059 * <p>The templates should be located under your Template turbine 060 * directory. 061 * 062 * <p>This class wraps the HtmlEmail class from commons-email. Thus, it uses 063 * the JavaMail API and also depends on having the mail.server property 064 * set in the TurbineResources.properties file. If you want to use 065 * this class outside of Turbine for general processing that is also 066 * possible by making sure to set the path to the 067 * TurbineResources.properties. See the 068 * TurbineResourceService.setPropertiesFileName() method for more 069 * information. 070 * 071 * <p>This class is basically a conversion of the WebMacroHtmlEmail 072 * written by Regis Koenig 073 * 074 * <p>You can turn on debugging for the JavaMail API by calling 075 * setDebug(true). The debugging messages will be written to System.out. 076 * 077 * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a> 078 * @author <a href="mailto:A.Schild@aarboard.ch">Andre Schild</a> 079 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a> 080 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> 081 * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a> 082 * @version $Id: VelocityHtmlEmail.java 929479 2010-03-31 11:24:21Z tv $ 083 */ 084 public class VelocityHtmlEmail extends HtmlEmail 085 { 086 /** Logging */ 087 private static Log log = LogFactory.getLog(VelocityHtmlEmail.class); 088 089 /** 090 * The html template to process, relative to VM's template 091 * directory. 092 */ 093 private String htmlTemplate = null; 094 095 /** 096 * The text template to process, relative to VM's template 097 * directory. 098 */ 099 private String textTemplate = null; 100 101 /** The cached context object. */ 102 private Context context = null; 103 104 /** The map of embedded files. */ 105 private Hashtable embmap = null; 106 107 /** Address of outgoing mail server */ 108 private String mailServer; 109 110 /** 111 * Constructor, sets the context object from the passed RunData object 112 * @deprecated use PipelineData version instead 113 * @param data A Turbine RunData object. 114 */ 115 public VelocityHtmlEmail(RunData data) 116 { 117 this.context = TurbineVelocity.getContext(data); 118 embmap = new Hashtable(); 119 } 120 121 /** 122 * Constructor, sets the context object from the passed RunData object 123 * 124 * @param data A Turbine RunData object. 125 */ 126 public VelocityHtmlEmail(PipelineData pipelineData) 127 { 128 this.context = TurbineVelocity.getContext(pipelineData); 129 embmap = new Hashtable(); 130 } 131 132 /** 133 * Constructor, sets the context object. 134 * 135 * @param context A Velocity context object. 136 */ 137 public VelocityHtmlEmail(Context context) 138 { 139 this.context = context; 140 embmap = new Hashtable(); 141 } 142 143 /** 144 * Set the HTML template for the mail. This is the Velocity 145 * template to execute for the HTML part. Path is relative to the 146 * VM templates directory. 147 * 148 * @param template A String. 149 * @return A VelocityHtmlEmail (self). 150 */ 151 public VelocityHtmlEmail setHtmlTemplate(String template) 152 { 153 this.htmlTemplate = template; 154 return this; 155 } 156 157 /** 158 * Set the text template for the mail. This is the Velocity 159 * template to execute for the text part. Path is relative to the 160 * VM templates directory 161 * 162 * @param template A String. 163 * @return A VelocityHtmlEmail (self). 164 */ 165 public VelocityHtmlEmail setTextTemplate(String template) 166 { 167 this.textTemplate = template; 168 return this; 169 } 170 171 /** 172 * Sets the address of the outgoing mail server. This method 173 * should be used when you need to override the value stored in 174 * TR.props. 175 * 176 * @param serverAddress host name of your outgoing mail server 177 */ 178 public void setMailServer(String serverAddress) 179 { 180 this.mailServer = serverAddress; 181 } 182 183 /** 184 * Gets the host name of the outgoing mail server. If the server 185 * name has not been set by calling setMailServer(), the value 186 * from TR.props for mail.server will be returned. If TR.props 187 * has no value for mail.server, localhost will be returned. 188 * 189 * @return host name of the mail server. 190 */ 191 public String getMailServer() 192 { 193 return StringUtils.isNotEmpty(mailServer) ? mailServer 194 : Turbine.getConfiguration().getString( 195 TurbineConstants.MAIL_SERVER_KEY, 196 TurbineConstants.MAIL_SERVER_DEFAULT); 197 } 198 199 /** 200 * Actually send the mail. 201 * 202 * @exception EmailException thrown if mail cannot be sent. 203 */ 204 public String send() throws EmailException 205 { 206 context.put("mail", this); 207 208 try 209 { 210 if (htmlTemplate != null) 211 { 212 setHtmlMsg( 213 TurbineVelocity.handleRequest(context, htmlTemplate)); 214 } 215 if (textTemplate != null) 216 { 217 setTextMsg( 218 TurbineVelocity.handleRequest(context, textTemplate)); 219 } 220 } 221 catch (Exception e) 222 { 223 throw new EmailException("Cannot parse velocity template", e); 224 } 225 setHostName(getMailServer()); 226 return super.send(); 227 } 228 229 /** 230 * Embed a file in the mail. The file can be referenced through 231 * its Content-ID. This function also registers the CID in an 232 * internal map, so the embedded file can be referenced more than 233 * once by using the getCid() function. This may be useful in a 234 * template. 235 * 236 * <p>Example of template: 237 * 238 * <code><pre width="80"> 239 * <html> 240 * <!-- $mail.embed("http://server/border.gif","border.gif"); --> 241 * <img src=$mail.getCid("border.gif")> 242 * <p>This is your content 243 * <img src=$mail.getCid("border.gif")> 244 * </html> 245 * </pre></code> 246 * 247 * @param surl A String. 248 * @param name A String. 249 * @return A String with the cid of the embedded file. 250 * 251 * @see HtmlEmail#embed(URL surl, String name) embed. 252 */ 253 public String embed(String surl, String name) 254 { 255 String cid = ""; 256 try 257 { 258 URL url = new URL(surl); 259 cid = embed(url, name); 260 } 261 catch (Exception e) 262 { 263 log.error("cannot embed " + surl + ": ", e); 264 } 265 return cid; 266 } 267 268 /** 269 * Get the cid of an embedded file. 270 * 271 * @param filename A String. 272 * @return A String with the cid of the embedded file. 273 * @see #embed(String surl, String name) embed. 274 */ 275 public String getCid(String filename) 276 { 277 String cid = (String) embmap.get(filename); 278 return "cid:" + cid; 279 } 280 281 }