View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.net.smtp;
19  
20  import java.io.BufferedReader;
21  import java.io.BufferedWriter;
22  import java.io.IOException;
23  import java.io.InputStreamReader;
24  import java.io.OutputStreamWriter;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  
28  import org.apache.commons.net.MalformedServerReplyException;
29  import org.apache.commons.net.ProtocolCommandListener;
30  import org.apache.commons.net.ProtocolCommandSupport;
31  import org.apache.commons.net.SocketClient;
32  
33  /***
34   * SMTP provides the basic the functionality necessary to implement your
35   * own SMTP client.  To derive the full benefits of the SMTP class requires
36   * some knowledge of the FTP protocol defined in RFC 821.  However, there
37   * is no reason why you should have to use the SMTP class.  The
38   * {@link org.apache.commons.net.smtp.SMTPClient} class,
39   * derived from SMTP,
40   * implements all the functionality required of an SMTP client.  The
41   * SMTP class is made public to provide access to various SMTP constants
42   * and to make it easier for adventurous programmers (or those with
43   * special needs) to interact with the SMTP protocol and implement their
44   * own clients.  A set of methods with names corresponding to the SMTP
45   * command names are provided to facilitate this interaction.
46   * <p>
47   * You should keep in mind that the SMTP server may choose to prematurely
48   * close a connection for various reasons.  The SMTP class will detect a
49   * premature SMTP server connection closing when it receives a
50   * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
51   *  response to a command.
52   * When that occurs, the SMTP class method encountering that reply will throw
53   * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
54   * .
55   * <code>SMTPConectionClosedException</code>
56   * is a subclass of <code> IOException </code> and therefore need not be
57   * caught separately, but if you are going to catch it separately, its
58   * catch block must appear before the more general <code> IOException </code>
59   * catch block.  When you encounter an
60   * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
61   * , you must disconnect the connection with
62   * {@link org.apache.commons.net.SocketClient#disconnect  disconnect() }
63   * to properly clean up the system resources used by SMTP.  Before
64   * disconnecting, you may check the
65   * last reply code and text with
66   * {@link #getReplyCode  getReplyCode },
67   * {@link #getReplyString  getReplyString },
68   * and {@link #getReplyStrings  getReplyStrings}.
69   * <p>
70   * Rather than list it separately for each method, we mention here that
71   * every method communicating with the server and throwing an IOException
72   * can also throw a
73   * {@link org.apache.commons.net.MalformedServerReplyException}
74   * , which is a subclass
75   * of IOException.  A MalformedServerReplyException will be thrown when
76   * the reply received from the server deviates enough from the protocol
77   * specification that it cannot be interpreted in a useful manner despite
78   * attempts to be as lenient as possible.
79   * <p>
80   * <p>
81   * @author Daniel F. Savarese
82   * @see SMTPClient
83   * @see SMTPConnectionClosedException
84   * @see org.apache.commons.net.MalformedServerReplyException
85   ***/
86  
87  public class SMTP extends SocketClient
88  {
89      /*** The default SMTP port (25). ***/
90      public static final int DEFAULT_PORT = 25;
91  
92      // We have to ensure that the protocol communication is in ASCII
93      // but we use ISO-8859-1 just in case 8-bit characters cross
94      // the wire.
95      private static final String __DEFAULT_ENCODING = "ISO-8859-1";
96      
97      /** The encoding to use (user-settable) */
98      private String encoding = __DEFAULT_ENCODING;
99  
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  */