View Javadoc
1 package org.apache.commons.net.smtp; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache Commons" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>;. 55 */ 56 57 import java.io.IOException; 58 import java.io.Writer; 59 import java.net.InetAddress; 60 import org.apache.commons.net.io.DotTerminatedMessageWriter; 61 62 /**** 63 * SMTPClient encapsulates all the functionality necessary to send files 64 * through an SMTP server. This class takes care of all 65 * low level details of interacting with an SMTP server and provides 66 * a convenient higher level interface. As with all classes derived 67 * from <a href="org.apache.commons.net.SocketClient.html"> SocketClient </a>, 68 * you must first connect to the server with 69 * <a href="org.apache.commons.net.SocketClient.html#connect"> connect </a> 70 * before doing anything, and finally 71 * <a href="org.apache.commons.net.SocketClient.html#disconnect"> disconnect </a> 72 * after you're completely finished interacting with the server. 73 * Then you need to check the SMTP reply code to see if the connection 74 * was successful. For example: 75 * <pre> 76 * try { 77 * int reply; 78 * client.connect("mail.foobar.com"); 79 * System.out.print(client.getReplyString()); 80 * 81 * // After connection attempt, you should check the reply code to verify 82 * // success. 83 * reply = client.getReplyCode(); 84 * 85 * if(!SMTPReply.isPositiveCompletion(reply)) { 86 * client.disconnect(); 87 * System.err.println("SMTP server refused connection."); 88 * System.exit(1); 89 * } 90 * 91 * // Do useful stuff here. 92 * ... 93 * } catch(IOException e) { 94 * if(client.isConnected()) { 95 * try { 96 * client.disconnect(); 97 * } catch(IOException f) { 98 * // do nothing 99 * } 100 * } 101 * System.err.println("Could not connect to server."); 102 * e.printStackTrace(); 103 * System.exit(1); 104 * } 105 * </pre> 106 * <p> 107 * Immediately after connecting is the only real time you need to check the 108 * reply code (because connect is of type void). The convention for all the 109 * SMTP command methods in SMTPClient is such that they either return a 110 * boolean value or some other value. 111 * The boolean methods return true on a successful completion reply from 112 * the SMTP server and false on a reply resulting in an error condition or 113 * failure. The methods returning a value other than boolean return a value 114 * containing the higher level data produced by the SMTP command, or null if a 115 * reply resulted in an error condition or failure. If you want to access 116 * the exact SMTP reply code causing a success or failure, you must call 117 * <a href="org.apache.commons.net.smtp.SMTP.html#getReplyCode"> getReplyCode </a> after 118 * a success or failure. 119 * <p> 120 * You should keep in mind that the SMTP server may choose to prematurely 121 * close a connection for various reasons. The SMTPClient class will detect a 122 * premature SMTP server connection closing when it receives a 123 * <a href="org.apache.commons.net.smtp.SMTPReply.html#SERVICE_NOT_AVAILABLE"> 124 * SMTPReply.SERVICE_NOT_AVAILABLE </a> response to a command. 125 * When that occurs, the method encountering that reply will throw 126 * an <a href="org.apache.commons.net.smtp.SMTPConnectionClosedException.html"> 127 * SMTPConnectionClosedException </a>. 128 * <code>SMTPConectionClosedException</code> 129 * is a subclass of <code> IOException </code> and therefore need not be 130 * caught separately, but if you are going to catch it separately, its 131 * catch block must appear before the more general <code> IOException </code> 132 * catch block. When you encounter an 133 * <a href="org.apache.commons.net.smtp.SMTPConnectionClosedException.html"> 134 * SMTPConnectionClosedException </a>, you must disconnect the connection with 135 * <a href="#disconnect"> disconnect() </a> to properly clean up the 136 * system resources used by SMTPClient. Before disconnecting, you may check 137 * the last reply code and text with 138 * <a href="org.apache.commons.net.smtp.SMTP.html#getReplyCode"> getReplyCode </a>, 139 * <a href="org.apache.commons.net.smtp.SMTP.html#getReplyString"> getReplyString </a>, 140 * and 141 * <a href="org.apache.commons.net.smtp.SMTP.html#getReplyStrings">getReplyStrings</a>. 142 * <p> 143 * Rather than list it separately for each method, we mention here that 144 * every method communicating with the server and throwing an IOException 145 * can also throw a 146 * <a href="org.apache.commons.net.MalformedServerReplyException.html"> 147 * MalformedServerReplyException </a>, which is a subclass 148 * of IOException. A MalformedServerReplyException will be thrown when 149 * the reply received from the server deviates enough from the protocol 150 * specification that it cannot be interpreted in a useful manner despite 151 * attempts to be as lenient as possible. 152 * <p> 153 * <p> 154 * @author Daniel F. Savarese 155 * @see SMTP 156 * @see SimpleSMTPHeader 157 * @see RelayPath 158 * @see SMTPConnectionClosedException 159 * @see org.apache.commons.net.MalformedServerReplyException 160 ***/ 161 162 public class SMTPClient extends SMTP 163 { 164 165 /* 166 * Default SMTPClient constructor. Creates a new SMTPClient instance. 167 */ 168 //public SMTPClient() { } 169 170 171 /**** 172 * At least one SMTPClient method (<a href="#sendMessage"> sendMessage </a>) 173 * does not complete the entire sequence of SMTP commands to complete a 174 * transaction. These types of commands require some action by the 175 * programmer after the reception of a positive intermediate command. 176 * After the programmer's code completes its actions, it must call this 177 * method to receive the completion reply from the server and verify the 178 * success of the entire transaction. 179 * <p> 180 * For example, 181 * <pre> 182 * writer = client.sendMessage(); 183 * if(writer == null) // failure 184 * return false; 185 * header = 186 * new SimpleSMTPHeader("foobar@foo.com", "foo@foobar.com", "Re: Foo"); 187 * writer.write(header.toString()); 188 * writer.write("This is just a test"); 189 * writer.close(); 190 * if(!client.completePendingCommand()) // failure 191 * return false; 192 * </pre> 193 * <p> 194 * @return True if successfully completed, false if not. 195 * @exception SMTPConnectionClosedException 196 * If the SMTP server prematurely closes the connection as a result 197 * of the client being idle or some other reason causing the server 198 * to send SMTP reply code 421. This exception may be caught either 199 * as an IOException or independently as itself. 200 * @exception IOException If an I/O error occurs while either sending a 201 * command to the server or receiving a reply from the server. 202 ***/ 203 public boolean completePendingCommand() throws IOException 204 { 205 return SMTPReply.isPositiveCompletion(getReply()); 206 } 207 208 209 /**** 210 * Login to the SMTP server by sending the HELO command with the 211 * given hostname as an argument. Before performing any mail commands, 212 * you must first login. 213 * <p> 214 * @param hostname The hostname with which to greet the SMTP server. 215 * @return True if successfully completed, false if not. 216 * @exception SMTPConnectionClosedException 217 * If the SMTP server prematurely closes the connection as a result 218 * of the client being idle or some other reason causing the server 219 * to send SMTP reply code 421. This exception may be caught either 220 * as an IOException or independently as itself. 221 * @exception IOException If an I/O error occurs while either sending a 222 * command to the server or receiving a reply from the server. 223 ***/ 224 public boolean login(String hostname) throws IOException 225 { 226 return SMTPReply.isPositiveCompletion(helo(hostname)); 227 } 228 229 230 /**** 231 * Login to the SMTP server by sending the HELO command with the 232 * client hostname as an argument. Before performing any mail commands, 233 * you must first login. 234 * <p> 235 * @return True if successfully completed, false if not. 236 * @exception SMTPConnectionClosedException 237 * If the SMTP server prematurely closes the connection as a result 238 * of the client being idle or some other reason causing the server 239 * to send SMTP reply code 421. This exception may be caught either 240 * as an IOException or independently as itself. 241 * @exception IOException If an I/O error occurs while either sending a 242 * command to the server or receiving a reply from the server. 243 ***/ 244 public boolean login() throws IOException 245 { 246 String name; 247 InetAddress host; 248 249 host = getLocalAddress(); 250 name = host.getHostName(); 251 252 if (name == null) 253 return false; 254 255 return SMTPReply.isPositiveCompletion(helo(name)); 256 } 257 258 259 /**** 260 * Set the sender of a message using the SMTP MAIL command, specifying 261 * a reverse relay path. The sender must be set first before any 262 * recipients may be specified, otherwise the mail server will reject 263 * your commands. 264 * <p> 265 * @param path The reverse relay path pointing back to the sender. 266 * @return True if successfully completed, false if not. 267 * @exception SMTPConnectionClosedException 268 * If the SMTP server prematurely closes the connection as a result 269 * of the client being idle or some other reason causing the server 270 * to send SMTP reply code 421. This exception may be caught either 271 * as an IOException or independently as itself. 272 * @exception IOException If an I/O error occurs while either sending a 273 * command to the server or receiving a reply from the server. 274 ***/ 275 public boolean setSender(RelayPath path) throws IOException 276 { 277 return SMTPReply.isPositiveCompletion(mail(path.toString())); 278 } 279 280 281 /**** 282 * Set the sender of a message using the SMTP MAIL command, specifying 283 * the sender's email address. The sender must be set first before any 284 * recipients may be specified, otherwise the mail server will reject 285 * your commands. 286 * <p> 287 * @param address The sender's email address. 288 * @return True if successfully completed, false if not. 289 * @exception SMTPConnectionClosedException 290 * If the SMTP server prematurely closes the connection as a result 291 * of the client being idle or some other reason causing the server 292 * to send SMTP reply code 421. This exception may be caught either 293 * as an IOException or independently as itself. 294 * @exception IOException If an I/O error occurs while either sending a 295 * command to the server or receiving a reply from the server. 296 ***/ 297 public boolean setSender(String address) throws IOException 298 { 299 return SMTPReply.isPositiveCompletion(mail("<" + address + ">")); 300 } 301 302 303 /**** 304 * Add a recipient for a message using the SMTP RCPT command, specifying 305 * a forward relay path. The sender must be set first before any 306 * recipients may be specified, otherwise the mail server will reject 307 * your commands. 308 * <p> 309 * @param path The forward relay path pointing to the recipient. 310 * @return True if successfully completed, false if not. 311 * @exception 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 * @exception IOException If an I/O error occurs while either sending a 317 * command to the server or receiving a reply from the server. 318 ***/ 319 public boolean addRecipient(RelayPath path) throws IOException 320 { 321 return SMTPReply.isPositiveCompletion(rcpt(path.toString())); 322 } 323 324 325 /**** 326 * Add a recipient for a message using the SMTP RCPT command, the 327 * recipient's email address. The sender must be set first before any 328 * recipients may be specified, otherwise the mail server will reject 329 * your commands. 330 * <p> 331 * @param address The recipient's email address. 332 * @return True if successfully completed, false if not. 333 * @exception SMTPConnectionClosedException 334 * If the SMTP server prematurely closes the connection as a result 335 * of the client being idle or some other reason causing the server 336 * to send SMTP reply code 421. This exception may be caught either 337 * as an IOException or independently as itself. 338 * @exception IOException If an I/O error occurs while either sending a 339 * command to the server or receiving a reply from the server. 340 ***/ 341 public boolean addRecipient(String address) throws IOException 342 { 343 return SMTPReply.isPositiveCompletion(rcpt("<" + address + ">")); 344 } 345 346 347 348 /**** 349 * Send the SMTP DATA command in preparation to send an email message. 350 * This method returns a DotTerminatedMessageWriter instance to which 351 * the message can be written. Null is returned if the DATA command 352 * fails. 353 * <p> 354 * You must not issue any commands to the SMTP server (i.e., call any 355 * (other methods) until you finish writing to the returned Writer 356 * instance and close it. The SMTP protocol uses the same stream for 357 * issuing commands as it does for returning results. Therefore the 358 * returned Writer actually writes directly to the SMTP connection. 359 * After you close the writer, you can execute new commands. If you 360 * do not follow these requirements your program will not work properly. 361 * <p> 362 * You can use the provided 363 * <a href="org.apache.commons.net.smtp.SimpleSMTPHeader.html"> SimpleSMTPHeader </a> 364 * class to construct a bare minimum header. 365 * To construct more complicated headers you should 366 * refer to RFC 822. When the Java Mail API is finalized, you will be 367 * able to use it to compose fully compliant Internet text messages. 368 * The DotTerminatedMessageWriter takes care of doubling line-leading 369 * dots and ending the message with a single dot upon closing, so all 370 * you have to worry about is writing the header and the message. 371 * <p> 372 * Upon closing the returned Writer, you need to call 373 * <a href="#completePendingCommand"> completePendingCommand() </a> 374 * to finalize the transaction and verify its success or failure from 375 * the server reply. 376 * <p> 377 * @return A DotTerminatedMessageWriter to which the message (including 378 * header) can be written. Returns null if the command fails. 379 * @exception SMTPConnectionClosedException 380 * If the SMTP server prematurely closes the connection as a result 381 * of the client being idle or some other reason causing the server 382 * to send SMTP reply code 421. This exception may be caught either 383 * as an IOException or independently as itself. 384 * @exception IOException If an I/O error occurs while either sending a 385 * command to the server or receiving a reply from the server. 386 ***/ 387 public Writer sendMessageData() throws IOException 388 { 389 if (!SMTPReply.isPositiveIntermediate(data())) 390 return null; 391 392 return new DotTerminatedMessageWriter(_writer); 393 } 394 395 396 /**** 397 * A convenience method for sending short messages. This method fetches 398 * the Writer returned by <a href="#sendMessageData"> sendMessageData() </a> 399 * and writes the specified String to it. After writing the message, 400 * this method calls <a href="#completePendingCommand"> 401 * completePendingCommand() </a> to finalize the transaction and returns 402 * its success or failure. 403 * <p> 404 * @param message The short email message to send. 405 * @return True if successfully completed, false if not. 406 * @exception SMTPConnectionClosedException 407 * If the SMTP server prematurely closes the connection as a result 408 * of the client being idle or some other reason causing the server 409 * to send SMTP reply code 421. This exception may be caught either 410 * as an IOException or independently as itself. 411 * @exception IOException If an I/O error occurs while either sending a 412 * command to the server or receiving a reply from the server. 413 ***/ 414 public boolean sendShortMessageData(String message) throws IOException 415 { 416 Writer writer; 417 418 writer = sendMessageData(); 419 420 if (writer == null) 421 return false; 422 423 writer.write(message); 424 writer.close(); 425 426 return completePendingCommand(); 427 } 428 429 430 /**** 431 * A convenience method for a sending short email without having to 432 * explicitly set the sender and recipient(s). This method 433 * sets the sender and recipient using 434 * <a href="#setSender"> setSender </a> and 435 * <a href="#addRecipient"> addRecipient </a>, and then sends the 436 * message using <a href="#sendShortMessageData"> sendShortMessageData </a>. 437 * <p> 438 * @param sender The email address of the sender. 439 * @param recipient The email address of the recipient. 440 * @param message The short email message to send. 441 * @return True if successfully completed, false if not. 442 * @exception SMTPConnectionClosedException 443 * If the SMTP server prematurely closes the connection as a result 444 * of the client being idle or some other reason causing the server 445 * to send SMTP reply code 421. This exception may be caught either 446 * as an IOException or independently as itself. 447 * @exception IOException If an I/O error occurs while either sending a 448 * command to the server or receiving a reply from the server. 449 ***/ 450 public boolean sendSimpleMessage(String sender, String recipient, 451 String message) 452 throws IOException 453 { 454 if (!setSender(sender)) 455 return false; 456 457 if (!addRecipient(recipient)) 458 return false; 459 460 return sendShortMessageData(message); 461 } 462 463 464 465 /**** 466 * A convenience method for a sending short email without having to 467 * explicitly set the sender and recipient(s). This method 468 * sets the sender and recipients using 469 * <a href="#setSender"> setSender </a> and 470 * <a href="#addRecipient"> addRecipient </a>, and then sends the 471 * message using <a href="#sendShortMessageData"> sendShortMessageData </a>. 472 * <p> 473 * @param sender The email address of the sender. 474 * @param recipients An array of recipient email addresses. 475 * @param message The short email message to send. 476 * @return True if successfully completed, false if not. 477 * @exception SMTPConnectionClosedException 478 * If the SMTP server prematurely closes the connection as a result 479 * of the client being idle or some other reason causing the server 480 * to send SMTP reply code 421. This exception may be caught either 481 * as an IOException or independently as itself. 482 * @exception IOException If an I/O error occurs while either sending a 483 * command to the server or receiving a reply from the server. 484 ***/ 485 public boolean sendSimpleMessage(String sender, String[] recipients, 486 String message) 487 throws IOException 488 { 489 boolean oneSuccess = false; 490 int count; 491 492 if (!setSender(sender)) 493 return false; 494 495 for (count = 0; count < recipients.length; count++) 496 { 497 if (addRecipient(recipients[count])) 498 oneSuccess = true; 499 } 500 501 if (!oneSuccess) 502 return false; 503 504 return sendShortMessageData(message); 505 } 506 507 508 /**** 509 * Logout of the SMTP server by sending the QUIT command. 510 * <p> 511 * @return True if successfully completed, false if not. 512 * @exception SMTPConnectionClosedException 513 * If the SMTP server prematurely closes the connection as a result 514 * of the client being idle or some other reason causing the server 515 * to send SMTP reply code 421. This exception may be caught either 516 * as an IOException or independently as itself. 517 * @exception IOException If an I/O error occurs while either sending a 518 * command to the server or receiving a reply from the server. 519 ***/ 520 public boolean logout() throws IOException 521 { 522 return SMTPReply.isPositiveCompletion(quit()); 523 } 524 525 526 527 /**** 528 * Aborts the current mail transaction, resetting all server stored 529 * sender, recipient, and mail data, cleaing all buffers and tables. 530 * <p> 531 * @return True if successfully completed, false if not. 532 * @exception 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 * @exception IOException If an I/O error occurs while either sending a 538 * command to the server or receiving a reply from the server. 539 ***/ 540 public boolean reset() throws IOException 541 { 542 return SMTPReply.isPositiveCompletion(rset()); 543 } 544 545 546 /**** 547 * Verify that a username or email address is valid, i.e., that mail 548 * can be delivered to that mailbox on the server. 549 * <p> 550 * @param username The username or email address to validate. 551 * @return True if the username is valid, false if not. 552 * @exception 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 * @exception IOException If an I/O error occurs while either sending a 558 * command to the server or receiving a reply from the server. 559 ***/ 560 public boolean verify(String username) throws IOException 561 { 562 int result; 563 564 result = vrfy(username); 565 566 return (result == SMTPReply.ACTION_OK || 567 result == SMTPReply.USER_NOT_LOCAL_WILL_FORWARD); 568 } 569 570 571 /**** 572 * Fetches the system help information from the server and returns the 573 * full string. 574 * <p> 575 * @return The system help string obtained from the server. null if the 576 * information could not be obtained. 577 * @exception SMTPConnectionClosedException 578 * If the SMTP server prematurely closes the connection as a result 579 * of the client being idle or some other reason causing the server 580 * to send SMTP reply code 421. This exception may be caught either 581 * as an IOException or independently as itself. 582 * @exception IOException If an I/O error occurs while either sending a 583 * command to the server or receiving a reply from the server. 584 ***/ 585 public String listHelp() throws IOException 586 { 587 if (SMTPReply.isPositiveCompletion(help())) 588 return getReplyString(); 589 return null; 590 } 591 592 593 /**** 594 * Fetches the help information for a given command from the server and 595 * returns the full string. 596 * <p> 597 * @param The command on which to ask for help. 598 * @return The command help string obtained from the server. null if the 599 * information could not be obtained. 600 * @exception SMTPConnectionClosedException 601 * If the SMTP server prematurely closes the connection as a result 602 * of the client being idle or some other reason causing the server 603 * to send SMTP reply code 421. This exception may be caught either 604 * as an IOException or independently as itself. 605 * @exception IOException If an I/O error occurs while either sending a 606 * command to the server or receiving a reply from the server. 607 ***/ 608 public String listHelp(String command) throws IOException 609 { 610 if (SMTPReply.isPositiveCompletion(help(command))) 611 return getReplyString(); 612 return null; 613 } 614 615 616 /**** 617 * Sends a NOOP command to the SMTP server. This is useful for preventing 618 * server timeouts. 619 * <p> 620 * @return True if successfully completed, false if not. 621 * @exception SMTPConnectionClosedException 622 * If the SMTP server prematurely closes the connection as a result 623 * of the client being idle or some other reason causing the server 624 * to send SMTP reply code 421. This exception may be caught either 625 * as an IOException or independently as itself. 626 * @exception IOException If an I/O error occurs while either sending a 627 * command to the server or receiving a reply from the server. 628 ***/ 629 public boolean sendNoOp() throws IOException 630 { 631 return SMTPReply.isPositiveCompletion(noop()); 632 } 633 634 }

This page was automatically generated by Maven