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.services.TurbineServices; 35 import org.apache.turbine.services.velocity.VelocityService; 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 1773378 2016-12-09 13:19:59Z 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 111 */ 112 public VelocityHtmlEmail() 113 { 114 super(); 115 } 116 117 /** 118 * Constructor, sets the context object. 119 * 120 * @param context A Velocity context object. 121 */ 122 public VelocityHtmlEmail(Context context) 123 { 124 this(); 125 this.context = context; 126 embmap = new Hashtable<String, String>(); 127 } 128 129 /** 130 * Set the HTML template for the mail. This is the Velocity 131 * template to execute for the HTML part. Path is relative to the 132 * VM templates directory. 133 * 134 * @param template A String. 135 * @return A VelocityHtmlEmail (self). 136 */ 137 public VelocityHtmlEmail setHtmlTemplate(String template) 138 { 139 this.htmlTemplate = template; 140 return this; 141 } 142 143 /** 144 * Set the text template for the mail. This is the Velocity 145 * template to execute for the text 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 setTextTemplate(String template) 152 { 153 this.textTemplate = template; 154 return this; 155 } 156 157 /** 158 * Sets the address of the outgoing mail server. This method 159 * should be used when you need to override the value stored in 160 * TR.props. 161 * 162 * @param serverAddress host name of your outgoing mail server 163 */ 164 public void setMailServer(String serverAddress) 165 { 166 this.mailServer = serverAddress; 167 } 168 169 /** 170 * Gets the host name of the outgoing mail server. If the server 171 * name has not been set by calling setMailServer(), the value 172 * from TR.props for mail.server will be returned. If TR.props 173 * has no value for mail.server, localhost will be returned. 174 * 175 * @return host name of the mail server. 176 */ 177 public String getMailServer() 178 { 179 return StringUtils.isNotEmpty(mailServer) ? mailServer 180 : Turbine.getConfiguration().getString( 181 TurbineConstants.MAIL_SERVER_KEY, 182 TurbineConstants.MAIL_SERVER_DEFAULT); 183 } 184 185 /** 186 * Actually send the mail. 187 * 188 * @throws EmailException thrown if mail cannot be sent. 189 */ 190 @Override 191 public String send() throws EmailException 192 { 193 context.put("mail", this); 194 195 try 196 { 197 VelocityService velocityService = (VelocityService)TurbineServices.getInstance().getService(VelocityService.SERVICE_NAME); 198 199 if (htmlTemplate != null) 200 { 201 setHtmlMsg(velocityService.handleRequest(context, htmlTemplate)); 202 } 203 if (textTemplate != null) 204 { 205 setTextMsg(velocityService.handleRequest(context, textTemplate)); 206 } 207 } 208 catch (Exception e) 209 { 210 throw new EmailException("Cannot parse velocity template", e); 211 } 212 setHostName(getMailServer()); 213 return super.send(); 214 } 215 216 /** 217 * Embed a file in the mail. The file can be referenced through 218 * its Content-ID. This function also registers the CID in an 219 * internal map, so the embedded file can be referenced more than 220 * once by using the getCid() function. This may be useful in a 221 * template. 222 * 223 * <p>Example of template: 224 * 225 * <pre> 226 * <html> 227 * <!-- $mail.embed("http://server/border.gif","border.gif"); --> 228 * <img src=$mail.getCid("border.gif")> 229 * <p>This is your content 230 * <img src=$mail.getCid("border.gif")> 231 * </html> 232 * </pre> 233 * 234 * @param surl A String. 235 * @param name A String. 236 * @return A String with the cid of the embedded file. 237 * 238 * @see HtmlEmail#embed(URL surl, String name) embed. 239 */ 240 @Override 241 public String embed(String surl, String name) 242 { 243 String cid = ""; 244 try 245 { 246 URL url = new URL(surl); 247 cid = super.embed(url, name); 248 embmap.put(name, cid); 249 } 250 catch (Exception e) 251 { 252 log.error("cannot embed " + surl + ": ", e); 253 } 254 return cid; 255 } 256 257 /** 258 * Get the cid of an embedded file. 259 * 260 * @param filename A String. 261 * @return A String with the cid of the embedded file. 262 * @see #embed(String surl, String name) embed. 263 */ 264 public String getCid(String filename) 265 { 266 String cid = embmap.get(filename); 267 return "cid:" + cid; 268 } 269 270 }