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