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 24 import java.net.URL; 25 import java.util.Hashtable; 26 27 import org.apache.commons.lang.StringUtils; 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 import org.apache.commons.mail.EmailException; 31 import org.apache.commons.mail.HtmlEmail; 32 import org.apache.turbine.Turbine; 33 import org.apache.turbine.TurbineConstants; 34 import org.apache.turbine.pipeline.PipelineData; 35 import org.apache.turbine.services.velocity.TurbineVelocity; 36 import org.apache.velocity.context.Context; 37 38 /** 39 * This is a simple class for sending html email from within Velocity. 40 * Essentially, the bodies (text and html) of the email are a Velocity 41 * Context objects. The beauty of this is that you can send email 42 * from within your Velocity template or from your business logic in 43 * your Java code. The body of the email is just a Velocity template 44 * so you can use all the template functionality of Velocity within 45 * your emails! 46 * 47 * <p>This class allows you to send HTML email with embedded content 48 * and/or with attachments. You can access the VelocityHtmlEmail 49 * instance within your templates trough the <code>$mail</code> 50 * Velocity variable. 51 * <p><code>VelocityHtmlEmail myEmail= new VelocityHtmlEmail(data);<br> 52 * context.put("mail", myMail);</code> 53 * <b>or</b> 54 * <code>VelocityHtmlEmail myEmail= new VelocityHtmlEmail(context);<br> 55 * context.put("mail", myMail);</code> 56 * 57 * 58 * <p>The templates should be located under your Template turbine 59 * directory. 60 * 61 * <p>This class wraps the HtmlEmail class from commons-email. Thus, it uses 62 * the JavaMail API and also depends on having the mail.server property 63 * set in the TurbineResources.properties file. If you want to use 64 * this class outside of Turbine for general processing that is also 65 * possible by making sure to set the path to the 66 * TurbineResources.properties. See the 67 * TurbineResourceService.setPropertiesFileName() method for more 68 * information. 69 * 70 * <p>This class is basically a conversion of the WebMacroHtmlEmail 71 * written by Regis Koenig 72 * 73 * <p>You can turn on debugging for the JavaMail API by calling 74 * setDebug(true). The debugging messages will be written to System.out. 75 * 76 * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a> 77 * @author <a href="mailto:A.Schild@aarboard.ch">Andre Schild</a> 78 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a> 79 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> 80 * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a> 81 * @version $Id: VelocityHtmlEmail.java 1706239 2015-10-01 13:18:35Z tv $ 82 */ 83 public class VelocityHtmlEmail extends HtmlEmail 84 { 85 /** Logging */ 86 private static Log log = LogFactory.getLog(VelocityHtmlEmail.class); 87 88 /** 89 * The html template to process, relative to VM's template 90 * directory. 91 */ 92 private String htmlTemplate = null; 93 94 /** 95 * The text template to process, relative to VM's template 96 * directory. 97 */ 98 private String textTemplate = null; 99 100 /** The cached context object. */ 101 private Context context = null; 102 103 /** The map of embedded files. */ 104 private Hashtable<String, String> embmap = null; 105 106 /** Address of outgoing mail server */ 107 private String mailServer; 108 109 /** 110 * Constructor, sets the context object from the passed {@link PipelineData} object 111 * 112 * @param pipelineData A Turbine {@link PipelineData} object. 113 */ 114 public VelocityHtmlEmail(PipelineData pipelineData) 115 { 116 this(TurbineVelocity.getContext(pipelineData)); 117 } 118 119 /** 120 * Constructor, sets the context object. 121 * 122 * @param context A Velocity context object. 123 */ 124 public VelocityHtmlEmail(Context context) 125 { 126 this.context = context; 127 embmap = new Hashtable<String, String>(); 128 } 129 130 /** 131 * Set the HTML template for the mail. This is the Velocity 132 * template to execute for the HTML part. Path is relative to the 133 * VM templates directory. 134 * 135 * @param template A String. 136 * @return A VelocityHtmlEmail (self). 137 */ 138 public VelocityHtmlEmail setHtmlTemplate(String template) 139 { 140 this.htmlTemplate = template; 141 return this; 142 } 143 144 /** 145 * Set the text template for the mail. This is the Velocity 146 * template to execute for the text part. Path is relative to the 147 * VM templates directory 148 * 149 * @param template A String. 150 * @return A VelocityHtmlEmail (self). 151 */ 152 public VelocityHtmlEmail setTextTemplate(String template) 153 { 154 this.textTemplate = template; 155 return this; 156 } 157 158 /** 159 * Sets the address of the outgoing mail server. This method 160 * should be used when you need to override the value stored in 161 * TR.props. 162 * 163 * @param serverAddress host name of your outgoing mail server 164 */ 165 public void setMailServer(String serverAddress) 166 { 167 this.mailServer = serverAddress; 168 } 169 170 /** 171 * Gets the host name of the outgoing mail server. If the server 172 * name has not been set by calling setMailServer(), the value 173 * from TR.props for mail.server will be returned. If TR.props 174 * has no value for mail.server, localhost will be returned. 175 * 176 * @return host name of the mail server. 177 */ 178 public String getMailServer() 179 { 180 return StringUtils.isNotEmpty(mailServer) ? mailServer 181 : Turbine.getConfiguration().getString( 182 TurbineConstants.MAIL_SERVER_KEY, 183 TurbineConstants.MAIL_SERVER_DEFAULT); 184 } 185 186 /** 187 * Actually send the mail. 188 * 189 * @exception EmailException thrown if mail cannot be sent. 190 */ 191 @Override 192 public String send() throws EmailException 193 { 194 context.put("mail", this); 195 196 try 197 { 198 if (htmlTemplate != null) 199 { 200 setHtmlMsg( 201 TurbineVelocity.handleRequest(context, htmlTemplate)); 202 } 203 if (textTemplate != null) 204 { 205 setTextMsg( 206 TurbineVelocity.handleRequest(context, textTemplate)); 207 } 208 } 209 catch (Exception e) 210 { 211 throw new EmailException("Cannot parse velocity template", e); 212 } 213 setHostName(getMailServer()); 214 return super.send(); 215 } 216 217 /** 218 * Embed a file in the mail. The file can be referenced through 219 * its Content-ID. This function also registers the CID in an 220 * internal map, so the embedded file can be referenced more than 221 * once by using the getCid() function. This may be useful in a 222 * template. 223 * 224 * <p>Example of template: 225 * 226 * <code><pre width="80"> 227 * <html> 228 * <!-- $mail.embed("http://server/border.gif","border.gif"); --> 229 * <img src=$mail.getCid("border.gif")> 230 * <p>This is your content 231 * <img src=$mail.getCid("border.gif")> 232 * </html> 233 * </pre></code> 234 * 235 * @param surl A String. 236 * @param name A String. 237 * @return A String with the cid of the embedded file. 238 * 239 * @see HtmlEmail#embed(URL surl, String name) embed. 240 */ 241 @Override 242 public String embed(String surl, String name) 243 { 244 String cid = ""; 245 try 246 { 247 URL url = new URL(surl); 248 cid = super.embed(url, name); 249 embmap.put(name, cid); 250 } 251 catch (Exception e) 252 { 253 log.error("cannot embed " + surl + ": ", e); 254 } 255 return cid; 256 } 257 258 /** 259 * Get the cid of an embedded file. 260 * 261 * @param filename A String. 262 * @return A String with the cid of the embedded file. 263 * @see #embed(String surl, String name) embed. 264 */ 265 public String getCid(String filename) 266 { 267 String cid = embmap.get(filename); 268 return "cid:" + cid; 269 } 270 271 }