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