001 package railo.runtime.net.smtp; 002 003 import java.io.FileNotFoundException; 004 import java.io.Serializable; 005 import java.io.UnsupportedEncodingException; 006 import java.net.URL; 007 import java.text.SimpleDateFormat; 008 import java.util.ArrayList; 009 import java.util.Date; 010 import java.util.Iterator; 011 import java.util.Locale; 012 import java.util.Map; 013 import java.util.Properties; 014 import java.util.TimeZone; 015 016 import javax.activation.DataHandler; 017 import javax.mail.Authenticator; 018 import javax.mail.BodyPart; 019 import javax.mail.Message; 020 import javax.mail.MessagingException; 021 import javax.mail.Multipart; 022 import javax.mail.internet.AddressException; 023 import javax.mail.internet.InternetAddress; 024 import javax.mail.internet.MimeBodyPart; 025 import javax.mail.internet.MimeMessage; 026 import javax.mail.internet.MimeMultipart; 027 import javax.mail.internet.MimePart; 028 029 import org.apache.commons.collections.ReferenceMap; 030 031 import railo.commons.activation.ResourceDataSource; 032 import railo.commons.collections.HashTable; 033 import railo.commons.io.SystemUtil; 034 import railo.commons.io.log.LogAndSource; 035 import railo.commons.io.log.LogUtil; 036 import railo.commons.io.res.Resource; 037 import railo.commons.io.res.util.ResourceUtil; 038 import railo.commons.lang.SerializableObject; 039 import railo.commons.lang.StringUtil; 040 import railo.runtime.config.Config; 041 import railo.runtime.config.ConfigImpl; 042 import railo.runtime.engine.ThreadLocalPageContext; 043 import railo.runtime.exp.ExpressionException; 044 import railo.runtime.exp.PageException; 045 import railo.runtime.net.mail.EmailNamePair; 046 import railo.runtime.net.mail.MailException; 047 import railo.runtime.net.mail.MailPart; 048 import railo.runtime.net.mail.MailUtil; 049 import railo.runtime.net.mail.Server; 050 import railo.runtime.net.mail.ServerImpl; 051 import railo.runtime.net.proxy.Proxy; 052 import railo.runtime.net.proxy.ProxyData; 053 import railo.runtime.net.proxy.ProxyDataImpl; 054 import railo.runtime.net.smtp.SMTPConnectionPool.SessionAndTransport; 055 import railo.runtime.op.Caster; 056 import railo.runtime.spooler.mail.MailSpoolerTask; 057 import railo.runtime.type.List; 058 import railo.runtime.type.util.ArrayUtil; 059 060 import com.sun.mail.smtp.SMTPMessage; 061 062 public final class SMTPClient implements Serializable { 063 064 065 066 /** 067 * 068 */ 069 private static final long serialVersionUID = 5227282806519740328L; 070 071 private static final int SPOOL_UNDEFINED=0; 072 private static final int SPOOL_YES=1; 073 private static final int SPOOL_NO=2; 074 075 private static final int SSL_NONE=0; 076 private static final int SSL_YES=1; 077 private static final int SSL_NO=2; 078 079 private static final int TLS_NONE=0; 080 private static final int TLS_YES=1; 081 private static final int TLS_NO=2; 082 083 private static final String TEXT_HTML = "text/html"; 084 private static final String TEXT_PLAIN = "text/plain"; 085 private static final SerializableObject LOCK = new SerializableObject(); 086 087 private static Map<TimeZone, SimpleDateFormat> formatters=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT); 088 //private static final int PORT = 25; 089 090 private int spool=SPOOL_UNDEFINED; 091 092 private int timeout=-1; 093 094 private String plainText; 095 private String plainTextCharset; 096 097 private String htmlText; 098 099 100 private String htmlTextCharset; 101 102 private Attachment[] attachmentz; 103 104 private String[] host; 105 private String charset="UTF-8"; 106 private InternetAddress from; 107 private InternetAddress[] tos; 108 private InternetAddress[] bccs; 109 private InternetAddress[] ccs; 110 private InternetAddress[] rts; 111 private InternetAddress[] fts; 112 private String subject=""; 113 private String xmailer="Railo Mail"; 114 private Map headers=new HashTable(); 115 private int port=-1; 116 117 private String username; 118 private String password=""; 119 120 121 122 123 private int ssl=SSL_NONE; 124 private int tls=TLS_NONE; 125 126 ProxyData proxyData=new ProxyDataImpl(); 127 private ArrayList<MailPart> parts; 128 129 private TimeZone timeZone; 130 131 132 public static String getNow(TimeZone tz){ 133 tz = ThreadLocalPageContext.getTimeZone(tz); 134 SimpleDateFormat df=formatters.get(tz); 135 if(df==null) { 136 df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z (z)",Locale.US); 137 df.setTimeZone(tz); 138 formatters.put(tz, df); 139 } 140 return df.format(new Date()); 141 } 142 143 144 public void setSpoolenable(boolean spoolenable) { 145 spool=spoolenable?SPOOL_YES:SPOOL_NO; 146 } 147 148 /** 149 * set port of the mailserver 150 * @param port 151 */ 152 public void setPort(int port) { 153 this.port=port; 154 } 155 156 /** 157 * @param charset the charset to set 158 */ 159 public void setCharset(String charset) { 160 this.charset = charset; 161 } 162 163 164 public static ServerImpl toServerImpl(String server,int port, String usr,String pwd) throws MailException { 165 int index; 166 167 // username/password 168 index=server.indexOf('@'); 169 if(index!=-1) { 170 usr=server.substring(0,index); 171 server=server.substring(index+1); 172 index=usr.indexOf(':'); 173 if(index!=-1) { 174 pwd=usr.substring(index+1); 175 usr=usr.substring(0,index); 176 } 177 } 178 179 // port 180 index=server.indexOf(':'); 181 if(index!=-1) { 182 try { 183 port=Caster.toIntValue(server.substring(index+1)); 184 } catch (ExpressionException e) { 185 throw new MailException(e.getMessage()); 186 } 187 server=server.substring(0,index); 188 } 189 190 191 ServerImpl srv = ServerImpl.getInstance(server, port, usr, pwd, false, false); 192 return srv; 193 } 194 195 196 /** 197 * @throws PageException 198 * @throws MailException 199 * @see mail.Mail#setHost(java.lang.String) 200 */ 201 public void setHost(String host) throws PageException { 202 if(!StringUtil.isEmpty(host,true))this.host = List.toStringArray(List.listToArrayRemoveEmpty(host, ',')); 203 } 204 205 /** 206 * @param password the password to set 207 */ 208 public void setPassword(String password) { 209 this.password = password; 210 } 211 212 /** 213 * @param username the username to set 214 */ 215 public void setUsername(String username) { 216 this.username = username; 217 } 218 219 220 public void addHeader(String name, String value) { 221 headers.put(name, value); 222 } 223 224 /** 225 * @see mail.Mail#addTo(javax.mail.internet.InternetAddress) 226 */ 227 public void addTo(InternetAddress to) { 228 tos=add(tos,to); 229 } 230 231 /** 232 * @throws UnsupportedEncodingException 233 * @throws AddressException 234 * @throws PageException 235 * @throws MailException 236 * @see mail.Mail#addTo(java.lang.String) 237 */ 238 public void addTo(Object to) throws AddressException, UnsupportedEncodingException, PageException, MailException { 239 InternetAddress[] tmp = EmailNamePair.toInternetAddresses(to); 240 for(int i=0;i<tmp.length;i++) { 241 addTo(tmp[i]); 242 } 243 } 244 245 /** 246 * @see mail.Mail#setFrom(javax.mail.internet.InternetAddress) 247 */ 248 public void setFrom(InternetAddress from) { 249 this.from=from; 250 } 251 252 /** 253 * @throws MailException 254 * @throws UnsupportedEncodingException 255 * @throws AddressException 256 * @throws PageException 257 * @see mail.Mail#setFrom(java.lang.String) 258 */ 259 public void setFrom(Object from) throws AddressException, UnsupportedEncodingException, MailException, PageException { 260 InternetAddress[] addrs = EmailNamePair.toInternetAddresses(from); 261 if(addrs.length==0) return; 262 setFrom(addrs[0]); 263 } 264 /** 265 * @see mail.Mail#addBCC(javax.mail.internet.InternetAddress) 266 */ 267 public void addBCC(InternetAddress bcc) { 268 bccs=add(bccs,bcc); 269 } 270 271 /** 272 * @throws MailException 273 * @throws UnsupportedEncodingException 274 * @throws AddressException 275 * @throws PageException 276 * @see mail.Mail#addBCC(java.lang.String) 277 */ 278 public void addBCC(Object bcc) throws AddressException, UnsupportedEncodingException, MailException, PageException { 279 InternetAddress[] tmp = EmailNamePair.toInternetAddresses(bcc); 280 for(int i=0;i<tmp.length;i++) { 281 addBCC(tmp[i]); 282 } 283 } 284 285 /** 286 * @see mail.Mail#addCC(javax.mail.internet.InternetAddress) 287 */ 288 public void addCC(InternetAddress cc) { 289 ccs=add(ccs,cc); 290 } 291 292 /** 293 * @throws MailException 294 * @throws UnsupportedEncodingException 295 * @throws AddressException 296 * @throws PageException 297 * @see mail.Mail#addCC(java.lang.String) 298 */ 299 public void addCC(Object cc) throws AddressException, UnsupportedEncodingException, MailException, PageException { 300 InternetAddress[] tmp = EmailNamePair.toInternetAddresses(cc); 301 for(int i=0;i<tmp.length;i++) { 302 addCC(tmp[i]); 303 } 304 } 305 306 /** 307 * @see mail.Mail#addReplyTo(javax.mail.internet.InternetAddress) 308 */ 309 public void addReplyTo(InternetAddress rt) { 310 rts=add(rts,rt); 311 } 312 313 /** 314 * @throws MailException 315 * @throws UnsupportedEncodingException 316 * @throws AddressException 317 * @throws PageException 318 * @see mail.Mail#addReplyTo(java.lang.String) 319 */ 320 public void addReplyTo(Object rt) throws AddressException, UnsupportedEncodingException, MailException, PageException { 321 InternetAddress[] tmp = EmailNamePair.toInternetAddresses(rt); 322 for(int i=0;i<tmp.length;i++) { 323 addReplyTo(tmp[i]); 324 } 325 } 326 327 /** 328 * @see mail.Mail#addFailTo(javax.mail.internet.InternetAddress) 329 */ 330 public void addFailTo(InternetAddress ft) { 331 fts=add(fts,ft); 332 } 333 334 public String getHTMLTextAsString() { 335 return htmlText; 336 } 337 public String getPlainTextAsString() { 338 return plainText; 339 } 340 341 /** 342 * @throws MailException 343 * @throws UnsupportedEncodingException 344 * @throws AddressException 345 * @throws PageException 346 * @see mail.Mail#addFailTo(java.lang.String) 347 */ 348 public void addFailTo(Object ft) throws AddressException, UnsupportedEncodingException, MailException, PageException { 349 InternetAddress[] tmp = EmailNamePair.toInternetAddresses(ft); 350 for(int i=0;i<tmp.length;i++) { 351 addFailTo(tmp[i]); 352 } 353 } 354 355 /** 356 * @param timeout the timeout to set 357 */ 358 public void setTimeout(int timeout) { 359 this.timeout = timeout; 360 } 361 362 /** 363 * @see mail.Mail#setSubject(java.lang.String) 364 */ 365 public void setSubject(String subject) { 366 this.subject=subject; 367 } 368 369 /** 370 * @see mail.Mail#setXMailer(java.lang.String) 371 */ 372 public void setXMailer(String xmailer) { 373 this.xmailer=xmailer; 374 } 375 376 /** 377 * creates a new expanded array and return it; 378 * @param oldArr 379 * @param newValue 380 * @return new expanded array 381 */ 382 protected static InternetAddress[] add(InternetAddress[] oldArr, InternetAddress newValue) { 383 if(oldArr==null) return new InternetAddress[] {newValue}; 384 //else { 385 InternetAddress[] tmp=new InternetAddress[oldArr.length+1]; 386 for(int i=0;i<oldArr.length;i++) { 387 tmp[i]=oldArr[i]; 388 } 389 tmp[oldArr.length]=newValue; 390 return tmp; 391 //} 392 } 393 394 protected static Attachment[] add(Attachment[] oldArr, Attachment newValue) { 395 if(oldArr==null) return new Attachment[] {newValue}; 396 //else { 397 Attachment[] tmp=new Attachment[oldArr.length+1]; 398 for(int i=0;i<oldArr.length;i++) { 399 tmp[i]=oldArr[i]; 400 } 401 tmp[oldArr.length]=newValue; 402 return tmp; 403 //} 404 } 405 406 public static class MimeMessageAndSession { 407 public final MimeMessage message; 408 public final SessionAndTransport session; 409 410 public MimeMessageAndSession(MimeMessage message,SessionAndTransport session){ 411 this.message=message; 412 this.session=session; 413 } 414 } 415 416 private MimeMessageAndSession createMimeMessage(railo.runtime.config.Config config,String hostName, int port, String username, String password, 417 boolean tls,boolean ssl) throws MessagingException { 418 419 Properties props = System.getProperties(); 420 421 props.put("mail.smtp.host", hostName); 422 props.put("mail.smtp.timeout", Caster.toString(timeout)); 423 props.put("mail.smtp.connectiontimeout", Caster.toString(timeout)); 424 if(port>0){ 425 props.put("mail.smtp.port", Caster.toString(port)); 426 } 427 if(ssl) { 428 props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); 429 props.put("mail.smtp.socketFactory.port", Caster.toString(port)); 430 props.put("mail.smtp.socketFactory.fallback", "false"); 431 } 432 else { 433 props.put("mail.smtp.socketFactory.class", "javax.net.SocketFactory"); 434 props.remove("mail.smtp.socketFactory.port"); 435 props.remove("mail.smtp.socketFactory.fallback"); 436 } 437 Authenticator auth=null; 438 if(!StringUtil.isEmpty(username)) { 439 props.put("mail.smtp.auth", "true"); 440 props.put("mail.smtp.starttls.enable",tls?"true":"false"); 441 442 props.put("mail.smtp.user", username); 443 props.put("mail.smtp.password", password); 444 props.put("password", password); 445 auth=new SMTPAuthenticator( username, password ); 446 } 447 else { 448 props.put("mail.smtp.auth", "false"); 449 props.remove("mail.smtp.starttls.enable"); 450 451 props.remove("mail.smtp.user"); 452 props.remove("mail.smtp.password"); 453 props.remove("password"); 454 } 455 SessionAndTransport sat = SMTPConnectionPool.getSessionAndTransport(props,auth); 456 457 // Contacts 458 SMTPMessage msg = new SMTPMessage(sat.session); 459 if(from==null)throw new MessagingException("you have do define the from for the mail"); 460 //if(tos==null)throw new MessagingException("you have do define the to for the mail"); 461 462 checkAddress(from,charset); 463 //checkAddress(tos,charset); 464 465 msg.setFrom(from); 466 //msg.setRecipients(Message.RecipientType.TO, tos); 467 468 if(tos!=null){ 469 checkAddress(tos,charset); 470 msg.setRecipients(Message.RecipientType.TO, tos); 471 } 472 if(ccs!=null){ 473 checkAddress(ccs,charset); 474 msg.setRecipients(Message.RecipientType.CC, ccs); 475 } 476 if(bccs!=null){ 477 checkAddress(bccs,charset); 478 msg.setRecipients(Message.RecipientType.BCC, bccs); 479 } 480 if(rts!=null){ 481 checkAddress(rts,charset); 482 msg.setReplyTo(rts); 483 } 484 if(fts!=null){ 485 checkAddress(fts,charset); 486 msg.setEnvelopeFrom(fts[0].toString()); 487 } 488 489 // Subject and headers 490 try { 491 msg.setSubject(MailUtil.encode(subject, charset)); 492 } catch (UnsupportedEncodingException e) { 493 throw new MessagingException("the encoding "+charset+" is not supported"); 494 } 495 msg.setHeader("X-Mailer", xmailer); 496 497 msg.setHeader("Date",getNow(timeZone)); 498 //msg.setSentDate(new Date()); 499 500 Multipart mp=null; 501 502 // Only HTML 503 if(plainText==null) { 504 if(ArrayUtil.isEmpty(attachmentz) && ArrayUtil.isEmpty(parts)){ 505 fillHTMLText(msg); 506 setHeaders(msg,headers); 507 return new MimeMessageAndSession(msg,sat); 508 } 509 mp = new MimeMultipart(); 510 mp.addBodyPart(getHTMLText()); 511 } 512 // only Plain 513 else if(htmlText==null) { 514 if(ArrayUtil.isEmpty(attachmentz) && ArrayUtil.isEmpty(parts)){ 515 fillPlainText(msg); 516 setHeaders(msg,headers); 517 return new MimeMessageAndSession(msg,sat); 518 } 519 mp = new MimeMultipart(); 520 mp.addBodyPart(getPlainText()); 521 } 522 // Plain and HTML 523 else { 524 mp=new MimeMultipart("alternative"); 525 mp.addBodyPart(getPlainText()); 526 mp.addBodyPart(getHTMLText()); 527 528 if(!ArrayUtil.isEmpty(attachmentz) || !ArrayUtil.isEmpty(parts)){ 529 MimeBodyPart content = new MimeBodyPart(); 530 content.setContent(mp); 531 mp = new MimeMultipart(); 532 mp.addBodyPart(content); 533 } 534 } 535 536 // parts 537 if(!ArrayUtil.isEmpty(parts)){ 538 Iterator<MailPart> it = parts.iterator(); 539 if(mp instanceof MimeMultipart) 540 ((MimeMultipart)mp).setSubType("alternative"); 541 while(it.hasNext()){ 542 mp.addBodyPart(toMimeBodyPart(it.next())); 543 } 544 } 545 546 // Attachments 547 if(!ArrayUtil.isEmpty(attachmentz)){ 548 for(int i=0;i<attachmentz.length;i++) { 549 mp.addBodyPart(toMimeBodyPart(mp,config,attachmentz[i])); 550 } 551 } 552 msg.setContent(mp); 553 setHeaders(msg,headers); 554 555 return new MimeMessageAndSession(msg,sat); 556 } 557 558 559 private static void setHeaders(SMTPMessage msg, Map headers) throws MessagingException { 560 Iterator it = headers.keySet().iterator(); 561 String key; 562 while(it.hasNext()) { 563 key = (String)it.next(); 564 msg.setHeader(key, (String)headers.get(key)); 565 } 566 } 567 568 private void checkAddress(InternetAddress[] ias,String charset) { // DIFF 23 569 for(int i=0;i<ias.length;i++) { 570 checkAddress(ias[i], charset); 571 } 572 } 573 private void checkAddress(InternetAddress ia,String charset) { // DIFF 23 574 try { 575 if(!StringUtil.isEmpty(ia.getPersonal())) { 576 String personal = MailUtil.encode(ia.getPersonal(), charset); 577 if(!personal.equals(ia.getPersonal())) 578 ia.setPersonal(personal); 579 } 580 } catch (UnsupportedEncodingException e) {} 581 } 582 583 /** 584 * @param plainText 585 */ 586 public void setPlainText(String plainText) { 587 this.plainText=plainText; 588 this.plainTextCharset=charset; 589 } 590 591 /** 592 * @param plainText 593 * @param plainTextCharset 594 */ 595 public void setPlainText(String plainText, String plainTextCharset) { 596 this.plainText=plainText; 597 this.plainTextCharset=plainTextCharset; 598 } 599 600 /** 601 * @param htmlText 602 */ 603 public void setHTMLText(String htmlText) { 604 this.htmlText=htmlText; 605 this.htmlTextCharset=charset; 606 } 607 608 609 610 public boolean hasHTMLText() { 611 return htmlText!=null; 612 } 613 614 public boolean hasPlainText() { 615 return plainText!=null; 616 } 617 618 /** 619 * @param htmlText 620 * @param htmlTextCharset 621 */ 622 public void setHTMLText(String htmlText, String htmlTextCharset) { 623 this.htmlText=htmlText; 624 this.htmlTextCharset=htmlTextCharset; 625 } 626 627 public void addAttachment(URL url) { 628 Attachment mbp = new Attachment(url); 629 attachmentz=add(attachmentz, mbp); 630 } 631 632 public void addAttachment(Resource resource, String type, String disposition, String contentID,boolean removeAfterSend) { 633 Attachment att = new Attachment(resource, type, disposition, contentID,removeAfterSend); 634 attachmentz=add(attachmentz, att); 635 } 636 637 public MimeBodyPart toMimeBodyPart(Multipart mp, railo.runtime.config.Config config,Attachment att) throws MessagingException { 638 639 MimeBodyPart mbp = new MimeBodyPart(); 640 641 // set Data Source 642 String strRes = att.getAbsolutePath(); 643 if(!StringUtil.isEmpty(strRes)){ 644 645 mbp.setDataHandler(new DataHandler(new ResourceDataSource(config.getResource(strRes)))); 646 } 647 else mbp.setDataHandler(new DataHandler(new URLDataSource2(att.getURL()))); 648 649 mbp.setFileName(att.getFileName()); 650 if(!StringUtil.isEmpty(att.getType())) mbp.setHeader("Content-Type", att.getType()); 651 if(!StringUtil.isEmpty(att.getDisposition())){ 652 mbp.setDisposition(att.getDisposition()); 653 if(mp instanceof MimeMultipart) 654 ((MimeMultipart)mp).setSubType("related"); 655 656 } 657 if(!StringUtil.isEmpty(att.getContentID()))mbp.setContentID(att.getContentID()); 658 659 return mbp; 660 } 661 662 /** 663 * @param is 664 * @throws MessagingException 665 * @throws FileNotFoundException 666 */ 667 public void addAttachment(Resource file) throws MessagingException { 668 addAttachment(file,null,null,null,false); 669 } 670 671 672 673 674 public void send(ConfigImpl config) throws MailException { 675 if(ArrayUtil.isEmpty(config.getMailServers()) && ArrayUtil.isEmpty(host)) 676 throw new MailException("no SMTP Server defined"); 677 678 if(plainText==null && htmlText==null) 679 throw new MailException("you must define plaintext or htmltext"); 680 681 if(timeout<1)timeout=config.getMailTimeout()*1000; 682 683 if(spool==SPOOL_YES || (spool==SPOOL_UNDEFINED && config.isMailSpoolEnable())) { 684 config.getSpoolerEngine().add(new MailSpoolerTask(this)); 685 } 686 else 687 _send(config); 688 } 689 690 691 public void _send(railo.runtime.config.Config config) throws MailException { 692 try { 693 694 Proxy.start(proxyData); 695 LogAndSource log = config.getMailLogger(); 696 // Server 697 Server[] servers = config.getMailServers(); 698 if(host!=null) { 699 int prt; 700 String usr,pwd; 701 ServerImpl[] nServers = new ServerImpl[host.length]; 702 for(int i=0;i<host.length;i++) { 703 usr=null;pwd=null; 704 prt=ServerImpl.DEFAULT_PORT; 705 706 if(port>0)prt=port; 707 if(!StringUtil.isEmpty(username)) { 708 usr=username; 709 pwd=password; 710 } 711 712 nServers[i]=toServerImpl(host[i],prt,usr,pwd); 713 if(ssl==SSL_YES) nServers[i].setSSL(true); 714 if(tls==TLS_YES) nServers[i].setTLS(true); 715 716 } 717 servers=nServers; 718 } 719 if(servers.length==0) { 720 //return; 721 throw new MailException("no SMTP Server defined"); 722 } 723 724 boolean _ssl,_tls; 725 for(int i=0;i<servers.length;i++) { 726 727 Server server = servers[i]; 728 String _username=null,_password=""; 729 //int _port; 730 731 // username/password 732 733 if(server.hasAuthentication()) { 734 _username=server.getUsername(); 735 _password=server.getPassword(); 736 } 737 738 739 // tls 740 if(tls!=TLS_NONE)_tls=tls==TLS_YES; 741 else _tls=((ServerImpl)server).isTLS(); 742 743 // ssl 744 if(ssl!=SSL_NONE)_ssl=ssl==SSL_YES; 745 else _ssl=((ServerImpl)server).isSSL(); 746 747 748 MimeMessageAndSession msgSess; 749 750 synchronized(LOCK) { 751 try { 752 msgSess = createMimeMessage(config,server.getHostName(),server.getPort(),_username,_password,_tls,_ssl); 753 } catch (MessagingException e) { 754 log.error("mail",LogUtil.toMessage(e)); 755 MailException me = new MailException(e.getMessage()); 756 me.setStackTrace(e.getStackTrace()); 757 throw me; 758 } 759 try { 760 SerializableObject lock = new SerializableObject(); 761 SMTPSender sender=new SMTPSender(lock,msgSess,server.getHostName(),server.getPort(),_username,_password); 762 sender.start(); 763 SystemUtil.wait(lock, timeout); 764 765 if(!sender.hasSended()) { 766 Throwable t = sender.getThrowable(); 767 if(t!=null) throw Caster.toPageException(t); 768 769 // stop when still running 770 try{ 771 if(sender.isAlive())sender.stop(); 772 } 773 catch(Throwable t2){} 774 775 // after thread s stopped check send flag again 776 if(!sender.hasSended()){ 777 throw new MessagingException("timeout occurred after "+(timeout/1000)+" seconds while sending mail message"); 778 } 779 } 780 clean(config,attachmentz); 781 782 log.info("mail","send mail"); 783 break; 784 } 785 catch (Exception e) {e.printStackTrace(); 786 if(i+1==servers.length) { 787 String msg=e.getMessage(); 788 if(StringUtil.isEmpty(msg))msg=Caster.toClassName(e); 789 790 log.error("mail spooler",msg); 791 MailException me = new MailException(server.getHostName()+" "+msg+":"+i); 792 me.setStackTrace(e.getStackTrace()); 793 794 throw me; 795 } 796 } 797 } 798 } 799 } 800 finally { 801 Proxy.end(); 802 } 803 } 804 805 // remove all atttachements that are marked to remove 806 private static void clean(Config config, Attachment[] attachmentz) { 807 if(attachmentz!=null)for(int i=0;i<attachmentz.length;i++){ 808 if(attachmentz[i].isRemoveAfterSend()){ 809 Resource res = config.getResource(attachmentz[i].getAbsolutePath()); 810 ResourceUtil.removeEL(res,true); 811 } 812 } 813 } 814 815 private MimeBodyPart getHTMLText() throws MessagingException { 816 MimeBodyPart html = new MimeBodyPart(); 817 fillHTMLText(html); 818 return html; 819 } 820 821 private void fillHTMLText(MimePart mp) throws MessagingException { 822 mp.setDataHandler(new DataHandler(new StringDataSource(htmlText,TEXT_HTML ,htmlTextCharset))); 823 mp.setHeader("Content-Transfer-Encoding", "7bit"); 824 mp.setHeader("Content-Type", TEXT_HTML+"; charset="+htmlTextCharset); 825 } 826 827 private MimeBodyPart getPlainText() throws MessagingException { 828 MimeBodyPart plain = new MimeBodyPart(); 829 fillPlainText(plain); 830 return plain; 831 } 832 private void fillPlainText(MimePart mp) throws MessagingException { 833 mp.setDataHandler(new DataHandler(new StringDataSource(plainText,TEXT_PLAIN ,plainTextCharset))); 834 mp.setHeader("Content-Transfer-Encoding", "7bit"); 835 mp.setHeader("Content-Type", TEXT_PLAIN+"; charset="+plainTextCharset); 836 } 837 838 private BodyPart toMimeBodyPart(MailPart part) throws MessagingException { 839 MimeBodyPart mbp = new MimeBodyPart(); 840 mbp.setDataHandler(new DataHandler(new StringDataSource(part.getBody(),part.getType() ,part.getCharset()))); 841 //mbp.setHeader("Content-Transfer-Encoding", "7bit"); 842 //mbp.setHeader("Content-Type", TEXT_PLAIN+"; charset="+plainTextCharset); 843 return mbp; 844 } 845 846 /** 847 * @return the proxyData 848 */ 849 public ProxyData getProxyData() { 850 return proxyData; 851 } 852 853 /** 854 * @param proxyData the proxyData to set 855 */ 856 public void setProxyData(ProxyData proxyData) { 857 this.proxyData = proxyData; 858 } 859 860 /** 861 * @param ssl the ssl to set 862 */ 863 public void setSSL(boolean ssl) { 864 this.ssl = ssl?SSL_YES:SSL_NO; 865 } 866 867 /** 868 * @param tls the tls to set 869 */ 870 public void setTLS(boolean tls) { 871 this.tls = tls?TLS_YES:TLS_NO; 872 } 873 874 /** 875 * @return the subject 876 */ 877 public String getSubject() { 878 return subject; 879 } 880 881 /** 882 * @return the from 883 */ 884 public InternetAddress getFrom() { 885 return from; 886 } 887 888 /** 889 * @return the tos 890 */ 891 public InternetAddress[] getTos() { 892 return tos; 893 } 894 895 /** 896 * @return the bccs 897 */ 898 public InternetAddress[] getBccs() { 899 return bccs; 900 } 901 902 /** 903 * @return the ccs 904 */ 905 public InternetAddress[] getCcs() { 906 return ccs; 907 } 908 909 public void setPart(MailPart part) { 910 if(parts==null) parts=new ArrayList<MailPart>(); 911 parts.add(part); 912 } 913 914 915 public void setTimeZone(TimeZone timeZone) { 916 this.timeZone=timeZone; 917 } 918 }