001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.net.smtp;
019
020 import java.io.BufferedReader;
021 import java.io.BufferedWriter;
022 import java.io.IOException;
023 import java.io.InputStreamReader;
024 import java.io.OutputStreamWriter;
025 import java.util.ArrayList;
026
027 import org.apache.commons.net.MalformedServerReplyException;
028 import org.apache.commons.net.ProtocolCommandSupport;
029 import org.apache.commons.net.SocketClient;
030 import org.apache.commons.net.io.CRLFLineReader;
031
032 /***
033 * SMTP provides the basic the functionality necessary to implement your
034 * own SMTP client. To derive the full benefits of the SMTP class requires
035 * some knowledge of the FTP protocol defined in RFC 821. However, there
036 * is no reason why you should have to use the SMTP class. The
037 * {@link org.apache.commons.net.smtp.SMTPClient} class,
038 * derived from SMTP,
039 * implements all the functionality required of an SMTP client. The
040 * SMTP class is made public to provide access to various SMTP constants
041 * and to make it easier for adventurous programmers (or those with
042 * special needs) to interact with the SMTP protocol and implement their
043 * own clients. A set of methods with names corresponding to the SMTP
044 * command names are provided to facilitate this interaction.
045 * <p>
046 * You should keep in mind that the SMTP server may choose to prematurely
047 * close a connection for various reasons. The SMTP class will detect a
048 * premature SMTP server connection closing when it receives a
049 * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
050 * response to a command.
051 * When that occurs, the SMTP class method encountering that reply will throw
052 * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
053 * .
054 * <code>SMTPConectionClosedException</code>
055 * is a subclass of <code> IOException </code> and therefore need not be
056 * caught separately, but if you are going to catch it separately, its
057 * catch block must appear before the more general <code> IOException </code>
058 * catch block. When you encounter an
059 * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
060 * , you must disconnect the connection with
061 * {@link org.apache.commons.net.SocketClient#disconnect disconnect() }
062 * to properly clean up the system resources used by SMTP. Before
063 * disconnecting, you may check the
064 * last reply code and text with
065 * {@link #getReplyCode getReplyCode },
066 * {@link #getReplyString getReplyString },
067 * and {@link #getReplyStrings getReplyStrings}.
068 * <p>
069 * Rather than list it separately for each method, we mention here that
070 * every method communicating with the server and throwing an IOException
071 * can also throw a
072 * {@link org.apache.commons.net.MalformedServerReplyException}
073 * , which is a subclass
074 * of IOException. A MalformedServerReplyException will be thrown when
075 * the reply received from the server deviates enough from the protocol
076 * specification that it cannot be interpreted in a useful manner despite
077 * attempts to be as lenient as possible.
078 * <p>
079 * <p>
080 * @see SMTPClient
081 * @see SMTPConnectionClosedException
082 * @see org.apache.commons.net.MalformedServerReplyException
083 ***/
084
085 public class SMTP extends SocketClient
086 {
087 /*** The default SMTP port (25). ***/
088 public static final int DEFAULT_PORT = 25;
089
090 // We have to ensure that the protocol communication is in ASCII
091 // but we use ISO-8859-1 just in case 8-bit characters cross
092 // the wire.
093 private static final String __DEFAULT_ENCODING = "ISO-8859-1";
094
095 /**
096 * The encoding to use (user-settable).
097 *
098 * @since 3.1 (changed from private to protected)
099 */
100 protected final String encoding;
101
102 /**
103 * A ProtocolCommandSupport object used to manage the registering of
104 * ProtocolCommandListeners and te firing of ProtocolCommandEvents.
105 */
106 protected ProtocolCommandSupport _commandSupport_;
107
108 BufferedReader _reader;
109 BufferedWriter _writer;
110
111 private int _replyCode;
112 private final ArrayList<String> _replyLines;
113 private boolean _newReplyString;
114 private String _replyString;
115
116 /***
117 * The default SMTP constructor. Sets the default port to
118 * <code>DEFAULT_PORT</code> and initializes internal data structures
119 * for saving SMTP reply information.
120 ***/
121 public SMTP()
122 {
123 this(__DEFAULT_ENCODING);
124 }
125
126 /**
127 * Overloaded constructor where the user may specify a default encoding.
128 * @param encoding
129 * @since 2.0
130 */
131 public SMTP(String encoding) {
132 setDefaultPort(DEFAULT_PORT);
133 _replyLines = new ArrayList<String>();
134 _newReplyString = false;
135 _replyString = null;
136 _commandSupport_ = new ProtocolCommandSupport(this);
137 this.encoding = encoding;
138 }
139
140 /**
141 * Send a command to the server. May also be used to send text data.
142 *
143 * @param command the command to send (as a plain String)
144 * @param args the command arguments, may be {@code null}
145 * @param includeSpace if {@code true}, add a space between the command and its arguments
146 * @return the reply code
147 * @throws IOException
148 */
149 private int __sendCommand(String command, String args, boolean includeSpace)
150 throws IOException
151 {
152 StringBuilder __commandBuffer = new StringBuilder();
153 __commandBuffer.append(command);
154
155 if (args != null)
156 {
157 if (includeSpace) {
158 __commandBuffer.append(' ');
159 }
160 __commandBuffer.append(args);
161 }
162
163 __commandBuffer.append(SocketClient.NETASCII_EOL);
164
165 String message;
166 _writer.write(message = __commandBuffer.toString());
167 _writer.flush();
168
169 fireCommandSent(command, message);
170
171 __getReply();
172 return _replyCode;
173 }
174
175 /**
176 *
177 * @param command the command to send (as an int defined in {@link SMPTCommand})
178 * @param args the command arguments, may be {@code null}
179 * @param includeSpace if {@code true}, add a space between the command and its arguments
180 * @return the reply code
181 * @throws IOException
182 */
183 private int __sendCommand(int command, String args, boolean includeSpace)
184 throws IOException
185 {
186 return __sendCommand(SMTPCommand.getCommand(command), args, includeSpace);
187 }
188
189 private void __getReply() throws IOException
190 {
191 int length;
192
193 _newReplyString = true;
194 _replyLines.clear();
195
196 String line = _reader.readLine();
197
198 if (line == null) {
199 throw new SMTPConnectionClosedException(
200 "Connection closed without indication.");
201 }
202
203 // In case we run into an anomaly we don't want fatal index exceptions
204 // to be thrown.
205 length = line.length();
206 if (length < 3) {
207 throw new MalformedServerReplyException(
208 "Truncated server reply: " + line);
209 }
210
211 try
212 {
213 String code = line.substring(0, 3);
214 _replyCode = Integer.parseInt(code);
215 }
216 catch (NumberFormatException e)
217 {
218 throw new MalformedServerReplyException(
219 "Could not parse response code.\nServer Reply: " + line);
220 }
221
222 _replyLines.add(line);
223
224 // Get extra lines if message continues.
225 if (length > 3 && line.charAt(3) == '-')
226 {
227 do
228 {
229 line = _reader.readLine();
230
231 if (line == null) {
232 throw new SMTPConnectionClosedException(
233 "Connection closed without indication.");
234 }
235
236 _replyLines.add(line);
237
238 // The length() check handles problems that could arise from readLine()
239 // returning too soon after encountering a naked CR or some other
240 // anomaly.
241 }
242 while (!(line.length() >= 4 && line.charAt(3) != '-' &&
243 Character.isDigit(line.charAt(0))));
244 // This is too strong a condition because a non-conforming server
245 // could screw things up like ftp.funet.fi does for FTP
246 // line.startsWith(code)));
247 }
248
249 fireReplyReceived(_replyCode, getReplyString());
250
251 if (_replyCode == SMTPReply.SERVICE_NOT_AVAILABLE) {
252 throw new SMTPConnectionClosedException(
253 "SMTP response 421 received. Server closed connection.");
254 }
255 }
256
257 /*** Initiates control connections and gets initial reply. ***/
258 @Override
259 protected void _connectAction_() throws IOException
260 {
261 super._connectAction_();
262 _reader =
263 new CRLFLineReader(new InputStreamReader(_input_,
264 encoding));
265 _writer =
266 new BufferedWriter(new OutputStreamWriter(_output_,
267 encoding));
268 __getReply();
269
270 }
271
272
273 /***
274 * Closes the connection to the SMTP server and sets to null
275 * some internal data so that the memory may be reclaimed by the
276 * garbage collector. The reply text and code information from the
277 * last command is voided so that the memory it used may be reclaimed.
278 * <p>
279 * @exception IOException If an error occurs while disconnecting.
280 ***/
281 @Override
282 public void disconnect() throws IOException
283 {
284 super.disconnect();
285 _reader = null;
286 _writer = null;
287 _replyString = null;
288 _replyLines.clear();
289 _newReplyString = false;
290 }
291
292
293 /***
294 * Sends an SMTP command to the server, waits for a reply and returns the
295 * numerical response code. After invocation, for more detailed
296 * information, the actual reply text can be accessed by calling
297 * {@link #getReplyString getReplyString } or
298 * {@link #getReplyStrings getReplyStrings }.
299 * <p>
300 * @param command The text representation of the SMTP command to send.
301 * @param args The arguments to the SMTP command. If this parameter is
302 * set to null, then the command is sent with no argument.
303 * @return The integer value of the SMTP reply code returned by the server
304 * in response to the command.
305 * @exception SMTPConnectionClosedException
306 * If the SMTP server prematurely closes the connection as a result
307 * of the client being idle or some other reason causing the server
308 * to send SMTP reply code 421. This exception may be caught either
309 * as an IOException or independently as itself.
310 * @exception IOException If an I/O error occurs while either sending the
311 * command or receiving the server reply.
312 ***/
313 public int sendCommand(String command, String args) throws IOException
314 {
315 return __sendCommand(command, args, true);
316 }
317
318
319 /***
320 * Sends an SMTP command to the server, waits for a reply and returns the
321 * numerical response code. After invocation, for more detailed
322 * information, the actual reply text can be accessed by calling
323 * {@link #getReplyString getReplyString } or
324 * {@link #getReplyStrings getReplyStrings }.
325 * <p>
326 * @param command The SMTPCommand constant corresponding to the SMTP command
327 * to send.
328 * @param args The arguments to the SMTP command. If this parameter is
329 * set to null, then the command is sent with no argument.
330 * @return The integer value of the SMTP reply code returned by the server
331 * in response to the command.
332 * @exception SMTPConnectionClosedException
333 * If the SMTP server prematurely closes the connection as a result
334 * of the client being idle or some other reason causing the server
335 * to send SMTP reply code 421. This exception may be caught either
336 * as an IOException or independently as itself.
337 * @exception IOException If an I/O error occurs while either sending the
338 * command or receiving the server reply.
339 ***/
340 public int sendCommand(int command, String args) throws IOException
341 {
342 return sendCommand(SMTPCommand.getCommand(command), args);
343 }
344
345
346 /***
347 * Sends an SMTP command with no arguments to the server, waits for a
348 * reply and returns the numerical response code. After invocation, for
349 * more detailed information, the actual reply text can be accessed by
350 * calling {@link #getReplyString getReplyString } or
351 * {@link #getReplyStrings getReplyStrings }.
352 * <p>
353 * @param command The text representation of the SMTP command to send.
354 * @return The integer value of the SMTP reply code returned by the server
355 * in response to the command.
356 * @exception SMTPConnectionClosedException
357 * If the SMTP server prematurely closes the connection as a result
358 * of the client being idle or some other reason causing the server
359 * to send SMTP reply code 421. This exception may be caught either
360 * as an IOException or independently as itself.
361 * @exception IOException If an I/O error occurs while either sending the
362 * command or receiving the server reply.
363 ***/
364 public int sendCommand(String command) throws IOException
365 {
366 return sendCommand(command, null);
367 }
368
369
370 /***
371 * Sends an SMTP command with no arguments to the server, waits for a
372 * reply and returns the numerical response code. After invocation, for
373 * more detailed information, the actual reply text can be accessed by
374 * calling {@link #getReplyString getReplyString } or
375 * {@link #getReplyStrings getReplyStrings }.
376 * <p>
377 * @param command The SMTPCommand constant corresponding to the SMTP command
378 * to send.
379 * @return The integer value of the SMTP reply code returned by the server
380 * in response to the command.
381 * @exception SMTPConnectionClosedException
382 * If the SMTP server prematurely closes the connection as a result
383 * of the client being idle or some other reason causing the server
384 * to send SMTP reply code 421. This exception may be caught either
385 * as an IOException or independently as itself.
386 * @exception IOException If an I/O error occurs while either sending the
387 * command or receiving the server reply.
388 ***/
389 public int sendCommand(int command) throws IOException
390 {
391 return sendCommand(command, null);
392 }
393
394
395 /***
396 * Returns the integer value of the reply code of the last SMTP reply.
397 * You will usually only use this method after you connect to the
398 * SMTP server to check that the connection was successful since
399 * <code> connect </code> is of type void.
400 * <p>
401 * @return The integer value of the reply code of the last SMTP reply.
402 ***/
403 public int getReplyCode()
404 {
405 return _replyCode;
406 }
407
408 /***
409 * Fetches a reply from the SMTP server and returns the integer reply
410 * code. After calling this method, the actual reply text can be accessed
411 * from either calling {@link #getReplyString getReplyString } or
412 * {@link #getReplyStrings getReplyStrings }. Only use this
413 * method if you are implementing your own SMTP client or if you need to
414 * fetch a secondary response from the SMTP server.
415 * <p>
416 * @return The integer value of the reply code of the fetched SMTP reply.
417 * @exception SMTPConnectionClosedException
418 * If the SMTP server prematurely closes the connection as a result
419 * of the client being idle or some other reason causing the server
420 * to send SMTP reply code 421. This exception may be caught either
421 * as an IOException or independently as itself.
422 * @exception IOException If an I/O error occurs while receiving the
423 * server reply.
424 ***/
425 public int getReply() throws IOException
426 {
427 __getReply();
428 return _replyCode;
429 }
430
431
432 /***
433 * Returns the lines of text from the last SMTP server response as an array
434 * of strings, one entry per line. The end of line markers of each are
435 * stripped from each line.
436 * <p>
437 * @return The lines of text from the last SMTP response as an array.
438 ***/
439 public String[] getReplyStrings()
440 {
441 return _replyLines.toArray(new String[_replyLines.size()]);
442 }
443
444 /***
445 * Returns the entire text of the last SMTP server response exactly
446 * as it was received, including all end of line markers in NETASCII
447 * format.
448 * <p>
449 * @return The entire text from the last SMTP response as a String.
450 ***/
451 public String getReplyString()
452 {
453 StringBuilder buffer;
454
455 if (!_newReplyString) {
456 return _replyString;
457 }
458
459 buffer = new StringBuilder();
460
461 for (String line : _replyLines)
462 {
463 buffer.append(line);
464 buffer.append(SocketClient.NETASCII_EOL);
465 }
466
467 _newReplyString = false;
468
469 return (_replyString = buffer.toString());
470 }
471
472
473 /***
474 * A convenience method to send the SMTP HELO command to the server,
475 * receive the reply, and return the reply code.
476 * <p>
477 * @param hostname The hostname of the sender.
478 * @return The reply code received from the server.
479 * @exception SMTPConnectionClosedException
480 * If the SMTP server prematurely closes the connection as a result
481 * of the client being idle or some other reason causing the server
482 * to send SMTP reply code 421. This exception may be caught either
483 * as an IOException or independently as itself.
484 * @exception IOException If an I/O error occurs while either sending the
485 * command or receiving the server reply.
486 ***/
487 public int helo(String hostname) throws IOException
488 {
489 return sendCommand(SMTPCommand.HELO, hostname);
490 }
491
492
493 /***
494 * A convenience method to send the SMTP MAIL command to the server,
495 * receive the reply, and return the reply code.
496 * <p>
497 * @param reversePath The reverese path.
498 * @return The reply code received from the server.
499 * @exception SMTPConnectionClosedException
500 * If the SMTP server prematurely closes the connection as a result
501 * of the client being idle or some other reason causing the server
502 * to send SMTP reply code 421. This exception may be caught either
503 * as an IOException or independently as itself.
504 * @exception IOException If an I/O error occurs while either sending the
505 * command or receiving the server reply.
506 ***/
507 public int mail(String reversePath) throws IOException
508 {
509 return __sendCommand(SMTPCommand.MAIL, reversePath, false);
510 }
511
512
513 /***
514 * A convenience method to send the SMTP RCPT command to the server,
515 * receive the reply, and return the reply code.
516 * <p>
517 * @param forwardPath The forward path.
518 * @return The reply code received from the server.
519 * @exception SMTPConnectionClosedException
520 * If the SMTP server prematurely closes the connection as a result
521 * of the client being idle or some other reason causing the server
522 * to send SMTP reply code 421. This exception may be caught either
523 * as an IOException or independently as itself.
524 * @exception IOException If an I/O error occurs while either sending the
525 * command or receiving the server reply.
526 ***/
527 public int rcpt(String forwardPath) throws IOException
528 {
529 return __sendCommand(SMTPCommand.RCPT, forwardPath, false);
530 }
531
532
533 /***
534 * A convenience method to send the SMTP DATA command to the server,
535 * receive the reply, and return the reply code.
536 * <p>
537 * @return The reply code received from the server.
538 * @exception SMTPConnectionClosedException
539 * If the SMTP server prematurely closes the connection as a result
540 * of the client being idle or some other reason causing the server
541 * to send SMTP reply code 421. This exception may be caught either
542 * as an IOException or independently as itself.
543 * @exception IOException If an I/O error occurs while either sending the
544 * command or receiving the server reply.
545 ***/
546 public int data() throws IOException
547 {
548 return sendCommand(SMTPCommand.DATA);
549 }
550
551
552 /***
553 * A convenience method to send the SMTP SEND command to the server,
554 * receive the reply, and return the reply code.
555 * <p>
556 * @param reversePath The reverese path.
557 * @return The reply code received from the server.
558 * @exception SMTPConnectionClosedException
559 * If the SMTP server prematurely closes the connection as a result
560 * of the client being idle or some other reason causing the server
561 * to send SMTP reply code 421. This exception may be caught either
562 * as an IOException or independently as itself.
563 * @exception IOException If an I/O error occurs while either sending the
564 * command or receiving the server reply.
565 ***/
566 public int send(String reversePath) throws IOException
567 {
568 return sendCommand(SMTPCommand.SEND, reversePath);
569 }
570
571
572 /***
573 * A convenience method to send the SMTP SOML command to the server,
574 * receive the reply, and return the reply code.
575 * <p>
576 * @param reversePath The reverese path.
577 * @return The reply code received from the server.
578 * @exception SMTPConnectionClosedException
579 * If the SMTP server prematurely closes the connection as a result
580 * of the client being idle or some other reason causing the server
581 * to send SMTP reply code 421. This exception may be caught either
582 * as an IOException or independently as itself.
583 * @exception IOException If an I/O error occurs while either sending the
584 * command or receiving the server reply.
585 ***/
586 public int soml(String reversePath) throws IOException
587 {
588 return sendCommand(SMTPCommand.SOML, reversePath);
589 }
590
591
592 /***
593 * A convenience method to send the SMTP SAML command to the server,
594 * receive the reply, and return the reply code.
595 * <p>
596 * @param reversePath The reverese path.
597 * @return The reply code received from the server.
598 * @exception SMTPConnectionClosedException
599 * If the SMTP server prematurely closes the connection as a result
600 * of the client being idle or some other reason causing the server
601 * to send SMTP reply code 421. This exception may be caught either
602 * as an IOException or independently as itself.
603 * @exception IOException If an I/O error occurs while either sending the
604 * command or receiving the server reply.
605 ***/
606 public int saml(String reversePath) throws IOException
607 {
608 return sendCommand(SMTPCommand.SAML, reversePath);
609 }
610
611
612 /***
613 * A convenience method to send the SMTP RSET command to the server,
614 * receive the reply, and return the reply code.
615 * <p>
616 * @return The reply code received from the server.
617 * @exception SMTPConnectionClosedException
618 * If the SMTP server prematurely closes the connection as a result
619 * of the client being idle or some other reason causing the server
620 * to send SMTP reply code 421. This exception may be caught either
621 * as an IOException or independently as itself.
622 * @exception IOException If an I/O error occurs while either sending the
623 * command or receiving the server reply.
624 ***/
625 public int rset() throws IOException
626 {
627 return sendCommand(SMTPCommand.RSET);
628 }
629
630
631 /***
632 * A convenience method to send the SMTP VRFY command to the server,
633 * receive the reply, and return the reply code.
634 * <p>
635 * @param user The user address to verify.
636 * @return The reply code received from the server.
637 * @exception SMTPConnectionClosedException
638 * If the SMTP server prematurely closes the connection as a result
639 * of the client being idle or some other reason causing the server
640 * to send SMTP reply code 421. This exception may be caught either
641 * as an IOException or independently as itself.
642 * @exception IOException If an I/O error occurs while either sending the
643 * command or receiving the server reply.
644 ***/
645 public int vrfy(String user) throws IOException
646 {
647 return sendCommand(SMTPCommand.VRFY, user);
648 }
649
650
651 /***
652 * A convenience method to send the SMTP VRFY command to the server,
653 * receive the reply, and return the reply code.
654 * <p>
655 * @param name The name to expand.
656 * @return The reply code received from the server.
657 * @exception SMTPConnectionClosedException
658 * If the SMTP server prematurely closes the connection as a result
659 * of the client being idle or some other reason causing the server
660 * to send SMTP reply code 421. This exception may be caught either
661 * as an IOException or independently as itself.
662 * @exception IOException If an I/O error occurs while either sending the
663 * command or receiving the server reply.
664 ***/
665 public int expn(String name) throws IOException
666 {
667 return sendCommand(SMTPCommand.EXPN, name);
668 }
669
670 /***
671 * A convenience method to send the SMTP HELP command to the server,
672 * receive the reply, and return the reply code.
673 * <p>
674 * @return The reply code received from the server.
675 * @exception SMTPConnectionClosedException
676 * If the SMTP server prematurely closes the connection as a result
677 * of the client being idle or some other reason causing the server
678 * to send SMTP reply code 421. This exception may be caught either
679 * as an IOException or independently as itself.
680 * @exception IOException If an I/O error occurs while either sending the
681 * command or receiving the server reply.
682 ***/
683 public int help() throws IOException
684 {
685 return sendCommand(SMTPCommand.HELP);
686 }
687
688 /***
689 * A convenience method to send the SMTP HELP command to the server,
690 * receive the reply, and return the reply code.
691 * <p>
692 * @param command The command name on which to request help.
693 * @return The reply code received from the server.
694 * @exception SMTPConnectionClosedException
695 * If the SMTP server prematurely closes the connection as a result
696 * of the client being idle or some other reason causing the server
697 * to send SMTP reply code 421. This exception may be caught either
698 * as an IOException or independently as itself.
699 * @exception IOException If an I/O error occurs while either sending the
700 * command or receiving the server reply.
701 ***/
702 public int help(String command) throws IOException
703 {
704 return sendCommand(SMTPCommand.HELP, command);
705 }
706
707 /***
708 * A convenience method to send the SMTP NOOP command to the server,
709 * receive the reply, and return the reply code.
710 * <p>
711 * @return The reply code received from the server.
712 * @exception SMTPConnectionClosedException
713 * If the SMTP server prematurely closes the connection as a result
714 * of the client being idle or some other reason causing the server
715 * to send SMTP reply code 421. This exception may be caught either
716 * as an IOException or independently as itself.
717 * @exception IOException If an I/O error occurs while either sending the
718 * command or receiving the server reply.
719 ***/
720 public int noop() throws IOException
721 {
722 return sendCommand(SMTPCommand.NOOP);
723 }
724
725
726 /***
727 * A convenience method to send the SMTP TURN command to the server,
728 * receive the reply, and return the reply code.
729 * <p>
730 * @return The reply code received from the server.
731 * @exception SMTPConnectionClosedException
732 * If the SMTP server prematurely closes the connection as a result
733 * of the client being idle or some other reason causing the server
734 * to send SMTP reply code 421. This exception may be caught either
735 * as an IOException or independently as itself.
736 * @exception IOException If an I/O error occurs while either sending the
737 * command or receiving the server reply.
738 ***/
739 public int turn() throws IOException
740 {
741 return sendCommand(SMTPCommand.TURN);
742 }
743
744
745 /***
746 * A convenience method to send the SMTP QUIT command to the server,
747 * receive the reply, and return the reply code.
748 * <p>
749 * @return The reply code received from the server.
750 * @exception SMTPConnectionClosedException
751 * If the SMTP server prematurely closes the connection as a result
752 * of the client being idle or some other reason causing the server
753 * to send SMTP reply code 421. This exception may be caught either
754 * as an IOException or independently as itself.
755 * @exception IOException If an I/O error occurs while either sending the
756 * command or receiving the server reply.
757 ***/
758 public int quit() throws IOException
759 {
760 return sendCommand(SMTPCommand.QUIT);
761 }
762
763 /**
764 * Removes a ProtocolCommandListener.
765 *
766 * Delegates this incorrectly named method - removeProtocolCommandistener (note the missing "L")- to
767 * the correct method {@link SocketClient#removeProtocolCommandListener}
768 * @param listener The ProtocolCommandListener to remove
769 */
770 public void removeProtocolCommandistener(org.apache.commons.net.ProtocolCommandListener listener){
771 removeProtocolCommandListener(listener);
772 }
773
774 /**
775 * Provide command support to super-class
776 */
777 @Override
778 protected ProtocolCommandSupport getCommandSupport() {
779 return _commandSupport_;
780 }
781 }
782
783 /* Emacs configuration
784 * Local variables: **
785 * mode: java **
786 * c-basic-offset: 4 **
787 * indent-tabs-mode: nil **
788 * End: **
789 */