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  */