View Javadoc

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