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