    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
    018    package org.apache.commons.net.smtp;
    019
    020    import java.io.BufferedReader;
    021    import java.io.BufferedWriter;
    022    import java.io.IOException;
    023    import java.io.InputStreamReader;
    024    import java.io.OutputStreamWriter;
    025    import java.util.ArrayList;
    026
    027    import org.apache.commons.net.MalformedServerReplyException;
    028    import org.apache.commons.net.ProtocolCommandSupport;
    029    import org.apache.commons.net.SocketClient;
    030    import 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     * <p>
    079     * <p>
    080     * @see SMTPClient
    081     * @see SMTPConnectionClosedException
    082     * @see org.apache.commons.net.MalformedServerReplyException
    083     ***/
    084
    085    public 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
    129         * @since 2.0
    130         */
    131        public SMTP(String encoding) {
    132            setDefaultPort(DEFAULT_PORT);
    133            _replyLines = new ArrayList<String>();
    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(String command, String args, boolean includeSpace)
    150        throws IOException
    151        {
    152            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            String message;
    166            _writer.write(message = __commandBuffer.toString());
    167            _writer.flush();
    168
    169            fireCommandSent(command, message);
    170
    171            __getReply();
    172            return _replyCode;
    173        }
    174
    175        /**
    176         *
    177         * @param command the command to send (as an int defined in {@link SMPTCommand})
    178         * @param args the command arguments, may be {@code null}
    179         * @param includeSpace if {@code true}, add a space between the command and its arguments
    180         * @return the reply code
    181         * @throws IOException
    182         */
    183        private int __sendCommand(int command, String args, boolean includeSpace)
    184        throws IOException
    185        {
    186            return __sendCommand(SMTPCommand.getCommand(command), args, includeSpace);
    187        }
    188
    189        private void __getReply() throws IOException
    190        {
    191            int length;
    192
    193            _newReplyString = true;
    194            _replyLines.clear();
    195
    196            String line = _reader.readLine();
    197
    198            if (line == null) {
    199                throw new SMTPConnectionClosedException(
    200                    "Connection closed without indication.");
    201            }
    202
    203            // In case we run into an anomaly we don't want fatal index exceptions
    204            // to be thrown.
    205            length = line.length();
    206            if (length < 3) {
    207                throw new MalformedServerReplyException(
    208                    "Truncated server reply: " + line);
    209            }
    210
    211            try
    212            {
    213                String code = line.substring(0, 3);
    214                _replyCode = Integer.parseInt(code);
    215            }
    216            catch (NumberFormatException e)
    217            {
    218                throw new MalformedServerReplyException(
    219                    "Could not parse response code.\nServer Reply: " + line);
    220            }
    221
    222            _replyLines.add(line);
    223
    224            // Get extra lines if message continues.
    225            if (length > 3 && line.charAt(3) == '-')
    226            {
    227                do
    228                {
    229                    line = _reader.readLine();
    230
    231                    if (line == null) {
    232                        throw new SMTPConnectionClosedException(
    233                            "Connection closed without indication.");
    234                    }
    235
    236                    _replyLines.add(line);
    237
    238                    // The length() check handles problems that could arise from readLine()
    239                    // returning too soon after encountering a naked CR or some other
    240                    // anomaly.
    241                }
    242                while (!(line.length() >= 4 && line.charAt(3) != '-' &&
    243                         Character.isDigit(line.charAt(0))));
    244                // This is too strong a condition because a non-conforming server
    245                // could screw things up like ftp.funet.fi does for FTP
    246                // line.startsWith(code)));
    247            }
    248
    249            fireReplyReceived(_replyCode, getReplyString());
    250
    251            if (_replyCode == SMTPReply.SERVICE_NOT_AVAILABLE) {
    252                throw new SMTPConnectionClosedException(
    253                    "SMTP response 421 received.  Server closed connection.");
    254            }
    255        }
    256
    257        /*** Initiates control connections and gets initial reply. ***/
    258        @Override
    259        protected void _connectAction_() throws IOException
    260        {
    261            super._connectAction_();
    262            _reader =
    263                new CRLFLineReader(new InputStreamReader(_input_,
    264                                                        encoding));
    265            _writer =
    266                new BufferedWriter(new OutputStreamWriter(_output_,
    267                                                          encoding));
    268            __getReply();
    269
    270        }
    271
    272
    273        /***
    274         * Closes the connection to the SMTP server and sets to null
    275         * some internal data so that the memory may be reclaimed by the
    276         * garbage collector.  The reply text and code information from the
    277         * last command is voided so that the memory it used may be reclaimed.
    278         * <p>
    279         * @exception IOException If an error occurs while disconnecting.
    280         ***/
    281        @Override
    282        public void disconnect() throws IOException
    283        {
    284            super.disconnect();
    285            _reader = null;
    286            _writer = null;
    287            _replyString = null;
    288            _replyLines.clear();
    289            _newReplyString = false;
    290        }
    291
    292
    293        /***
    294         * Sends an SMTP command to the server, waits for a reply and returns the
    295         * numerical response code.  After invocation, for more detailed
    296         * information, the actual reply text can be accessed by calling
    297         * {@link #getReplyString  getReplyString } or
    298         * {@link #getReplyStrings  getReplyStrings }.
    299         * <p>
    300         * @param command  The text representation of the  SMTP command to send.
    301         * @param args The arguments to the SMTP command.  If this parameter is
    302         *             set to null, then the command is sent with no argument.
    303         * @return The integer value of the SMTP reply code returned by the server
    304         *         in response to the command.
    305         * @exception SMTPConnectionClosedException
    306         *      If the SMTP server prematurely closes the connection as a result
    307         *      of the client being idle or some other reason causing the server
    308         *      to send SMTP reply code 421.  This exception may be caught either
    309         *      as an IOException or independently as itself.
    310         * @exception IOException  If an I/O error occurs while either sending the
    311         *      command or receiving the server reply.
    312         ***/
    313        public int sendCommand(String command, String args) throws IOException
    314        {
    315            return __sendCommand(command, args, true);
    316        }
    317
    318
    319        /***
    320         * Sends an SMTP command to the server, waits for a reply and returns the
    321         * numerical response code.  After invocation, for more detailed
    322         * information, the actual reply text can be accessed by calling
    323         * {@link #getReplyString  getReplyString } or
    324         * {@link #getReplyStrings  getReplyStrings }.
    325         * <p>
    326         * @param command  The SMTPCommand constant corresponding to the SMTP command
    327         *                 to send.
    328         * @param args The arguments to the SMTP command.  If this parameter is
    329         *             set to null, then the command is sent with no argument.
    330         * @return The integer value of the SMTP reply code returned by the server
    331         *         in response to the command.
    332         * @exception SMTPConnectionClosedException
    333         *      If the SMTP server prematurely closes the connection as a result
    334         *      of the client being idle or some other reason causing the server
    335         *      to send SMTP reply code 421.  This exception may be caught either
    336         *      as an IOException or independently as itself.
    337         * @exception IOException  If an I/O error occurs while either sending the
    338         *      command or receiving the server reply.
    339         ***/
    340        public int sendCommand(int command, String args) throws IOException
    341        {
    342            return sendCommand(SMTPCommand.getCommand(command), args);
    343        }
    344
    345
    346        /***
    347         * Sends an SMTP command with no arguments to the server, waits for a
    348         * reply and returns the numerical response code.  After invocation, for
    349         * more detailed information, the actual reply text can be accessed by
    350         * calling {@link #getReplyString  getReplyString } or
    351         * {@link #getReplyStrings  getReplyStrings }.
    352         * <p>
    353         * @param command  The text representation of the  SMTP command to send.
    354         * @return The integer value of the SMTP reply code returned by the server
    355         *         in response to the command.
    356         * @exception SMTPConnectionClosedException
    357         *      If the SMTP server prematurely closes the connection as a result
    358         *      of the client being idle or some other reason causing the server
    359         *      to send SMTP reply code 421.  This exception may be caught either
    360         *      as an IOException or independently as itself.
    361         * @exception IOException  If an I/O error occurs while either sending the
    362         *      command or receiving the server reply.
    363         ***/
    364        public int sendCommand(String command) throws IOException
    365        {
    366            return sendCommand(command, null);
    367        }
    368
    369
    370        /***
    371         * Sends an SMTP command with no arguments to the server, waits for a
    372         * reply and returns the numerical response code.  After invocation, for
    373         * more detailed information, the actual reply text can be accessed by
    374         * calling {@link #getReplyString  getReplyString } or
    375         * {@link #getReplyStrings  getReplyStrings }.
    376         * <p>
    377         * @param command  The SMTPCommand constant corresponding to the SMTP command
    378         *                 to send.
    379         * @return The integer value of the SMTP reply code returned by the server
    380         *         in response to the command.
    381         * @exception SMTPConnectionClosedException
    382         *      If the SMTP server prematurely closes the connection as a result
    383         *      of the client being idle or some other reason causing the server
    384         *      to send SMTP reply code 421.  This exception may be caught either
    385         *      as an IOException or independently as itself.
    386         * @exception IOException  If an I/O error occurs while either sending the
    387         *      command or receiving the server reply.
    388         ***/
    389        public int sendCommand(int command) throws IOException
    390        {
    391            return sendCommand(command, null);
    392        }
    393
    394
    395        /***
    396         * Returns the integer value of the reply code of the last SMTP reply.
    397         * You will usually only use this method after you connect to the
    398         * SMTP server to check that the connection was successful since
    399         * <code> connect </code> is of type void.
    400         * <p>
    401         * @return The integer value of the reply code of the last SMTP reply.
    402         ***/
    403        public int getReplyCode()
    404        {
    405            return _replyCode;
    406        }
    407
    408        /***
    409         * Fetches a reply from the SMTP server and returns the integer reply
    410         * code.  After calling this method, the actual reply text can be accessed
    411         * from either  calling {@link #getReplyString  getReplyString } or
    412         * {@link #getReplyStrings  getReplyStrings }.  Only use this
    413         * method if you are implementing your own SMTP client or if you need to
    414         * fetch a secondary response from the SMTP server.
    415         * <p>
    416         * @return The integer value of the reply code of the fetched SMTP reply.
    417         * @exception SMTPConnectionClosedException
    418         *      If the SMTP server prematurely closes the connection as a result
    419         *      of the client being idle or some other reason causing the server
    420         *      to send SMTP reply code 421.  This exception may be caught either
    421         *      as an IOException or independently as itself.
    422         * @exception IOException  If an I/O error occurs while receiving the
    423         *                         server reply.
    424         ***/
    425        public int getReply() throws IOException
    426        {
    427            __getReply();
    428            return _replyCode;
    429        }
    430
    431
    432        /***
    433         * Returns the lines of text from the last SMTP server response as an array
    434         * of strings, one entry per line.  The end of line markers of each are
    435         * stripped from each line.
    436         * <p>
    437         * @return The lines of text from the last SMTP response as an array.
    438         ***/
    439        public String[] getReplyStrings()
    440        {
    441            return _replyLines.toArray(new String[_replyLines.size()]);
    442        }
    443
    444        /***
    445         * Returns the entire text of the last SMTP server response exactly
    446         * as it was received, including all end of line markers in NETASCII
    447         * format.
    448         * <p>
    449         * @return The entire text from the last SMTP response as a String.
    450         ***/
    451        public String getReplyString()
    452        {
    453            StringBuilder buffer;
    454
    455            if (!_newReplyString) {
    456                return _replyString;
    457            }
    458
    459            buffer = new StringBuilder();
    460
    461            for (String line : _replyLines)
    462            {
    463                buffer.append(line);
    464                buffer.append(SocketClient.NETASCII_EOL);
    465            }
    466
    467            _newReplyString = false;
    468
    469            return (_replyString = buffer.toString());
    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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    485         *      command or receiving the server reply.
    486         ***/
    487        public int helo(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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    505         *      command or receiving the server reply.
    506         ***/
    507        public int mail(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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    525         *      command or receiving the server reply.
    526         ***/
    527        public int rcpt(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         * @exception 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         * @exception 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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    564         *      command or receiving the server reply.
    565         ***/
    566        public int send(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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    584         *      command or receiving the server reply.
    585         ***/
    586        public int soml(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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    604         *      command or receiving the server reply.
    605         ***/
    606        public int saml(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         * @exception 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         * @exception 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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    643         *      command or receiving the server reply.
    644         ***/
    645        public int vrfy(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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    663         *      command or receiving the server reply.
    664         ***/
    665        public int expn(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         * @exception 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         * @exception 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         * @exception 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         * @exception IOException  If an I/O error occurs while either sending the
    700         *      command or receiving the server reply.
    701         ***/
    702        public int help(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         * @exception 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         * @exception 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         * @exception 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         * @exception 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         * @exception 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         * @exception 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(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     */