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