    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.net.smtp;
    019
    020import java.io.BufferedReader;
    021import java.io.BufferedWriter;
    022import java.io.IOException;
    023import java.io.InputStreamReader;
    024import java.io.OutputStreamWriter;
    025import java.util.ArrayList;
    026
    027import org.apache.commons.net.MalformedServerReplyException;
    028import org.apache.commons.net.ProtocolCommandSupport;
    029import org.apache.commons.net.SocketClient;
    030import org.apache.commons.net.io.CRLFLineReader;
    031
    032/***
    033 * SMTP provides the basic the functionality necessary to implement your
    034 * own SMTP client.  To derive the full benefits of the SMTP class requires
    035 * some knowledge of the FTP protocol defined in RFC 821.  However, there
    036 * is no reason why you should have to use the SMTP class.  The
    037 * {@link org.apache.commons.net.smtp.SMTPClient} class,
    038 * derived from SMTP,
    039 * implements all the functionality required of an SMTP client.  The
    040 * SMTP class is made public to provide access to various SMTP constants
    041 * and to make it easier for adventurous programmers (or those with
    042 * special needs) to interact with the SMTP protocol and implement their
    043 * own clients.  A set of methods with names corresponding to the SMTP
    044 * command names are provided to facilitate this interaction.
    045 * <p>
    046 * You should keep in mind that the SMTP server may choose to prematurely
    047 * close a connection for various reasons.  The SMTP class will detect a
    048 * premature SMTP server connection closing when it receives a
    049 * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
    050 *  response to a command.
    051 * When that occurs, the SMTP class method encountering that reply will throw
    052 * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
    053 * .
    054 * <code>SMTPConectionClosedException</code>
    055 * is a subclass of <code> IOException </code> and therefore need not be
    056 * caught separately, but if you are going to catch it separately, its
    057 * catch block must appear before the more general <code> IOException </code>
    058 * catch block.  When you encounter an
    059 * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
    060 * , you must disconnect the connection with
    061 * {@link org.apache.commons.net.SocketClient#disconnect  disconnect() }
    062 * to properly clean up the system resources used by SMTP.  Before
    063 * disconnecting, you may check the
    064 * last reply code and text with
    065 * {@link #getReplyCode  getReplyCode },
    066 * {@link #getReplyString  getReplyString },
    067 * and {@link #getReplyStrings  getReplyStrings}.
    068 * <p>
    069 * Rather than list it separately for each method, we mention here that
    070 * every method communicating with the server and throwing an IOException
    071 * can also throw a
    072 * {@link org.apache.commons.net.MalformedServerReplyException}
    073 * , which is a subclass
    074 * of IOException.  A MalformedServerReplyException will be thrown when
    075 * the reply received from the server deviates enough from the protocol
    076 * specification that it cannot be interpreted in a useful manner despite
    077 * attempts to be as lenient as possible.
    078 *
    079 * @see SMTPClient
    080 * @see SMTPConnectionClosedException
    081 * @see org.apache.commons.net.MalformedServerReplyException
    082 ***/
    083
    084public class SMTP extends SocketClient
    085{
    086    /*** The default SMTP port (25). ***/
    087    public static final int DEFAULT_PORT = 25;
    088
    089    // We have to ensure that the protocol communication is in ASCII
    090    // but we use ISO-8859-1 just in case 8-bit characters cross
    091    // the wire.
    092    private static final String DEFAULT_ENCODING = "ISO-8859-1";
    093
    094    /**
    095     * The encoding to use (user-settable).
    096     *
    097     * @since 3.1 (changed from private to protected)
    098     */
    099    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(final String encoding) {
    131        setDefaultPort(DEFAULT_PORT);
    132        replyLines = new ArrayList<>();
    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(final String command, final String args, final boolean includeSpace)
    149    throws IOException
    150    {
    151        final 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        final String message = __commandBuffer.toString();
    165        writer.write(message);
    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(final int command, final String args, final 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            final String code = line.substring(0, 3);
    213            replyCode = Integer.parseInt(code);
    214        }
    215        catch (final 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     * @throws 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     * @throws 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     * @throws IOException  If an I/O error occurs while either sending the
    310     *      command or receiving the server reply.
    311     ***/
    312    public int sendCommand(final String command, final 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     * @throws 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     * @throws IOException  If an I/O error occurs while either sending the
    337     *      command or receiving the server reply.
    338     ***/
    339    public int sendCommand(final int command, final 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     * @throws 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     * @throws IOException  If an I/O error occurs while either sending the
    361     *      command or receiving the server reply.
    362     ***/
    363    public int sendCommand(final 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     * @throws 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     * @throws IOException  If an I/O error occurs while either sending the
    386     *      command or receiving the server reply.
    387     ***/
    388    public int sendCommand(final 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     * @throws 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     * @throws 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 (final String line : replyLines)
    461        {
    462            buffer.append(line);
    463            buffer.append(SocketClient.NETASCII_EOL);
    464        }
    465
    466        newReplyString = false;
    467
    468        replyString = buffer.toString();
    469        return replyString;
    470    }
    471
    472
    473    /***
    474     * A convenience method to send the SMTP HELO command to the server,
    475     * receive the reply, and return the reply code.
    476     * <p>
    477     * @param hostname The hostname of the sender.
    478     * @return The reply code received from the server.
    479     * @throws SMTPConnectionClosedException
    480     *      If the SMTP server prematurely closes the connection as a result
    481     *      of the client being idle or some other reason causing the server
    482     *      to send SMTP reply code 421.  This exception may be caught either
    483     *      as an IOException or independently as itself.
    484     * @throws IOException  If an I/O error occurs while either sending the
    485     *      command or receiving the server reply.
    486     ***/
    487    public int helo(final String hostname) throws IOException
    488    {
    489        return sendCommand(SMTPCommand.HELO, hostname);
    490    }
    491
    492
    493    /***
    494     * A convenience method to send the SMTP MAIL command to the server,
    495     * receive the reply, and return the reply code.
    496     * <p>
    497     * @param reversePath The reverese path.
    498     * @return The reply code received from the server.
    499     * @throws SMTPConnectionClosedException
    500     *      If the SMTP server prematurely closes the connection as a result
    501     *      of the client being idle or some other reason causing the server
    502     *      to send SMTP reply code 421.  This exception may be caught either
    503     *      as an IOException or independently as itself.
    504     * @throws IOException  If an I/O error occurs while either sending the
    505     *      command or receiving the server reply.
    506     ***/
    507    public int mail(final String reversePath) throws IOException
    508    {
    509        return __sendCommand(SMTPCommand.MAIL, reversePath, false);
    510    }
    511
    512
    513    /***
    514     * A convenience method to send the SMTP RCPT command to the server,
    515     * receive the reply, and return the reply code.
    516     * <p>
    517     * @param forwardPath The forward path.
    518     * @return The reply code received from the server.
    519     * @throws SMTPConnectionClosedException
    520     *      If the SMTP server prematurely closes the connection as a result
    521     *      of the client being idle or some other reason causing the server
    522     *      to send SMTP reply code 421.  This exception may be caught either
    523     *      as an IOException or independently as itself.
    524     * @throws IOException  If an I/O error occurs while either sending the
    525     *      command or receiving the server reply.
    526     ***/
    527    public int rcpt(final String forwardPath) throws IOException
    528    {
    529        return __sendCommand(SMTPCommand.RCPT, forwardPath, false);
    530    }
    531
    532
    533    /***
    534     * A convenience method to send the SMTP DATA command to the server,
    535     * receive the reply, and return the reply code.
    536     * <p>
    537     * @return The reply code received from the server.
    538     * @throws SMTPConnectionClosedException
    539     *      If the SMTP server prematurely closes the connection as a result
    540     *      of the client being idle or some other reason causing the server
    541     *      to send SMTP reply code 421.  This exception may be caught either
    542     *      as an IOException or independently as itself.
    543     * @throws IOException  If an I/O error occurs while either sending the
    544     *      command or receiving the server reply.
    545     ***/
    546    public int data() throws IOException
    547    {
    548        return sendCommand(SMTPCommand.DATA);
    549    }
    550
    551
    552    /***
    553     * A convenience method to send the SMTP SEND command to the server,
    554     * receive the reply, and return the reply code.
    555     * <p>
    556     * @param reversePath The reverese path.
    557     * @return The reply code received from the server.
    558     * @throws SMTPConnectionClosedException
    559     *      If the SMTP server prematurely closes the connection as a result
    560     *      of the client being idle or some other reason causing the server
    561     *      to send SMTP reply code 421.  This exception may be caught either
    562     *      as an IOException or independently as itself.
    563     * @throws IOException  If an I/O error occurs while either sending the
    564     *      command or receiving the server reply.
    565     ***/
    566    public int send(final String reversePath) throws IOException
    567    {
    568        return sendCommand(SMTPCommand.SEND, reversePath);
    569    }
    570
    571
    572    /***
    573     * A convenience method to send the SMTP SOML command to the server,
    574     * receive the reply, and return the reply code.
    575     * <p>
    576     * @param reversePath The reverese path.
    577     * @return The reply code received from the server.
    578     * @throws SMTPConnectionClosedException
    579     *      If the SMTP server prematurely closes the connection as a result
    580     *      of the client being idle or some other reason causing the server
    581     *      to send SMTP reply code 421.  This exception may be caught either
    582     *      as an IOException or independently as itself.
    583     * @throws IOException  If an I/O error occurs while either sending the
    584     *      command or receiving the server reply.
    585     ***/
    586    public int soml(final String reversePath) throws IOException
    587    {
    588        return sendCommand(SMTPCommand.SOML, reversePath);
    589    }
    590
    591
    592    /***
    593     * A convenience method to send the SMTP SAML command to the server,
    594     * receive the reply, and return the reply code.
    595     * <p>
    596     * @param reversePath The reverese path.
    597     * @return The reply code received from the server.
    598     * @throws SMTPConnectionClosedException
    599     *      If the SMTP server prematurely closes the connection as a result
    600     *      of the client being idle or some other reason causing the server
    601     *      to send SMTP reply code 421.  This exception may be caught either
    602     *      as an IOException or independently as itself.
    603     * @throws IOException  If an I/O error occurs while either sending the
    604     *      command or receiving the server reply.
    605     ***/
    606    public int saml(final String reversePath) throws IOException
    607    {
    608        return sendCommand(SMTPCommand.SAML, reversePath);
    609    }
    610
    611
    612    /***
    613     * A convenience method to send the SMTP RSET command to the server,
    614     * receive the reply, and return the reply code.
    615     * <p>
    616     * @return The reply code received from the server.
    617     * @throws SMTPConnectionClosedException
    618     *      If the SMTP server prematurely closes the connection as a result
    619     *      of the client being idle or some other reason causing the server
    620     *      to send SMTP reply code 421.  This exception may be caught either
    621     *      as an IOException or independently as itself.
    622     * @throws IOException  If an I/O error occurs while either sending the
    623     *      command or receiving the server reply.
    624     ***/
    625    public int rset() throws IOException
    626    {
    627        return sendCommand(SMTPCommand.RSET);
    628    }
    629
    630
    631    /***
    632     * A convenience method to send the SMTP VRFY command to the server,
    633     * receive the reply, and return the reply code.
    634     * <p>
    635     * @param user The user address to verify.
    636     * @return The reply code received from the server.
    637     * @throws SMTPConnectionClosedException
    638     *      If the SMTP server prematurely closes the connection as a result
    639     *      of the client being idle or some other reason causing the server
    640     *      to send SMTP reply code 421.  This exception may be caught either
    641     *      as an IOException or independently as itself.
    642     * @throws IOException  If an I/O error occurs while either sending the
    643     *      command or receiving the server reply.
    644     ***/
    645    public int vrfy(final String user) throws IOException
    646    {
    647        return sendCommand(SMTPCommand.VRFY, user);
    648    }
    649
    650
    651    /***
    652     * A convenience method to send the SMTP VRFY command to the server,
    653     * receive the reply, and return the reply code.
    654     * <p>
    655     * @param name The name to expand.
    656     * @return The reply code received from the server.
    657     * @throws SMTPConnectionClosedException
    658     *      If the SMTP server prematurely closes the connection as a result
    659     *      of the client being idle or some other reason causing the server
    660     *      to send SMTP reply code 421.  This exception may be caught either
    661     *      as an IOException or independently as itself.
    662     * @throws IOException  If an I/O error occurs while either sending the
    663     *      command or receiving the server reply.
    664     ***/
    665    public int expn(final String name) throws IOException
    666    {
    667        return sendCommand(SMTPCommand.EXPN, name);
    668    }
    669
    670    /***
    671     * A convenience method to send the SMTP HELP command to the server,
    672     * receive the reply, and return the reply code.
    673     * <p>
    674     * @return The reply code received from the server.
    675     * @throws SMTPConnectionClosedException
    676     *      If the SMTP server prematurely closes the connection as a result
    677     *      of the client being idle or some other reason causing the server
    678     *      to send SMTP reply code 421.  This exception may be caught either
    679     *      as an IOException or independently as itself.
    680     * @throws IOException  If an I/O error occurs while either sending the
    681     *      command or receiving the server reply.
    682     ***/
    683    public int help() throws IOException
    684    {
    685        return sendCommand(SMTPCommand.HELP);
    686    }
    687
    688    /***
    689     * A convenience method to send the SMTP HELP command to the server,
    690     * receive the reply, and return the reply code.
    691     * <p>
    692     * @param command  The command name on which to request help.
    693     * @return The reply code received from the server.
    694     * @throws SMTPConnectionClosedException
    695     *      If the SMTP server prematurely closes the connection as a result
    696     *      of the client being idle or some other reason causing the server
    697     *      to send SMTP reply code 421.  This exception may be caught either
    698     *      as an IOException or independently as itself.
    699     * @throws IOException  If an I/O error occurs while either sending the
    700     *      command or receiving the server reply.
    701     ***/
    702    public int help(final String command) throws IOException
    703    {
    704        return sendCommand(SMTPCommand.HELP, command);
    705    }
    706
    707    /***
    708     * A convenience method to send the SMTP NOOP command to the server,
    709     * receive the reply, and return the reply code.
    710     * <p>
    711     * @return The reply code received from the server.
    712     * @throws SMTPConnectionClosedException
    713     *      If the SMTP server prematurely closes the connection as a result
    714     *      of the client being idle or some other reason causing the server
    715     *      to send SMTP reply code 421.  This exception may be caught either
    716     *      as an IOException or independently as itself.
    717     * @throws IOException  If an I/O error occurs while either sending the
    718     *      command or receiving the server reply.
    719     ***/
    720    public int noop() throws IOException
    721    {
    722        return sendCommand(SMTPCommand.NOOP);
    723    }
    724
    725
    726    /***
    727     * A convenience method to send the SMTP TURN command to the server,
    728     * receive the reply, and return the reply code.
    729     * <p>
    730     * @return The reply code received from the server.
    731     * @throws SMTPConnectionClosedException
    732     *      If the SMTP server prematurely closes the connection as a result
    733     *      of the client being idle or some other reason causing the server
    734     *      to send SMTP reply code 421.  This exception may be caught either
    735     *      as an IOException or independently as itself.
    736     * @throws IOException  If an I/O error occurs while either sending the
    737     *      command or receiving the server reply.
    738     ***/
    739    public int turn() throws IOException
    740    {
    741        return sendCommand(SMTPCommand.TURN);
    742    }
    743
    744
    745    /***
    746     * A convenience method to send the SMTP QUIT command to the server,
    747     * receive the reply, and return the reply code.
    748     * <p>
    749     * @return The reply code received from the server.
    750     * @throws SMTPConnectionClosedException
    751     *      If the SMTP server prematurely closes the connection as a result
    752     *      of the client being idle or some other reason causing the server
    753     *      to send SMTP reply code 421.  This exception may be caught either
    754     *      as an IOException or independently as itself.
    755     * @throws IOException  If an I/O error occurs while either sending the
    756     *      command or receiving the server reply.
    757     ***/
    758    public int quit() throws IOException
    759    {
    760        return sendCommand(SMTPCommand.QUIT);
    761    }
    762
    763    /**
    764     * Removes a ProtocolCommandListener.
    765     *
    766     * Delegates this incorrectly named method - removeProtocolCommandistener (note the missing "L")- to
    767     * the correct method {@link SocketClient#removeProtocolCommandListener}
    768     * @param listener The ProtocolCommandListener to remove
    769     */
    770    public void removeProtocolCommandistener(final org.apache.commons.net.ProtocolCommandListener listener){
    771        removeProtocolCommandListener(listener);
    772    }
    773
    774    /**
    775     * Provide command support to super-class
    776     */
    777    @Override
    778    protected ProtocolCommandSupport getCommandSupport() {
    779        return _commandSupport_;
    780    }
    781}
    782
    783/* Emacs configuration
    784 * Local variables:        **
    785 * mode:             java  **
    786 * c-basic-offset:   4     **
    787 * indent-tabs-mode: nil   **
    788 * End:                    **
    789 */