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 }