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 }