1 16 package com.blandware.atleap.service.util; 17 18 import com.blandware.atleap.common.Constants; 19 import com.blandware.atleap.common.parsers.html.HTMLPlainTextExtractor; 20 import com.blandware.atleap.common.util.ConvertUtil; 21 import com.blandware.atleap.common.util.RegExUtil; 22 import com.blandware.atleap.common.util.StringUtil; 23 import com.blandware.atleap.model.core.ContentField; 24 import com.blandware.atleap.model.core.ContentFieldValue; 25 import com.blandware.atleap.model.core.ContentLocale; 26 import com.blandware.atleap.model.core.ContentResource; 27 import com.blandware.atleap.model.core.MailTemplate; 28 import com.blandware.atleap.persistence.core.ContentLocaleDAO; 29 import com.blandware.atleap.persistence.core.ContentResourceDAO; 30 import com.blandware.atleap.persistence.core.MailTemplateDAO; 31 import com.blandware.atleap.service.exception.BeanNotFoundException; 32 import com.blandware.atleap.service.exception.MailAddressException; 33 import org.apache.commons.logging.Log; 34 import org.apache.commons.logging.LogFactory; 35 import org.apache.oro.text.regex.MalformedPatternException; 36 import org.apache.velocity.app.VelocityEngine; 37 import org.apache.velocity.exception.ResourceNotFoundException; 38 import org.apache.velocity.exception.VelocityException; 39 import org.springframework.core.io.InputStreamSource; 40 import org.springframework.mail.MailPreparationException; 41 import org.springframework.mail.javamail.JavaMailSender; 42 import org.springframework.mail.javamail.MimeMessageHelper; 43 import org.springframework.ui.velocity.VelocityEngineUtils; 44 45 import javax.mail.MessagingException ; 46 import javax.mail.internet.InternetAddress ; 47 import javax.mail.internet.MimeMessage ; 48 import java.io.ByteArrayInputStream ; 49 import java.io.IOException ; 50 import java.io.InputStream ; 51 import java.util.Date ; 52 import java.util.HashMap ; 53 import java.util.HashSet ; 54 import java.util.Iterator ; 55 import java.util.Map ; 56 import java.util.Set ; 57 58 59 68 public class MailEngine { 69 70 73 protected transient final Log log = LogFactory.getLog(MailEngine.class); 74 75 78 protected JavaMailSender mailSender; 79 80 83 protected VelocityEngine velocityEngine; 84 85 88 protected MailTemplateDAO mailTemplateDAO; 89 90 93 protected ContentLocaleDAO contentLocaleDAO; 94 95 98 protected ContentResourceDAO contentResourceDAO; 99 100 105 public void setMailSender(JavaMailSender mailSender) { 106 this.mailSender = mailSender; 107 } 108 109 114 public void setVelocityEngine(VelocityEngine velocityEngine) { 115 this.velocityEngine = velocityEngine; 116 } 117 118 124 public void setMailTemplateDAO(MailTemplateDAO mailTemplateDAO) { 125 this.mailTemplateDAO = mailTemplateDAO; 126 } 127 128 134 public void setContentLocaleDAO(ContentLocaleDAO contentLocaleDAO) { 135 this.contentLocaleDAO = contentLocaleDAO; 136 } 137 138 144 public void setContentResourceDAO(ContentResourceDAO contentResourceDAO) { 145 this.contentResourceDAO = contentResourceDAO; 146 } 147 148 161 public void sendMessage(String from, String subject, String [] to, String [] cc, String [] bcc, String templateIdentifier, String locale, Map model) { 162 163 if ( to == null || to.length == 0 ) { 164 throw new MailPreparationException("No recipient specified"); 165 } 166 167 MimeMessage message = null; 168 try { 169 message = createMessage(from, subject, to, cc, bcc, templateIdentifier, locale, model); 170 } catch ( Exception e ) { 171 throw new MailPreparationException(e); 172 } 173 send(message); 174 } 175 176 188 public void sendMessage(String [] to, String [] cc, String [] bcc, String templateIdentifier, String locale, Map model) { 189 sendMessage(null, null, to, cc, bcc, templateIdentifier, locale, model); 190 } 191 192 202 public void sendMessage(String [] to, String templateIdentifier, String locale, Map model) { 203 sendMessage(to, null, null, templateIdentifier, locale, model); 204 } 205 206 216 public void sendMessage(String to, String templateIdentifier, String locale, Map model) { 217 sendMessage(new String []{to}, templateIdentifier, locale, model); 218 } 219 220 233 protected MimeMessage createMessage(String from, String subject, String [] to, String [] cc, String [] bcc, String templateIdentifier, String locale, Map model) throws BeanNotFoundException, VelocityException { 234 MailTemplate mailTemplate = mailTemplateDAO.findMailTemplateByIdentifier(templateIdentifier); 235 if ( mailTemplate == null ) { 236 throw new BeanNotFoundException("No template with identifier '" + templateIdentifier + "' could be found"); 237 } 238 MimeMessageHelper messageHelper = null; 239 String charset = (String ) mailTemplate.getCharset().get(locale); 240 if ( charset == null || charset.length() == 0 ) { 241 charset = Constants.DEFAULT_ENCODING; 242 } 243 244 boolean plain = mailTemplate.isPlain(); 245 246 if ( from == null || from.length() == 0 ) { 247 from = mergeTemplate(templateIdentifier, "from", locale, model); 248 } 249 250 if ( subject == null || subject.length() == 0 ) { 251 subject = mergeTemplate(templateIdentifier, "subject", locale, model); 252 } 253 254 String text = mergeTemplate(templateIdentifier, "body", locale, model); 255 256 258 try { 259 text = RegExUtil.replaceAll(text, "<br\040*/?>", "<br />"); 260 } catch ( MalformedPatternException e ) { 261 } 263 264 InternetAddress fromAddress = prepareAddress(from, charset); 265 InternetAddress [] toAddresses = prepareAddresses(to, charset); 266 267 try { 268 messageHelper = createEmptyMessageHelper(charset, !plain, false); 269 messageHelper.setFrom(fromAddress); 270 messageHelper.setReplyTo(fromAddress); 271 messageHelper.setSubject(subject); 272 messageHelper.setTo(toAddresses); 273 if ( cc != null ) { 274 InternetAddress [] ccAddresses = prepareAddresses(cc, charset); 275 messageHelper.setCc(ccAddresses); 276 } 277 if ( bcc != null ) { 278 InternetAddress [] bccAddresses = prepareAddresses(bcc, charset); 279 messageHelper.setBcc(bccAddresses); 280 } 281 messageHelper.setSentDate(new Date ()); 282 if ( !plain ) { 283 prepareMimeMessage(messageHelper, text); 284 } else { 285 messageHelper.setText(text, true); 288 } 289 } catch ( MessagingException e ) { 290 throw new MailPreparationException(e); 291 } 292 293 return messageHelper.getMimeMessage(); 294 } 295 296 304 protected MimeMessageHelper createEmptyMessageHelper(String charset, boolean multipart, boolean validate) throws MessagingException { 305 MimeMessage message = mailSender.createMimeMessage(); 306 MimeMessageHelper messageHelper = new MimeMessageHelper(message, multipart, charset); 307 messageHelper.setValidateAddresses(validate); 308 return messageHelper; 309 } 310 311 317 protected void prepareMimeMessage(MimeMessageHelper helper, String text) { 318 try { 319 HTMLPlainTextExtractor extractor = new HTMLPlainTextExtractor(); 320 Set resourceUris = new HashSet (extractor.extractInlineResources(new ByteArrayInputStream (ConvertUtil.convertToByteArray(text)), Constants.DEFAULT_ENCODING)); 321 Map resourcesMap = new HashMap (); 322 for ( Iterator i = resourceUris.iterator(); i.hasNext(); ) { 323 String src = (String ) i.next(); 324 String prefix = Constants.RESOURCES_URI_PREFIX; 325 if ( prefix.startsWith("/") ) { 326 prefix = prefix.substring(1); 327 } 328 329 int k = src.indexOf(prefix); 330 if ( k == -1 ) { 331 continue; 333 } 334 335 String resourceUri = src.substring(k); 336 if ( !resourceUri.startsWith("/") ) { 337 resourceUri = "/" + resourceUri; 338 } 339 340 ContentResource resource = contentResourceDAO.findContentResourceByUri(resourceUri); 341 if ( resource != null ) { 342 String cid = "resource" + resource.getId(); 343 resourcesMap.put(cid, resource); 344 text = text.replaceAll("=\"" + src + "\"", "=\"cid:" + cid + "\""); 345 } 346 } 347 348 helper.setText(text, true); 349 350 for ( Iterator i = resourcesMap.entrySet().iterator(); i.hasNext(); ) { 352 Map.Entry entry = (Map.Entry ) i.next(); 353 String cid = (String ) entry.getKey(); 354 ContentResource resource = (ContentResource) entry.getValue(); 355 helper.addInline(cid, new InputStreamContentResource(resource), resource.getMimeType()); 356 } 357 358 } catch ( Exception e ) { 359 throw new MailPreparationException(e); 360 } 361 362 } 363 364 372 public InternetAddress prepareAddress(String address, String charset) { 373 return prepareAddresses(new String []{address}, charset)[0]; 374 } 375 376 386 public InternetAddress [] prepareAddresses(String [] addresses, String charset) { 387 InternetAddress [] internetAddresses = new InternetAddress [addresses.length]; 388 try { 389 for ( int i = 0; i < addresses.length; i++ ) { 390 String address = addresses[i]; 391 InternetAddress internetAddress = new InternetAddress (address); 392 internetAddress.setPersonal(internetAddress.getPersonal(), charset); 393 internetAddresses[i] = internetAddress; 394 } 395 } catch ( Exception e ) { 396 throw new MailAddressException(e.getLocalizedMessage()); 397 } 398 return internetAddresses; 399 } 400 401 408 protected void send(MimeMessage msg) { 409 mailSender.send(msg); 410 } 411 412 421 public String mergeTemplate(String identifier, String field, String locale, Map model) throws VelocityException { 422 return mergeTemplate(identifier, field, locale, model, true); 423 } 424 425 426 436 public String mergeTemplate(String identifier, String field, String locale, Map model, boolean encodeModel) throws VelocityException { 437 String result = null; 438 439 MailTemplate mailTemplate = mailTemplateDAO.findMailTemplateByIdentifier(identifier); 441 if ( mailTemplate == null ) { 442 throw new ResourceNotFoundException("Mail template with identifier '" + identifier + "' could not be found"); 443 } 444 445 ContentField requestedField = (ContentField) mailTemplate.getContentFieldsMap().get(field); 446 if ( requestedField == null ) { 447 throw new ResourceNotFoundException("Content field with identifier '" + field + "' could not be found on mail template '" + identifier + "' (ID=" + mailTemplate.getId() + ")"); 448 } 449 450 Map contentFieldValues = requestedField.getContentFieldValuesMap(); 451 ContentFieldValue templateValue = null; 452 if ( contentFieldValues != null && !contentFieldValues.isEmpty() ) { 453 templateValue = (ContentFieldValue) contentFieldValues.get(locale); 455 456 if ( templateValue == null || isEmpty(templateValue) ) { 458 459 if ( log.isWarnEnabled() ) { 460 log.warn("No value of content field with ID=" + requestedField.getId() + " could be found for locale '" + locale + "' Trying to search by default locale..."); 461 } 462 463 ContentLocale defaultLocale = contentLocaleDAO.findDefaultContentLocale(); 464 templateValue = (ContentFieldValue) contentFieldValues.get(defaultLocale.getIdentifier()); 465 466 if ( templateValue == null || isEmpty(templateValue) ) { 468 if ( log.isWarnEnabled() ) { 469 log.warn("No value for default locale could be found. Getting the first one..."); 470 } 471 templateValue = (ContentFieldValue) contentFieldValues.values().iterator().next(); 472 } 473 } 474 } else { 475 throw new ResourceNotFoundException("No content field value could be found on field with ID=" + requestedField.getId()); 476 } 477 478 String template = ConvertUtil.convertToString(templateValue.getValue()); 480 481 if ( template == null ) { 483 template = templateValue.getSimpleValue(); 484 } 485 486 template = "mailTemplate: " + template; 487 488 if ( encodeModel ) { 489 model = StringUtil.htmlEncodeModel(model); 490 } 491 result = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, template, model); 492 493 return result; 494 } 495 496 502 protected boolean isEmpty(ContentFieldValue value) { 503 return (value.getSimpleValue() == null || value.getSimpleValue().length() == 0) && (value.getValue() == null || value.getValue().length == 0); 504 } 505 506 509 protected static class InputStreamContentResource implements InputStreamSource { 510 511 514 protected ContentResource contentResource; 515 516 521 public InputStreamContentResource(ContentResource contentResource) { 522 this.contentResource = contentResource; 523 } 524 525 528 public InputStream getInputStream() throws IOException { 529 InputStream stream = null; 530 if ( contentResource != null ) { 531 stream = new ByteArrayInputStream (contentResource.getResourceData().getData()); 532 } 533 return stream; 534 } 535 } 536 } 537 | Popular Tags |