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