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