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 }