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