1 /**
2 * AUTOHIT 2003
3 * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Additional license information can be found in the documentation.
19 * @author Erich P Gatejen
20 */
21 package autohit.call.modules;
22
23 import java.io.BufferedReader;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.OutputStream;
27 import java.io.Writer;
28
29 import org.apache.commons.net.io.Util;
30 import org.apache.commons.net.smtp.RelayPath;
31 import org.apache.commons.net.smtp.SMTPClient;
32 import org.apache.commons.net.smtp.SMTPConnectionClosedException;
33
34 import autohit.call.CallException;
35 import autohit.common.Constants;
36 import autohit.universe.UniverseException;
37 import autohit.vm.process.StringProcessors;
38
39 /**
40 * Tolerant SMTP module. There is a client/per module at this time. This one
41 * supports streaming and will not throw faults on every error. <code>
42 * start(address,optional{port}) start an SMTP session<br>
43 * login(optional{hostname}) login to peer<br>
44 * sender(address) set the sender with address<br>
45 * addsenderrelay(address) add to the sender relay path<br>
46 * senderrelay() set the sender with sender relay path. clear the accumulated relay path.<br>
47 * recipient(address) add a recipient with address<br>
48 * addrecipientrelay(address) add to the recipient relay path<br>
49 * newrecipientrelay(address) start a new recipient relay path<br>
50 * recipientrelay() add a recipient with recipient relay path. clear the accumulated relay path.<br>
51 * send(text) send message from text.<br>
52 * senduni(uniobj) send message from universe object.<br>
53 * senduniscrub(uniobj) send message from universe object. scrub it first with variable replacements<br>
54 * reset() reset the smtp state.<br>
55 * done() complete a session. It will logout and close.<br>
56 * mailit(from,to,text,host,optional{port}) convenience method for sending small message.
57 * mailituni(from,to,uniobj,host,optional{port}) convenience method for sending small message.
58 * </code>
59 *
60 * @author Erich P. Gatejen
61 * @version 1.0 <i>Version History</i><code>EPG - Initial, branched from SimpleSmtpModule - 25 Dec03</code>
62 */
63 public class TolerantSmtpModule extends Module {
64
65 private final static String myNAME = "TolerantSmtp";
66 private final static String TEMPFILE = "temp/tsmtpscrub";
67
68 private final static String ERROR_STRING_FOR_FAILURE = "451";
69 private final static int SMTP_ERROR_THRESHOLD = 300;
70 // An SMTP error code
71
72 /**
73 * METHODS
74 */
75 private final static String method_START = "start";
76 private final static String method_START_1_ADDRESS = "address";
77 private final static String method_START_2_PORT = "port";
78 private final static String method_LOGIN = "login";
79 private final static String method_LOGIN_1_HOSTNAME = "hostname";
80 private final static String method_SENDER = "sender";
81 private final static String method_SENDER_1_ADDRESS = "address";
82 private final static String method_ADDSENDERRELAY = "addsenderrelay";
83 private final static String method_ADDSENDERRELAY_1_ADDRESS = "address";
84 private final static String method_SENDERRELAY = "senderrelay";
85 private final static String method_RECIPIENT = "recipient";
86 private final static String method_RECIPIENT_1_ADDRESS = "address";
87 private final static String method_ADDRECIPIENTRELAY = "addrecipientrelay";
88 private final static String method_NEWRECIPIENTRELAY = "newrecipientrelay";
89 private final static String method_ADDRECIPIENTRELAY_1_ADDRESS = "address";
90 private final static String method_RECIPIENTRELAY = "recipientrelay";
91 private final static String method_SEND = "send";
92 private final static String method_SEND_1_TEXT = "text";
93 private final static String method_SENDUNI = "senduni";
94 private final static String method_SENDUNI_1_TEXT = "uniobj";
95 private final static String method_SENDUNISCRUB = "senduniscrub";
96 private final static String method_SENDUNISCRUB_1_TEXT = "uniobj";
97 private final static String method_RESET = "reset";
98 private final static String method_DONE = "done";
99 private final static String method_MAILIT = "mailit";
100 private final static String method_MAILIT_1_TO = "to";
101 private final static String method_MAILIT_2_FROM = "from";
102 private final static String method_MAILIT_3_TEXT = "text";
103 private final static String method_MAILIT_4_HOSTNAME = "host";
104 private final static String method_MAILIT_5_PORT = "port";
105 private final static String method_MAILITUNI = "mailituni";
106 private final static String method_MAILITUNI_1_TO = "to";
107 private final static String method_MAILITUNI_2_FROM = "from";
108 private final static String method_MAILITUNI_3_UNIOBJ = "uniobj";
109 private final static String method_MAILITUNI_4_HOSTNAME = "host";
110 private final static String method_MAILITUNI_5_PORT = "port";
111
112 SMTPClient client;
113 RelayPath senderrelay;
114 RelayPath recipientrelay;
115 boolean loggedIn;
116
117 /**
118 * Constructor
119 */
120 public TolerantSmtpModule() {
121
122 }
123
124 // IMPLEMENTORS
125
126 /**
127 * Execute a named method. You must implement this method. You can call any
128 * of the helpers for data and services. The returned object better be a
129 * string (for now).
130 *
131 * @param name
132 * name of the method
133 * @see autohit.common.NOPair
134 * @throws CallException
135 */
136 public Object execute_chain(String name) throws CallException {
137
138 Object response = Constants.EMPTY_LEFT;
139 Object thingie;
140
141 if (name.equals(method_START)) {
142 String param1 = this.required(method_START_1_ADDRESS, name);
143 String param2 = this.optional(method_START_2_PORT);
144 this.start(param1, param2);
145
146 } else if (name.equals(method_LOGIN)) {
147 String param1 = this.optional(method_LOGIN_1_HOSTNAME);
148 this.login(param1);
149
150 } else if (name.equals(method_SENDER)) {
151 String param1 = this.required(method_SENDER_1_ADDRESS, name);
152 this.sender(param1);
153
154 } else if (name.equals(method_ADDSENDERRELAY)) {
155 String param1 =
156 this.required(method_ADDSENDERRELAY_1_ADDRESS, name);
157 this.addsenderrelay(param1);
158
159 } else if (name.equals(method_SENDERRELAY)) {
160 this.senderrelay();
161
162 } else if (name.equals(method_RECIPIENT)) {
163 String param1 = this.required(method_RECIPIENT_1_ADDRESS, name);
164 this.recipient(param1);
165
166 } else if (name.equals(method_ADDRECIPIENTRELAY)) {
167 String param1 =
168 this.required(method_ADDRECIPIENTRELAY_1_ADDRESS, name);
169 this.addrecipientrelay(param1);
170
171 } else if (name.equals(method_NEWRECIPIENTRELAY)) {
172 this.newrecipientrelay();
173
174 } else if (name.equals(method_RECIPIENTRELAY)) {
175 this.recipientrelay();
176
177 } else if (name.equals(method_SEND)) {
178 String param1 = this.required(method_SEND_1_TEXT, name);
179 response = this.send(param1);
180
181 } else if (name.equals(method_SENDUNI)) {
182 String param1 = this.required(method_SENDUNI_1_TEXT, name);
183 response = this.senduni(param1);
184
185 } else if (name.equals(method_SENDUNISCRUB)) {
186 String param1 = this.required(method_SENDUNISCRUB_1_TEXT, name);
187 response = this.senduniscrub(param1);
188
189 } else if (name.equals(method_RESET)) {
190 this.reset();
191
192 } else if (name.equals(method_DONE)) {
193 this.done();
194
195 } else if (name.equals(method_MAILIT)) {
196 String param1 = this.required(method_MAILIT_1_TO, name);
197 String param2 = this.required(method_MAILIT_2_FROM, name);
198 String param3 = this.required(method_MAILIT_3_TEXT, name);
199 String param4 = this.required(method_MAILIT_4_HOSTNAME, name);
200 String param5 = this.optional(method_MAILIT_5_PORT);
201 response = this.mailit(param1, param2, param3, param4, param5);
202
203 } else if (name.equals(method_MAILITUNI)) {
204 String param1 = this.required(method_MAILITUNI_1_TO, name);
205 String param2 = this.required(method_MAILITUNI_2_FROM, name);
206 String param3 = this.required(method_MAILITUNI_3_UNIOBJ, name);
207 String param4 = this.required(method_MAILITUNI_4_HOSTNAME, name);
208 String param5 = this.optional(method_MAILITUNI_5_PORT);
209 response = this.mailituni(param1, param2, param3, param4, param5);
210
211 } else {
212 error("Not a provided method. method=" + name);
213 }
214 return response;
215 }
216
217 /**
218 * Allow the subclass a chance to initialize. At a minium, an implementor
219 * should create an empty method.
220 *
221 * @throws CallException
222 * @return the name
223 */
224 protected String instantiation_chain() throws CallException {
225 client = null;
226 loggedIn = false;
227 return myNAME;
228 }
229
230 /**
231 * Allow the subclass a chance to cleanup on free. At a minium, an
232 * implementor should create an empty method.
233 *
234 * @throws CallException
235 */
236 protected void free_chain() throws CallException {
237 try {
238 this.done();
239 } catch (Exception e) {
240 // don't care
241 }
242 }
243
244 // PRIVATE IMPLEMENTATIONS
245
246 /**
247 * Start method. It will open a connection to an SMTP server/relay. If a
248 * session is already started, it will report an error. If it cannot make
249 * the connection, it will cause a fault.
250 *
251 * @param addr
252 * the domain name address. Do not include protocol or port.
253 * @param post
254 * this should be a parsable integer. If it is null, the default
255 * will be used.
256 * @throws CallException
257 */
258 private void start(String addr, String port) throws CallException {
259
260 SMTPClient candidate = null;
261
262 // Already started?
263 if (client != null) {
264 this.error("Session already started. Ignoring new start().");
265 return;
266 }
267 // Passed a port number?
268 int portNum = 0;
269 if (port != null) {
270 try {
271 portNum = Integer.parseInt(port);
272 } catch (Exception e) {
273 this.fault(
274 "Malformed 'port' number. It must be a parsable integer. text="
275 + port);
276 }
277 }
278 // Try and construct it
279 try {
280 candidate = new SMTPClient();
281 if (port == null) {
282 candidate.connect(addr);
283 } else {
284 candidate.connect(addr, portNum);
285 }
286
287 } catch (Exception ex) {
288 this.error(
289 "Could not connect to host. message=" + ex.getMessage());
290 return;
291 }
292
293 // NO CODE AFTER THIS!
294 this.log("Connection started.");
295 loggedIn = false;
296 client = candidate;
297 }
298
299 /**
300 * Done method. Dispose of state and everything.
301 */
302 private void done() {
303
304 // Brute force close. Don't care about errors
305 if (client != null) {
306 try {
307 client.logout();
308 } catch (Exception exx) {
309 }
310 try {
311 client.disconnect();
312 } catch (Exception exx) {
313 }
314 }
315 senderrelay = null;
316 client = null;
317 loggedIn = false;
318 this.log("Connection closed.");
319 // NO NEW CODE BEFORE THIS LINE!
320 }
321
322 /**
323 * Login method. It will fault if a session has not been started or has
324 * expired. The hostname is optional; pass null if not used.
325 *
326 * @param hostname
327 * hostname to use instead of localhost.
328 * @throws CallException
329 */
330 private void login(String hostname) throws CallException {
331
332 // Is it started?
333 if (client == null) {
334 this.error("Session not start()'ed.");
335 }
336
337 try {
338 if (hostname == null) {
339 client.login();
340 } else {
341 client.login(hostname);
342 }
343
344 // what happened?
345 int code = client.getReplyCode();
346 if (code >= SMTP_ERROR_THRESHOLD) {
347 this.error(
348 "Login failed with code="
349 + code
350 + " reply="
351 + client.getReplyString());
352 } else {
353 loggedIn = true;
354 if (this.isDebugging()) {
355 this.debug("Login complete. code=" + code);
356 }
357 }
358
359 } catch (SMTPConnectionClosedException ex) {
360 this.done();
361 this.error("Cannot login. Connection expired and closed itself.");
362 } catch (Exception ex) {
363 this.done();
364 this.error(
365 "Cannot login due to exception. message=" + ex.getMessage());
366 }
367 }
368
369 /**
370 * Sender method. It will fault if a session has not been started or has
371 * expired. It will set the sender. Subsequent calls will overwrite the
372 * value. The address should be a valid email address.
373 *
374 * @param hostname
375 * hostname to use instead of localhost.
376 * @throws CallException
377 */
378 private void sender(String s) throws CallException {
379
380 // Is it started?
381 if (client == null) {
382 this.error("Session not start()'ed.");
383 }
384
385 try {
386 client.setSender(s);
387
388 // what happened?
389 int code = client.getReplyCode();
390 if (code >= SMTP_ERROR_THRESHOLD) {
391 this.error(
392 "Sender failed with code="
393 + code
394 + " reply="
395 + client.getReplyString());
396 } else if (this.isDebugging()) {
397 this.debug("Sender complete. code=" + code);
398 }
399
400 } catch (SMTPConnectionClosedException ex) {
401 this.done();
402 this.error(
403 "Cannot set sender. Connection expired and closed itself.");
404 } catch (Exception ex) {
405 this.done();
406 this.error(
407 "Cannot set sender due to exception. message="
408 + ex.getMessage());
409 }
410 }
411
412 /**
413 * Add sender relay leg method. It will fault if a session has not been
414 * started or has expired. It will start accumulating a sender relay path.
415 * You must call this at least once, if you are going to use senderrelay().
416 * The first call should contain a complete email address at the root of
417 * the relay chain. The accumulation will be reset after done() or other
418 * connection ending event.
419 *
420 * @param leg
421 * relay leg.
422 * @throws CallException
423 */
424 private void addsenderrelay(String leg) throws CallException {
425
426 // Is it started?
427 if (client == null) {
428 this.fault("Session not start()'ed.");
429 }
430
431 try {
432 if (senderrelay == null) {
433 senderrelay = new RelayPath(leg);
434 } else {
435 senderrelay.addRelay(leg);
436 }
437
438 } catch (Exception ex) {
439 this.done();
440 this.error(
441 "Cannot add sender relay due to exception. message="
442 + ex.getMessage());
443 }
444 }
445
446 /**
447 * Sender relay method. It will fault if a session has not been started or
448 * has expired. It will set the sender as the accumulated relay. You must
449 * have called addsenderrelay() at least once or you will get an error.
450 * Subsequent calls will overwrite the value.
451 *
452 * @param hostname
453 * hostname to use instead of localhost.
454 * @throws CallException
455 */
456 private void senderrelay() throws CallException {
457
458 // Is it started?
459 if (client == null) {
460 this.error("Session not start()'ed.");
461 }
462
463 // Is there a relay?
464 if (senderrelay == null) {
465 this.error(
466 "Sender relay not ready. You need to call addsenderrelay() at least once before this method.");
467 return;
468 }
469
470 try {
471 client.setSender(senderrelay);
472
473 // what happened?
474 int code = client.getReplyCode();
475 if (code >= SMTP_ERROR_THRESHOLD) {
476 this.error(
477 "Set sender relay failed with code="
478 + code
479 + " reply="
480 + client.getReplyString());
481 } else if (this.isDebugging()) {
482 this.debug("Set sender relay complete. code=" + code);
483 }
484
485 } catch (SMTPConnectionClosedException ex) {
486 this.done();
487 this.error(
488 "Cannot set sender. Connection expired and closed itself.");
489 } catch (Exception ex) {
490 this.done();
491 this.error(
492 "Cannot set sender due to exception. message="
493 + ex.getMessage());
494 }
495 }
496
497 /**
498 * Recipient method. It will fault if a session has not been started or has
499 * expired. It will add a recipient. Subsequent calls will add to the list
500 * of recipients. The address should be a valid email address. The only way
501 * to clear the list is to call reset() and start over.
502 *
503 * @param hostname
504 * hostname to use instead of localhost.
505 * @throws CallException
506 */
507 private void recipient(String s) throws CallException {
508
509 // Is it started?
510 if (client == null) {
511 this.error("Session not start()'ed.");
512 }
513
514 try {
515 client.addRecipient(s);
516
517 // what happened?
518 int code = client.getReplyCode();
519 if (code >= SMTP_ERROR_THRESHOLD) {
520 this.error(
521 "Add recipient failed with code="
522 + code
523 + " reply="
524 + client.getReplyString());
525 } else if (this.isDebugging()) {
526 this.debug("Add recipient complete. code=" + code);
527 }
528
529 } catch (SMTPConnectionClosedException ex) {
530 this.done();
531 this.error(
532 "Cannot add recipient. Connection expired and closed itself.");
533 } catch (Exception ex) {
534 this.done();
535 this.error(
536 "Cannot add recipient due to exception. message="
537 + ex.getMessage());
538 }
539 }
540
541 /**
542 * Add recipeint relay leg method. It will fault if a session has not been
543 * started or has expired. It will start accumulating a recipeint relay
544 * path. You must call this at least once, if you are going to use
545 * recipient relay(). The first call should contain a complete email
546 * address at the root of the relay chain. The accumulation will be reset
547 * after done(), a call to new recipientrelay(), or some other connection
548 * ending event.
549 *
550 * @param leg
551 * relay leg.
552 * @throws CallException
553 */
554 private void addrecipientrelay(String leg) throws CallException {
555
556 // Is it started?
557 if (client == null) {
558 this.error("Session not start()'ed.");
559 }
560
561 try {
562 if (recipientrelay == null) {
563 recipientrelay = new RelayPath(leg);
564 } else {
565 recipientrelay.addRelay(leg);
566 }
567 } catch (Exception ex) {
568 this.done();
569 this.error(
570 "Cannot add recipient relay due to exception. message="
571 + ex.getMessage());
572 }
573 }
574
575 /**
576 * Recipient relay method. It will fault if a session has not been started
577 * or has expired. It will set the sender as the accumulated relay. You
578 * must have called addrecipientrelay() at least once or you will get an
579 * error. Subsequent calls will overwrite the value.
580 *
581 * @param hostname
582 * hostname to use instead of localhost.
583 * @throws CallException
584 */
585 private void recipientrelay() throws CallException {
586
587 // Is it started?
588 if (client == null) {
589 this.error("Session not start()'ed.");
590 }
591
592 // Is there a relay?
593 if (recipientrelay == null) {
594 this.error(
595 "Recipient relay not ready. You need to call addrecipientrelay() at least once before this method.");
596 return;
597 }
598
599 try {
600 client.addRecipient(recipientrelay);
601
602 // what happened?
603 int code = client.getReplyCode();
604 if (code >= SMTP_ERROR_THRESHOLD) {
605 this.error(
606 "Add recipient relay failed with code="
607 + code
608 + " reply="
609 + client.getReplyString());
610 } else if (this.isDebugging()) {
611 this.debug("Add recipient relay complete. code=" + code);
612 }
613
614 } catch (SMTPConnectionClosedException ex) {
615 this.done();
616 this.error(
617 "Cannot add recipient. Connection expired and closed itself.");
618 } catch (Exception ex) {
619 this.done();
620 this.error(
621 "Cannot add recipient due to exception. message="
622 + ex.getMessage());
623 }
624
625 }
626
627 /**
628 * Clear the recipeint relay accumulation. Do this if you want to start on
629 * a new recipeint relay. This will never report any kind of error.
630 *
631 * @param leg
632 * relay leg.
633 * @throws CallException
634 */
635 private void newrecipientrelay() {
636 recipientrelay = null;
637 }
638
639 /**
640 * Send the message in the text. Returns the SMTP reply code.
641 *
642 * @param hostname
643 * hostname to use instead of localhost.
644 * @throws CallException
645 */
646 private String send(String text) throws CallException {
647
648 String result = ERROR_STRING_FOR_FAILURE;
649
650 // Is it started?
651 if (client == null) {
652 this.error("Session not start()'ed.");
653 }
654
655 // Is there something to send? PARANOID
656 if (text == null) {
657 this.error("Nothing to send.");
658 return result;
659 }
660
661 try {
662
663 client.sendShortMessageData(text);
664 //client.completePendingCommand(); // don't care if it was ok.
665 result = Integer.toString(client.getReplyCode());
666
667 // what happened?
668 int code = client.getReplyCode();
669 if (code >= SMTP_ERROR_THRESHOLD) {
670 this.error(
671 "Message send FAILED. code="
672 + code
673 + " reply="
674 + client.getReplyString());
675 } else if (this.isDebugging()) {
676 this.debug(
677 "Message send complete. code="
678 + code
679 + " reply="
680 + client.getReplyString());
681 }
682
683 } catch (SMTPConnectionClosedException ex) {
684 this.done();
685 this.error("Send failed. Connection expired and closed itself." + " last reply="
686 + client.getReplyString());
687 } catch (Exception ex) {
688 this.done();
689 this.error(
690 "Send failed due to exception. message=" + ex.getMessage());
691 }
692 return result;
693 }
694
695 /**
696 * Send the message in a Universe Object. Returns the SMTP reply code.
697 *
698 * @param hostname
699 * hostname to use instead of localhost.
700 * @throws CallException
701 */
702 private String senduni(String uniobject) throws CallException {
703
704 String result = ERROR_STRING_FOR_FAILURE;
705
706 // Is it started?
707 if (client == null) {
708 this.error("Session not start()'ed.");
709 }
710
711 try {
712 // get the hoses
713 InputStream unio = visUniverse.getStream(uniobject);
714 BufferedReader bin =
715 new BufferedReader(new InputStreamReader(unio));
716 Writer mwriter = client.sendMessageData();
717
718 // and pipe them together
719 if (mwriter != null) {
720 Util.copyReader(bin, mwriter);
721 mwriter.close();
722 unio.close();
723 client.completePendingCommand(); // don't care if it was ok.
724
725 // what happened?
726 int code = client.getReplyCode();
727 if (code >= SMTP_ERROR_THRESHOLD) {
728 this.error(
729 "Message send FAILED (from Universe). code="
730 + code
731 + " reply="
732 + client.getReplyString());
733 } else if (this.isDebugging()) {
734 this.debug("Message send complete (from Universe). code=");
735 }
736 result = Integer.toString(code);
737
738 } else {
739 this.log(
740 "Message send FAILED (from Universe) because SMTP connection was completely ready. reply="
741 + client.getReplyString());
742 }
743
744 } catch (UniverseException uex) {
745 this.fault(
746 "Could not send universe object due to Universe problem. code="
747 + uex.numeric
748 + " message="
749 + uex.getMessage(),
750 uex);
751 } catch (SMTPConnectionClosedException ex) {
752 this.done();
753 this.error(
754 "Send failed (from Universe). Connection expired and closed itself. Last reply="
755 + client.getReplyString());
756 } catch (Exception ex) {
757 this.done();
758 this.error(
759 "Send failed (from Universe) due to exception. message="
760 + ex.getMessage());
761 }
762 return result;
763 }
764
765 /**
766 * Send the message in a Universe Object. Returns the SMTP reply code. It
767 * will run a variable replace on it before sending it.
768 *
769 * @param hostname
770 * hostname to use instead of localhost.
771 * @throws CallException
772 */
773 private String senduniscrub(String uniobject) throws CallException {
774
775 String result = ERROR_STRING_FOR_FAILURE;
776 String tempObj = null;
777
778 // Is it started?
779 if (client == null) {
780 this.error("Session not start()'ed.");
781 }
782
783 try {
784
785 // Process it
786 try {
787 tempObj = visUniverse.reserveUnique(TEMPFILE);
788 OutputStream os = visUniverse.putStream(tempObj);
789 StringProcessors.evalStreams2Core(visUniverse.getStream(uniobject), os, visCore);
790 os.close();
791
792 } catch (UniverseException ue) {
793 throw ue;
794 } catch (Exception e) {
795 this.fault(
796 "Send failed (from Universe). Could not create scrubbed intermediary tempfile. message="
797 + e.getMessage());
798 }
799
800 // get the hoses
801 InputStream unio = visUniverse.getStream(tempObj);
802 BufferedReader bin =
803 new BufferedReader(new InputStreamReader(unio));
804 Writer mwriter = client.sendMessageData();
805
806 // and pipe them together
807 if (mwriter != null) {
808 Util.copyReader(bin, mwriter);
809 mwriter.close();
810 unio.close();
811 client.completePendingCommand(); // don't care if it was ok.
812
813 // what happened?
814 int code = client.getReplyCode();
815 if (code >= SMTP_ERROR_THRESHOLD) {
816 this.error(
817 "Message send FAILED (from Universe). code="
818 + code
819 + " reply="
820 + client.getReplyString());
821 } else if (this.isDebugging()) {
822 this.debug("Message send complete (from Universe). code=");
823 }
824 result = Integer.toString(code);
825
826 } else {
827 this.log(
828 "Message send FAILED (from Universe) because SMTP connection was completely ready. reply="
829 + client.getReplyString());
830 }
831
832 } catch (CallException cex) {
833 throw cex;
834 } catch (UniverseException uex) {
835 this.fault(
836 "Could not send universe object due to Universe problem. code="
837 + uex.numeric
838 + " message="
839 + uex.getMessage(),
840 uex);
841 } catch (SMTPConnectionClosedException ex) {
842 this.done();
843 this.error(
844 "Send failed (from Universe). Connection expired and closed itself. Last reply="
845 + client.getReplyString());
846 } catch (Exception ex) {
847 this.done();
848 this.error(
849 "Send failed (from Universe) due to exception. message="
850 + ex.getMessage());
851 } finally {
852 if ((!this.isDebugging()) && (tempObj != null)) {
853 try {
854 visUniverse.remove(tempObj);
855 } catch (Exception ee) {
856 // Don't care
857 }
858 }
859 }
860 return result;
861 }
862
863 /**
864 * Reset method. It will never give an error, even if not start()'ed.
865 *
866 * @throws CallException
867 */
868 private void reset() throws CallException {
869 try {
870 if (client != null)
871 client.reset();
872
873 // what happened?
874 int code = client.getReplyCode();
875 if (code >= SMTP_ERROR_THRESHOLD) {
876 this.error(
877 "Reset FAILED with code="
878 + code
879 + " reply="
880 + client.getReplyString());
881 this.done();
882 } else if (this.isDebugging()) {
883 this.debug("Reset complete. code=" + code);
884 }
885
886 } catch (Exception ex) {
887 }
888 }
889
890 /**
891 * Mailit method. A complete transaction wrapped into a convenient method.
892 * It will start a session using host/port parameters. If a session is
893 * already started, host/port will be ignored and the current session will
894 * be used.
895 *
896 * @param to
897 * TO address.
898 * @param from
899 * FROM address.
900 * @param text
901 * to send as the message
902 * @param host
903 * address of smpt server or relay
904 * @param port
905 * optional port
906 * @throws CallException
907 */
908 private String mailit(
909 String to,
910 String from,
911 String text,
912 String host,
913 String port)
914 throws CallException {
915
916 String response = null;
917
918 // Is it started?
919 if (client == null) {
920 this.start(host, port);
921 }
922
923 if (client == null) return "XXX";
924
925 try {
926
927 if (loggedIn == false)
928 this.login(null);
929 this.reset();
930 this.sender(from);
931 this.recipient(to);
932 response = this.send(text);
933
934 } catch (CallException ce) {
935 this.done();
936 throw ce;
937 } catch (Exception ee) {
938 this.done();
939 this.fault("Serious exception caused FAULT while sending. message=" + ee.getMessage());
940 }
941 return response;
942 }
943
944 /**
945 * Mailituni method. A complete transaction wrapped into a convenient
946 * method. It will start a session using host/port parameters. If a session
947 * is already started, host/port will be ignored and the current session
948 * will be used.
949 *
950 * @param to
951 * TO address.
952 * @param from
953 * FROM address.
954 * @param uniobj
955 * to send as the message from universe
956 * @param host
957 * address of smpt server or relay
958 * @param port
959 * optional port
960 * @throws CallException
961 */
962 private String mailituni(
963 String to,
964 String from,
965 String uniobj,
966 String host,
967 String port)
968 throws CallException {
969
970 String response = null;
971
972 // Is it started?
973 if (client == null) {
974 this.start(host, port);
975 }
976
977 if (client == null) return "XXX";
978
979 try {
980 if (loggedIn == false)
981 this.login(null);
982 this.reset();
983 this.sender(from);
984 this.recipient(to);
985 response = this.senduniscrub(uniobj);
986
987 } catch (CallException ce) {
988 this.done();
989 throw ce;
990 } catch (Exception ee) {
991 this.done();
992 this.fault("Serious exception caused FAULT while sending. message=" + ee.getMessage());
993 }
994 return response;
995 }
996 }
|