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