001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.notification; 029 030import org.opencms.db.CmsUserSettings; 031import org.opencms.file.CmsFile; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsUser; 035import org.opencms.file.CmsVfsResourceNotFoundException; 036import org.opencms.i18n.CmsMessages; 037import org.opencms.mail.CmsHtmlMail; 038import org.opencms.main.CmsException; 039import org.opencms.main.CmsLog; 040import org.opencms.main.OpenCms; 041import org.opencms.util.CmsMacroResolver; 042import org.opencms.util.CmsStringUtil; 043import org.opencms.xml.content.CmsXmlContent; 044import org.opencms.xml.content.CmsXmlContentFactory; 045 046import java.util.List; 047import java.util.Locale; 048import java.util.regex.Pattern; 049 050import javax.mail.MessagingException; 051 052import org.apache.commons.logging.Log; 053import org.apache.commons.mail.EmailException; 054 055/** 056 * Abstract class to create a notfication which will be send as a html mail to 057 * a user in OpenCms. 058 * 059 * @since 6.5.3 060 */ 061public abstract class A_CmsNotification extends CmsHtmlMail { 062 063 /** Path to optional config file containing header and footer. */ 064 public static final String HEADER_FOOTER_CONFIG_PATH = "notification-header-footer.html"; 065 066 /** Separator between header and footer in optional config file. */ 067 public static final String HEADER_FOOTER_SEPARATOR = Pattern.quote("$BODY"); 068 069 /** The log object for this class. */ 070 private static final Log LOG = CmsLog.getLog(A_CmsNotification.class); 071 072 /** The configured header. */ 073 protected String m_configuredHeader; 074 075 /** The configured footer. */ 076 protected String m_configuredFooter; 077 078 /** The xml-content to read subject, header and footer of the notification. */ 079 protected CmsXmlContent m_mailContent; 080 081 /** The CmsObject. */ 082 protected CmsObject m_cms; 083 084 /** The locale of the receiver of the content notification. */ 085 protected Locale m_locale; 086 087 /** The macro resolver used. */ 088 protected CmsNotificationMacroResolver m_macroResolver; 089 090 /** The receiver of the notification. */ 091 private CmsUser m_receiver; 092 093 /** 094 * Creates a new A_CmsNotification.<p> 095 * 096 * @param cms the cms object to use 097 * @param receiver the receiver of the notification 098 */ 099 public A_CmsNotification(CmsObject cms, CmsUser receiver) { 100 101 m_cms = cms; 102 m_receiver = receiver; 103 104 m_macroResolver = new CmsNotificationMacroResolver(cms, receiver); 105 m_macroResolver.setCmsObject(cms); 106 } 107 108 /** 109 * Adds a new macro to the used macro resolver. Macros are used for the xml 110 * content file. 111 * 112 * @param key The key of the macro. 113 * @param value The value of the macro. 114 */ 115 public void addMacro(String key, String value) { 116 117 m_macroResolver.addMacro(key, value); 118 } 119 120 /** 121 * Returns the CmsObject.<p> 122 * 123 * @return the CmsObject 124 */ 125 public CmsObject getCmsObject() { 126 127 return m_cms; 128 } 129 130 /** 131 * Returns the locale.<p> 132 * 133 * @return the locale 134 */ 135 public Locale getLocale() { 136 137 return m_locale; 138 } 139 140 /** 141 * Returns the receiver.<p> 142 * 143 * @return the receiver 144 */ 145 public CmsUser getReceiver() { 146 147 return m_receiver; 148 } 149 150 /** 151 * @see org.apache.commons.mail.Email#send() 152 */ 153 @Override 154 public String send() throws EmailException { 155 156 String messageID = null; 157 try { 158 // check if user is valid and has a mail address specified 159 if (CmsStringUtil.isEmpty(m_receiver.getEmail())) { 160 LOG.error(Messages.get().getBundle().key(Messages.LOG_NOTIFICATION_NO_ADDRESS_1, m_receiver.getName())); 161 return null; 162 } 163 164 if (LOG.isInfoEnabled()) { 165 LOG.info(Messages.get().getBundle().key(Messages.LOG_NOTIFICATION_SEND_1, m_receiver.getEmail())); 166 } 167 168 // read resource with subject, header and footer 169 m_mailContent = CmsXmlContentFactory.unmarshal(m_cms, m_cms.readFile(getNotificationContent())); 170 171 // detect locale 172 List<Locale> locales = m_mailContent.getLocales(); 173 Locale userLocale = new CmsUserSettings(m_receiver).getLocale(); 174 if (locales.contains(userLocale)) { 175 // mail is localized in the user locale, use that 176 m_locale = userLocale; 177 } else if (locales.contains(OpenCms.getWorkplaceManager().getDefaultLocale())) { 178 // mail is localized in the system default locale, use that 179 m_locale = OpenCms.getWorkplaceManager().getDefaultLocale(); 180 } else { 181 // use any localization 182 m_locale = locales.get(0); 183 } 184 185 String mailCharset = Messages.get().getBundle(m_locale).key(Messages.GUI_MAIL_CHARSET_0); 186 if (!CmsMessages.isUnknownKey(mailCharset)) { 187 setCharset(mailCharset); 188 } 189 190 // define macro resolver 191 //TODO Remove when old notifications were adjusted 192 m_macroResolver.addMacro("firstname", m_receiver.getFirstname()); 193 m_macroResolver.addMacro("lastname", m_receiver.getLastname()); 194 m_macroResolver.addMacro("project", m_cms.getRequestContext().getCurrentProject().getName()); 195 try { 196 CmsResource configRes = m_cms.readResource( 197 OpenCms.getSystemInfo().getConfigFilePath(m_cms, HEADER_FOOTER_CONFIG_PATH)); 198 CmsFile configFile = m_cms.readFile(configRes); 199 String configContent = new String(configFile.getContents(), "UTF-8"); 200 String[] configParts = configContent.split(HEADER_FOOTER_SEPARATOR); 201 if (configParts.length == 2) { 202 m_configuredHeader = configParts[0]; 203 m_configuredFooter = configParts[1]; 204 } else { 205 LOG.error("Invalid notification header/footer configuration: " + HEADER_FOOTER_CONFIG_PATH); 206 } 207 } catch (CmsVfsResourceNotFoundException e) { 208 LOG.debug(e.getLocalizedMessage(), e); 209 } catch (Exception e) { 210 LOG.error(e.getLocalizedMessage(), e); 211 } 212 213 StringBuffer msg = new StringBuffer(); 214 215 // append html header 216 appendHtmlHeader(msg); 217 appendXMLContent(msg); 218 219 // append html footer 220 appenHtmlFooter(msg); 221 222 addTo(m_receiver.getEmail(), m_receiver.getFirstname() + ' ' + m_receiver.getLastname()); 223 setSubject( 224 CmsMacroResolver.resolveMacros( 225 m_mailContent.getStringValue(m_cms, "Subject", m_locale), 226 m_macroResolver)); 227 setHtmlMsg(msg.toString()); 228 229 // send mail 230 super.send(); 231 232 // get MIME message ID 233 messageID = getMimeMessage().getMessageID(); 234 235 } catch (CmsException e) { 236 LOG.error(Messages.get().getBundle().key(Messages.LOG_NOTIFICATION_SEND_ERROR_0), e); 237 } catch (MessagingException e) { 238 LOG.error(Messages.get().getBundle().key(Messages.LOG_NOTIFICATION_SEND_ERROR_0), e); 239 } 240 return messageID; 241 } 242 243 /** 244 * Append the html-code to start a html mail message to the given buffer.<p> 245 * 246 * @param buffer The StringBuffer to add the html code to. 247 */ 248 protected void appendHtmlHeader(StringBuffer buffer) { 249 250 if (m_configuredHeader != null) { 251 buffer.append(m_configuredHeader); 252 } else { 253 buffer.append("<html>\r\n"); 254 buffer.append(" <head>\r\n"); 255 buffer.append(" <style type=\"text/css\">\r\n"); 256 buffer.append( 257 " body { font-family: Verdana, Arial, Helvetica, sans-serif; background-color:white; }\r\n"); 258 buffer.append(" a { color:#b31b43; text-decoration:none; font-weight: bold; }\r\n"); 259 buffer.append(" a:hover { color:#b31b43; text-decoration:underline; font-weight: bold; }\r\n"); 260 buffer.append(" div.publish_link { margin: 20px 0; }\r\n"); 261 buffer.append(" table { white-space: nowrap; font-size: small; }\r\n"); 262 buffer.append(" tr.trow1 { background-color: #cdc0b0; }\r\n"); 263 buffer.append(" tr.trow2 { background-color: #eedfcc; }\r\n"); 264 buffer.append(" tr.trow3 { background-color: #ffefdb; }\r\n"); 265 buffer.append( 266 " th.rescol { border-width: 1px 0 2px 1px; border-style: solid; border-color: #222222; padding: 5px; }\r\n"); 267 buffer.append( 268 " th.titlecol { border-width: 1px 1px 2px 1px; border-style: solid; border-color: #222222; padding: 5px; }\r\n"); 269 buffer.append( 270 " td.rescol { border-width: 0 0 1px 1px; border-style: solid; border-color: #222222; padding: 5px; }\r\n"); 271 buffer.append( 272 " td.titlecol { border-width: 0 1px 1px 1px; border-style: solid; border-color: #222222; padding: 5px; }\r\n"); 273 buffer.append(" </style>\r\n"); 274 buffer.append(" </head>\r\n"); 275 buffer.append(" <body>\r\n"); 276 } 277 } 278 279 /** 280 * Append XMLContent to StringBuffer.<p> 281 * 282 * @param msg StringBuffer 283 */ 284 protected void appendXMLContent(StringBuffer msg) { 285 286 // append header from xmlcontent 287 msg.append( 288 CmsMacroResolver.resolveMacros(m_mailContent.getStringValue(m_cms, "Header", m_locale), m_macroResolver)); 289 290 // append body 291 msg.append("\n<br/><br/>\n"); 292 msg.append(generateHtmlMsg()); 293 msg.append("\n<br/><br/>\n"); 294 295 // append footer from xmlcontent 296 msg.append( 297 CmsMacroResolver.resolveMacros(m_mailContent.getStringValue(m_cms, "Footer", m_locale), m_macroResolver)); 298 } 299 300 /** 301 * Append the html-code to finish a html mail message to the given buffer. 302 * 303 * @param buffer The StringBuffer to add the html code to. 304 */ 305 protected void appenHtmlFooter(StringBuffer buffer) { 306 307 if (m_configuredFooter != null) { 308 buffer.append(m_configuredFooter); 309 } else { 310 buffer.append(" </body>\r\n" + "</html>"); 311 } 312 } 313 314 /** 315 * Overwrite the method to generate the message body of the notification. This 316 * text is placed between the header and the footer of the defined xmlcontent 317 * and the required html code is added.<p> 318 * 319 * @return The text to be inserted in the notification. 320 */ 321 protected abstract String generateHtmlMsg(); 322 323 /** 324 * Overwrite the method to return the path to the xmlcontent, where the subject, 325 * the header and the footer are defined.<p> 326 * 327 * @return The path to the xmlcontent file. 328 */ 329 protected abstract String getNotificationContent(); 330}