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