001: //** Copyright Statement ***************************************************
002: //The Salmon Open Framework for Internet Applications (SOFIA)
003: // Copyright (C) 1999 - 2002, Salmon LLC
004: //
005: // This program is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU General Public License version 2
007: // as published by the Free Software Foundation;
008: //
009: // This program is distributed in the hope that it will be useful,
010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: // GNU General Public License for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // along with this program; if not, write to the Free Software
016: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: //
018: // For more information please visit http://www.salmonllc.com
019: //** End Copyright Statement ***************************************************
020: package com.salmonllc.email;
021:
022: /////////////////////////
023: //$Archive: /SOFIA/SourceCode/com/salmonllc/email/SMTP.java $
024: //$Author: Dan $
025: //$Revision: 33 $
026: //$Modtime: 8/24/04 4:33p $
027: /////////////////////////
028:
029: import java.io.*;
030: import java.util.*;
031:
032: import javax.activation.DataHandler;
033: import javax.activation.FileDataSource;
034: import javax.mail.*;
035: import javax.mail.internet.*;
036:
037: import com.salmonllc.util.ApplicationContext;
038: import com.salmonllc.util.MessageLog;
039: import com.salmonllc.util.Util;
040:
041: /**
042: * This class abstracts and simplifies the process of sending email to via an SMTP server
043: */
044: public class SMTP implements Runnable {
045: private static final int _DefaultPort = 25;
046: private String _SMTPHost;
047: private int _SMTPPort;
048: private Vector _vRecipients = new Vector();
049:
050: // BYD - 6/30/03 - Added functionality to enable user to send e-amil to CC and BCC
051: private Vector _vCCRecipients = new Vector();
052: private Vector _vBCCRecipients = new Vector();
053: public static final int iTO = 0;
054: public static final int iCC = 1;
055: public static final int iBCC = 2;
056: // --
057:
058: private Vector _vFileNames = new Vector();
059: private String _SenderHost;
060: private String _From = null;
061: private String _sException = null;
062: private boolean _MailSent = false;
063: private String _Body = null;
064: private String _EndDataString = "\r\n.\r\n";
065: private String _Subject = null;
066: private String _OpenConnResponse = "220";
067: private String _OkResponse = "250";
068: private String _DataResponse = "354";
069: private String _CloseConnResponse = "221";
070: private String _ErrorResponse = "500";
071: private String _BodyMimeType = "text/plain";
072: private String _TimeStampFormat = "EEE, dd MMM yyyy hh:mm:ss (z)";
073:
074: private static final String _CRLF = "\r\n";
075: public java.util.Properties _fieldSMTPServers;
076: public javax.mail.Session _mailSession;
077: public Thread _interruptThread;
078:
079: /*Claudio Pi (04-02-2003)*/
080: /*Use SMTP Authentication ?*/
081: private boolean _SMTPAuth = false;
082: /*SMTP Authentication Username*/
083: private String _SMTPAuthUser = null;
084: /*SMTP Authentication Password*/
085: private String _SMTPAuthPass = null;
086:
087: /**
088: * Licensed Material - Property of Salmon LLC
089: * (C) Copyright Salmon LLC. 1999 - All Rights Reserved
090: * For more information go to www.salmonllc.com
091: *
092: * *************************************************************************
093: * DISCLAIMER:
094: * The following code has been created by Salmon LLC. The code is provided
095: * 'AS IS' , without warranty of any kind unless covered in another agreement
096: * between your corporation and Salmon LLC. Salmon LLC shall not be liable
097: * for any damages arising out of your use of this, even if they have been
098: * advised of the possibility of such damages.
099: * *************************************************************************
100: *
101: * This create an SMTP object using the Specified Port iPort.
102: * @param sHost The Hostname of the SMTP server
103: * @param iPort The Port Number the SMTP server listens on.
104: */
105: /**
106: * This create an SMTP object using the Standard Port 25.
107: * @param sHost The Hostname of the SMTP server.
108: */
109: public SMTP(String sHost) {
110: this (sHost, _DefaultPort);
111: }
112:
113: /**
114: * This create an SMTP object using the Specified Port iPort.
115: * @param sHost The Hostname of the SMTP server
116: * @param iPort The Port Number the SMTP server listens on.
117: */
118: public SMTP(String sHost, int iPort) {
119:
120: Properties props = new Properties();
121: props.put("Server1", sHost);
122: props.put("Port1", String.valueOf(iPort));
123: setSMTPServers(props);
124: }
125:
126: /**
127: * Claudio Pi (04-02-2003)
128: * This method creates an SMTP object using the specified host, port, authentication username and password.
129: * @param sHost The Hostname of the SMTP server
130: * @param iPort The Port Number the SMTP server listens on.
131: * @param smtpAuthUser The username to use for authentication.
132: * @param smtpAuthPass The password to use for authentication.
133: */
134:
135: public SMTP(String sHost, int iPort, String smtpAuthUser,
136: String smtpAuthPass) {
137: this (sHost, iPort);
138: this ._SMTPAuth = true;
139: this ._SMTPAuthUser = smtpAuthUser;
140: this ._SMTPAuthPass = smtpAuthPass;
141: }
142:
143: /**
144: * Claudio Pi (04-02-2003)
145: * This method creates an SMTP object using the specified host, authentication username and password.
146: * @param sHost The Hostname of the SMTP server
147: * @param smtpAuthUser The username to use for authentication.
148: * @param smtpAuthPass The password to use for authentication.
149: */
150: public SMTP(String sHost, String smtpAuthUser, String smtpAuthPass) {
151: this (sHost);
152: this ._SMTPAuth = true;
153: this ._SMTPAuthUser = smtpAuthUser;
154: this ._SMTPAuthPass = smtpAuthPass;
155: }
156:
157: /**
158: * This create an SMTP object using the Informations from a Properties object.
159: * @param props java.util.Properties The Properties object to specify the SMTP settings.
160: */
161: public SMTP(Properties props) {
162:
163: setSMTPServers(props);
164: }
165:
166: /*
167: * This method is Private to the SMTP object for accepting responses from the SMTP server.
168: * @param br This is the BufferInputReader of the Inputstream from the SMTP server.
169: * @param sAccept This is the String representing what you sholg get back from the SMTP server if successful.
170: private void acceptResponse(java.io.BufferedInputStream bis, String sAccept)
171: throws java.io.IOException, SMTPException {
172: int len = 256;
173:
174: byte[] bStream = new byte[len];
175: String sLine = "";
176: while (true) {
177: int i = bis.read(bStream, 0, len);
178: // System.err.println("read "+i+" bytes");
179: sLine = new String(bStream, 0, i);
180: // System.err.println(sLine);
181: if (sLine.startsWith(sAccept))
182: return;
183: else if (sLine.startsWith(_ErrorResponse)) {
184: int iQuote = sLine.indexOf('\'');
185: String sTmp = sLine.substring(iQuote + 1);
186: iQuote = sTmp.indexOf('\'');
187: if (iQuote != 0)
188: break;
189: }
190: else
191: break;
192: }
193: _sException = "SMTP Server Invalid Response: " + sLine;
194: throw new SMTPException(_sException);
195: }*/
196:
197: /**
198: * This method attaches to the SMTP object for use in sending mail to.
199: * @param sFile A Full Specified Path to a File.
200: */
201: public void addFile(String sFile) throws SMTPException {
202: File fFile = new File(sFile);
203: if (fFile.exists())
204: _vFileNames.addElement(sFile);
205: else
206: throw new SMTPException(sFile + " is not a valid file.");
207: }
208:
209: /**
210: * This method adds Recipients to the SMTP object for use in sending mail to.
211: * @param sAddress A Valid Email of a Recipient.
212: */
213: public void addRecipient(String sAddress) throws SMTPException {
214: addRecipient(sAddress, iTO);
215: }
216:
217: /**
218: * This method adds Recipients to the SMTP object for use in sending mail to.
219: * @param sAddress A Valid Email of a Recipient.
220: */
221: public void addRecipient(String sAddress, int iRecipientType)
222: throws SMTPException {
223: if (validEMailAddress(sAddress)) {
224: switch (iRecipientType) {
225: default:
226: case iTO:
227: _vRecipients.addElement(sAddress.trim());
228: break;
229:
230: case iCC:
231: _vCCRecipients.addElement(sAddress.trim());
232: break;
233:
234: case iBCC:
235: _vBCCRecipients.addElement(sAddress.trim());
236: break;
237: }
238: } else
239: throw new SMTPException(sAddress
240: + " is an Invalid E-Mail Address.");
241: }
242:
243: /**
244: * This method adds Recipients to the SMTP object for use in sending mail to.
245: * @param sCommaSepRecipients A Comma Separated List of valid E-Mail Addresses of Recipients.
246: */
247: public void addRecipients(String sCommaSepRecipients)
248: throws SMTPException {
249: addRecipients(sCommaSepRecipients, iTO);
250: }
251:
252: /**
253: * This method adds Recipients to the SMTP object for use in sending mail to.
254: * @param sCommaSepRecipients A Comma Separated List of valid E-Mail Addresses of Recipients.
255: * @param iRecipientType int - the type of recipient (TO, CC or BCC)
256: */
257: public void addRecipients(String sCommaSepRecipients,
258: int iRecipientType) throws SMTPException {
259: int iCommaPos = sCommaSepRecipients.indexOf(',');
260: if (iCommaPos != -1) {
261: String sRecipients = sCommaSepRecipients;
262: while (iCommaPos != -1) {
263: String sRecipient = sRecipients.substring(0, iCommaPos);
264: addRecipient(sRecipient, iRecipientType);
265: sRecipients = sRecipients.substring(iCommaPos + 1);
266: iCommaPos = sRecipients.indexOf(',');
267: }
268: addRecipient(sRecipients, iRecipientType);
269: } else
270: addRecipient(sCommaSepRecipients, iRecipientType);
271: }
272:
273: /**
274: * Returns the Properties object containing the SMTP settings
275: * @return java.util.Properties A Properties object with the SMTP settings
276: */
277: public java.util.Properties getSMTPServers() {
278: return _fieldSMTPServers;
279: }
280:
281: /**
282: * This is a main program for testing the SMTP class.
283: * @param args java.lang.String[] Parameters for the SMTP test.
284: */
285: public static void main(String args[]) {
286:
287: if (args.length < 2) {
288: System.out
289: .println("Must have two parameters, host & recipient E-Mail");
290: return;
291: }
292: try {
293: SMTP smtp;
294: smtp = new SMTP(args[0]);
295: smtp.setSubject("Test EMail");
296: smtp.setFromAddress("Test@salmonllc.com");
297: smtp.addRecipient(args[1]);
298: smtp.setBodyMimeType("text/plain");
299: smtp.setBody("<html><body><b>deepak</b></body></html>");
300: if (args.length > 2)
301: smtp.addFile(args[2]);
302: smtp.sendMail();
303: } catch (Exception e) {
304: System.out.println(e);
305: }
306:
307: }
308:
309: /**
310: * This Method does the Coummunication with the SMTP server and sends the mail.
311: * This Method should not be called by the developer, but only from calling sendMail.
312: */
313: public void run() {
314: String sHost = "";
315: String sPort = "";
316: boolean bSendMail = false;
317:
318: for (int j = 0; j < getSMTPServers().size(); j++) {
319: if (bSendMail)
320: break;
321:
322: sHost = getSMTPServers().getProperty("Server" + (j + 1));
323:
324: sPort = getSMTPServers().getProperty("Port" + (j + 1));
325: if (sPort == null)
326: sPort = String.valueOf(_DefaultPort);
327:
328: try {
329: Properties props = System.getProperties();
330: if (sHost != null) {
331: /*Claudio Pi (04-02-2003)*/
332: if (_SMTPAuth) {
333: props.put("mail.smtp.auth", "true");
334: }
335:
336: props.put("mail.smtp.host", sHost);
337: props.put("mail.smtp.port", sPort);
338: _mailSession = Session.getDefaultInstance(props,
339: null);
340: } else
341: break;
342:
343: // BYD - 6/30/03 - If there are no recipient in the TO:, CC: AND BCC: fields then return
344: if ((_vRecipients.size() <= 0)
345: && (_vCCRecipients.size() <= 0)
346: && (_vBCCRecipients.size() <= 0))
347: break;
348:
349: MessageLog.writeDebugMessage("SMTP HOST: " + sHost,
350: this );
351: MessageLog.writeDebugMessage("SMTP PORT: " + sPort,
352: this );
353: Message mailMessage = new MimeMessage(_mailSession);
354:
355: // Set the Form Addresss
356: InternetAddress addressFrom = new InternetAddress();
357: addressFrom.setAddress(_From);
358: mailMessage.setFrom(addressFrom);
359:
360: // BYD - 7/01/03 - Concatenate all recipients for use with the transport sendMessage method
361: InternetAddress[] recpAllAddresses = new InternetAddress[_vRecipients
362: .size()
363: + _vCCRecipients.size()
364: + _vBCCRecipients.size()];
365: int iAddr = 0;
366:
367: // BYD - 6/30/03 - Set the recipients
368: InternetAddress[] recpAddress = new InternetAddress[_vRecipients
369: .size()];
370: if (_vRecipients.size() > 0) {
371: for (int i = 0; i < _vRecipients.size(); i++) {
372: recpAddress[i] = new InternetAddress(
373: (String) _vRecipients.elementAt(i));
374: recpAllAddresses[iAddr++] = recpAddress[i];
375: MessageLog.writeDebugMessage("Recipient " + i
376: + ": "
377: + (String) _vRecipients.elementAt(i),
378: this );
379: }
380: mailMessage.setRecipients(Message.RecipientType.TO,
381: recpAddress);
382: }
383:
384: // BYD - 6/30/03 - Set the CC recipients
385: InternetAddress[] recpCCAddress = new InternetAddress[_vCCRecipients
386: .size()];
387: if (_vCCRecipients.size() > 0) {
388: for (int i = 0; i < _vCCRecipients.size(); i++) {
389: recpCCAddress[i] = new InternetAddress(
390: (String) _vCCRecipients.elementAt(i));
391: recpAllAddresses[iAddr++] = recpCCAddress[i];
392: MessageLog.writeDebugMessage("CC Recipient "
393: + i + ": "
394: + (String) _vCCRecipients.elementAt(i),
395: this );
396: }
397: mailMessage.setRecipients(Message.RecipientType.CC,
398: recpCCAddress);
399: }
400:
401: // BYD - 6/30/03 - Set the BCC recipients
402: InternetAddress[] recpBCCAddress = new InternetAddress[_vBCCRecipients
403: .size()];
404: if (_vBCCRecipients.size() > 0) {
405: for (int i = 0; i < _vBCCRecipients.size(); i++) {
406: recpBCCAddress[i] = new InternetAddress(
407: (String) _vBCCRecipients.elementAt(i));
408: recpAllAddresses[iAddr++] = recpBCCAddress[i];
409: MessageLog.writeDebugMessage(
410: "BCC Recipient "
411: + i
412: + ": "
413: + (String) _vBCCRecipients
414: .elementAt(i), this );
415: }
416: mailMessage.setRecipients(
417: Message.RecipientType.BCC, recpBCCAddress);
418: }
419:
420: mailMessage.setSubject(_Subject);
421: mailMessage.setSentDate(new Date(System
422: .currentTimeMillis()));
423:
424: // Add the attachments if any
425: if (_vFileNames.size() > 0) {
426:
427: Multipart multipart = new MimeMultipart();
428:
429: MimeBodyPart mbpBody = new MimeBodyPart();
430: mbpBody.setContent(_Body, _BodyMimeType);
431: multipart.addBodyPart(mbpBody);
432:
433: for (int i = 0; i < _vFileNames.size(); i++) {
434: MimeBodyPart mbp = new MimeBodyPart();
435:
436: // attach the file to the message
437: FileDataSource fds = new FileDataSource(
438: (String) _vFileNames.elementAt(i));
439: mbp.setDataHandler(new DataHandler(fds));
440: mbp.setFileName(fds.getName());
441:
442: multipart.addBodyPart(mbp);
443: }
444:
445: mailMessage.setContent(multipart);
446: } else {
447: mailMessage.setContent(_Body, _BodyMimeType);
448: }
449: /*Claudio Pi (04-02-2003)*/
450: Transport tr = _mailSession.getTransport("smtp");
451: if (_SMTPAuth) {
452: tr.connect(sHost, Util.stringToInt(sPort),
453: _SMTPAuthUser, _SMTPAuthPass);
454: } else {
455: tr.connect();
456: }
457:
458: tr.sendMessage(mailMessage, recpAllAddresses);
459:
460: //Transport.send(mailMessage);
461: bSendMail = true;
462: } catch (Exception e) {
463: bSendMail = false;
464: _sException = e.getMessage();
465: MessageLog.writeErrorMessage("run() for Server "
466: + sHost, e, this );
467: }
468: _MailSent = bSendMail;
469: if (_interruptThread != null)
470: _interruptThread.interrupt();
471: }
472: }
473:
474: /**
475: * This Method starts the Thread which Communicates with the SMTP server.
476: * This is the Method to be called when sending mail.
477: */
478: public void sendMail() throws SMTPException {
479: if (_From == null)
480: throw new SMTPException("EMail must contain a From Address");
481: if ((_vRecipients.size() == 0) && (_vCCRecipients.size() == 0)
482: && (_vBCCRecipients.size() == 0))
483: throw new SMTPException("EMail must contain Recipients");
484: if (_Body == null)
485: throw new SMTPException("EMail must contain a Body");
486: Thread t = ApplicationContext
487: .createThreadWithContextClone(this );
488: t.start();
489: }
490:
491: /**
492: * This method sets the body of the mail message.
493: * @param sBody A String representing the body of the message.
494: */
495: public void setBody(String sBody) {
496: String sTemp = sBody;
497: int iNewLine = sTemp.indexOf('\n');
498: int offset = 0;
499: while (iNewLine != -1) {
500: if (iNewLine - 1 >= 0) {
501: if (sTemp.charAt(iNewLine - 1) != '\r') {
502: sTemp = sTemp.substring(0, iNewLine) + _CRLF
503: + sTemp.substring(iNewLine + 1);
504: offset = iNewLine + 2;
505: } else
506: offset = iNewLine + 1;
507: } else {
508: sTemp = _CRLF + sTemp.substring(1);
509: offset = 2;
510: }
511: iNewLine = sTemp.indexOf('\n', offset);
512: }
513: _Body = sTemp;
514: }
515:
516: /**
517: * Sets the mime type of the body content of the e-mail
518: * @param sMimeType java.lang.String MimeType of the body of the e-mail.
519: */
520: public void setBodyMimeType(String sMimeType) {
521: _BodyMimeType = sMimeType;
522: }
523:
524: /**
525: * Sets the Close Response of the SMTP protocol.
526: * @param sClose java.lang.String The Close Response of the SMTP protocol
527: */
528: public void setCloseResponse(String sClose) {
529: _CloseConnResponse = sClose;
530: }
531:
532: /**
533: * Sets the Data Response of the SMTP protocol.
534: * @param sData java.lang.String The Data Response of the SMTP protocol
535: */
536: public void setDataResponse(String sData) {
537: _DataResponse = sData;
538: }
539:
540: /**
541: * This method sets the Ending Character String to inicate the end of the message body.
542: * @param sEndDataString This String Indicates the end of the Body of Message which the server is Expecting.
543: */
544: public void setEndDataString(String sEndDataString) {
545: _EndDataString = sEndDataString;
546: }
547:
548: /**
549: * Sets the Error Response of the SMTP protocol.
550: * @param sError java.lang.String The Error Response of the SMTP protocol
551: */
552: public void setErrorResponse(String sError) {
553: _ErrorResponse = sError;
554: }
555:
556: /**
557: * This method sets the EMail address of the person the message is from.
558: * @param sAddress A valid EMail Address.
559: */
560: public void setFromAddress(String sAddress) throws SMTPException {
561: if (validEMailAddress(sAddress))
562: _From = sAddress;
563: else
564: throw new SMTPException(sAddress
565: + " is an Invalid E-Mail Address.");
566: }
567:
568: /**
569: * This sets the Hostname of the SMTP Server.
570: * @param sHost The hostname of the SMTP server
571: */
572: public void setHost(String sHost) {
573: _SMTPHost = sHost;
574: }
575:
576: /**
577: * Sets the OK Response of the SMTP protocol.
578: * @param sOk java.lang.String The OK Response of the SMTP protocol
579: */
580: public void setOkResponse(String sOk) {
581: _OkResponse = sOk;
582: }
583:
584: /**
585: * Sets the Open Response of the SMTP protocol.
586: * @param sOpen java.lang.String The Open Response of the SMTP protocol
587: */
588: public void setOpenResponse(String sOpen) {
589: _OpenConnResponse = sOpen;
590: }
591:
592: /**
593: * This sets the port number of the SMTP server.
594: * @param iPort The port of the SMTP Server.
595: */
596: public void setPort(int iPort) {
597: _SMTPPort = iPort;
598: }
599:
600: /**
601: * This method sets the Sender Host of the message.
602: * @param sSenderHost A Hostname representing the sending machine.
603: */
604: public void setSenderHost(String sSenderHost) {
605: _SenderHost = sSenderHost;
606: }
607:
608: /**
609: * Sets the Properties object containing the information about SMTP settings.
610: * @param newSMTPServers java.util.Properties Properties Object with the SMTP settings
611: */
612: public void setSMTPServers(java.util.Properties newSMTPServers) {
613: _fieldSMTPServers = newSMTPServers;
614: }
615:
616: /**
617: * Sets the Subject of the E-Mail.
618: * @param sSubject java.lang.String The subject of the e-mail
619: */
620: public void setSubject(String sSubject) {
621: _Subject = sSubject;
622: }
623:
624: /**
625: * Sets the TimeStampFormat used in the e-mail.
626: * @param sFormat java.lang.String The format of the timestamp for the e-mail
627: */
628: public void setTimeStampFormat(String sFormat) {
629: _TimeStampFormat = sFormat;
630: }
631:
632: /**
633: * This method checks to see if sEmailAddress matches the format for an EMail.
634: * @return boolean Returns false if sEMailAddress is not valid.
635: * @param sEMailAddress java.lang.String
636: */
637: private boolean validEMailAddress(String sEMailAddress) {
638: boolean bRet = false;
639: int iAtPos = sEMailAddress.indexOf('@');
640: if (iAtPos != -1) {
641: String sHost = sEMailAddress.substring(iAtPos + 1);
642: if (sHost.indexOf('@') == -1)
643: if (sHost.indexOf('.') != -1)
644: bRet = true;
645: }
646: return bRet;
647: }
648:
649: /**
650: * This method waits iSeconds number of seconds to check to see if mail was sent successfully or not.
651: * @return boolean Returns true if Successfully sent.
652: */
653: public boolean waitForMailSendToComplete(int iSeconds)
654: throws SMTPException {
655: _interruptThread = Thread.currentThread();
656: try {
657: Thread.sleep(iSeconds * 1000);
658: } catch (Exception e) {
659: }
660: if (_sException != null)
661: throw new SMTPException(_sException);
662: return _MailSent;
663: }
664:
665: /**
666: * fmc 04/03/03.
667: * This sets the SMTP Auth User of the SMTP Server.
668: * @param sAuthUser The hostname of the SMTP server
669: */
670: public void setAuthUser(String sAuthUser) {
671: _SMTPAuthUser = sAuthUser;
672: if (_SMTPAuthUser != null && !_SMTPAuthUser.equals(""))
673: _SMTPAuth = true;
674: else
675: _SMTPAuth = false;
676: }
677:
678: /**
679: * fmc 04/03/03.
680: * This sets the SMTP Auth Password of the SMTP Server.
681: * @param sAuthPass The hostname of the SMTP server
682: */
683: public void setAuthPassword(String sAuthPass) {
684: _SMTPAuthPass = sAuthPass;
685: }
686:
687: }
|