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