All Downloads are FREE. Search and download functionalities are using the official Maven repository.

panda.net.smtp.SMTPClient Maven / Gradle / Ivy

Go to download

Panda Core is the core module of Panda Framework, it contains commonly used utility classes similar to apache-commons.

There is a newer version: 1.8.0
Show newest version
package panda.net.smtp;

import java.io.IOException;
import java.io.Writer;
import java.net.InetAddress;

import panda.io.stream.MultiWriter;
import panda.net.io.DotTerminatedMessageWriter;

/***
 * SMTPClient encapsulates all the functionality necessary to send files through an SMTP server.
 * This class takes care of all low level details of interacting with an SMTP server and provides a
 * convenient higher level interface. As with all classes derived from
 * {@link panda.net.SocketClient}, you must first connect to the server with
 * {@link panda.net.SocketClient#connect connect } before doing anything, and finally
 * {@link panda.net.SocketClient#disconnect disconnect } after you're completely finished
 * interacting with the server. Then you need to check the SMTP reply code to see if the connection
 * was successful. For example:
 * 
 * 
 *    try {
 *      int reply;
 *      client.connect("mail.foobar.com");
 *      System.out.print(client.getReplyString());
 * 
 *      // After connection attempt, you should check the reply code to verify
 *      // success.
 *      reply = client.getReplyCode();
 * 
 *      if(!SMTPReply.isPositiveCompletion(reply)) {
 *        client.disconnect();
 *        System.err.println("SMTP server refused connection.");
 *        System.exit(1);
 *      }
 * 
 *      // Do useful stuff here.
 *      ...
 *    } catch(IOException e) {
 *      if(client.isConnected()) {
 *        try {
 *          client.disconnect();
 *        } catch(IOException f) {
 *          // do nothing
 *        }
 *      }
 *      System.err.println("Could not connect to server.");
 *      e.printStackTrace();
 *      System.exit(1);
 *    }
 * 
*

* Immediately after connecting is the only real time you need to check the reply code (because * connect is of type void). The convention for all the SMTP command methods in SMTPClient is such * that they either return a boolean value or some other value. The boolean methods return true on a * successful completion reply from the SMTP server and false on a reply resulting in an error * condition or failure. The methods returning a value other than boolean return a value containing * the higher level data produced by the SMTP command, or null if a reply resulted in an error * condition or failure. If you want to access the exact SMTP reply code causing a success or * failure, you must call {@link panda.net.smtp.SMTP#getReplyCode getReplyCode } after a success or * failure. *

* You should keep in mind that the SMTP server may choose to prematurely close a connection for * various reasons. The SMTPClient class will detect a premature SMTP server connection closing when * it receives a {@link panda.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE * SMTPReply.SERVICE_NOT_AVAILABLE } response to a command. When that occurs, the method * encountering that reply will throw an {@link panda.net.smtp.SMTPConnectionClosedException} . * SMTPConectionClosedException is a subclass of IOException and * therefore need not be caught separately, but if you are going to catch it separately, its catch * block must appear before the more general IOException catch block. When you * encounter an {@link panda.net.smtp.SMTPConnectionClosedException} , you must disconnect the * connection with {@link #disconnect disconnect() } to properly clean up the system resources used * by SMTPClient. Before disconnecting, you may check the last reply code and text with * {@link panda.net.smtp.SMTP#getReplyCode getReplyCode }, * {@link panda.net.smtp.SMTP#getReplyString getReplyString }, and * {@link panda.net.smtp.SMTP#getReplyStrings getReplyStrings}. *

* Rather than list it separately for each method, we mention here that every method communicating * with the server and throwing an IOException can also throw a * {@link panda.net.MalformedServerReplyException} , which is a subclass of IOException. A * MalformedServerReplyException will be thrown when the reply received from the server deviates * enough from the protocol specification that it cannot be interpreted in a useful manner despite * attempts to be as lenient as possible. * * @see SMTP * @see SMTPHeader * @see RelayPath * @see SMTPConnectionClosedException * @see panda.net.MalformedServerReplyException ***/ public class SMTPClient extends SMTP { /** * Default SMTPClient constructor. Creates a new SMTPClient instance. */ public SMTPClient() { } /** * Overloaded constructor that takes an encoding specification * * @param encoding The encoding to use */ public SMTPClient(String encoding) { super(encoding); } /*** * At least one SMTPClient method ({@link #sendMessageData sendMessageData }) does not complete * the entire sequence of SMTP commands to complete a transaction. These types of commands * require some action by the programmer after the reception of a positive intermediate command. * After the programmer's code completes its actions, it must call this method to receive the * completion reply from the server and verify the success of the entire transaction. *

* For example, * *

	 * writer = client.sendMessageData();
	 * if (writer == null) // failure
	 * 	return false;
	 * header = new SimpleSMTPHeader("[email protected]", "[email protected]", "Re: Foo");
	 * writer.write(header.toString());
	 * writer.write("This is just a test");
	 * writer.close();
	 * if (!client.completePendingCommand()) // failure
	 * 	return false;
	 * 
*

* * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean completePendingCommand() throws IOException { return SMTPReply.isPositiveCompletion(getReply()); } /*** * Login to the SMTP server by sending the HELO command with the given hostname as an argument. * Before performing any mail commands, you must first login. *

* * @param hostname The hostname with which to greet the SMTP server. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean login(String hostname) throws IOException { return SMTPReply.isPositiveCompletion(helo(hostname)); } /*** * Login to the SMTP server by sending the HELO command with the client hostname as an argument. * Before performing any mail commands, you must first login. *

* * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean login() throws IOException { String name; InetAddress host; host = getLocalAddress(); name = host.getHostName(); if (name == null) { return false; } return SMTPReply.isPositiveCompletion(helo(name)); } /*** * Set the sender of a message using the SMTP MAIL command, specifying a reverse relay path. The * sender must be set first before any recipients may be specified, otherwise the mail server * will reject your commands. *

* * @param path The reverse relay path pointing back to the sender. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean setSender(RelayPath path) throws IOException { return SMTPReply.isPositiveCompletion(mail(path.toString())); } /*** * Set the sender of a message using the SMTP MAIL command, specifying the sender's email * address. The sender must be set first before any recipients may be specified, otherwise the * mail server will reject your commands. *

* * @param address The sender's email address. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean setSender(String address) throws IOException { return SMTPReply.isPositiveCompletion(mail("<" + address + ">")); } /*** * Add a recipient for a message using the SMTP RCPT command, specifying a forward relay path. * The sender must be set first before any recipients may be specified, otherwise the mail * server will reject your commands. *

* * @param path The forward relay path pointing to the recipient. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean addRecipient(RelayPath path) throws IOException { return SMTPReply.isPositiveCompletion(rcpt(path.toString())); } /*** * Add a recipient for a message using the SMTP RCPT command, the recipient's email address. The * sender must be set first before any recipients may be specified, otherwise the mail server * will reject your commands. *

* * @param address The recipient's email address. * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean addRecipient(String address) throws IOException { return SMTPReply.isPositiveCompletion(rcpt("<" + address + ">")); } /*** * Send the SMTP DATA command in preparation to send an email message. This method returns a * DotTerminatedMessageWriter instance to which the message can be written. Null is returned if * the DATA command fails. *

* You must not issue any commands to the SMTP server (i.e., call any (other methods) until you * finish writing to the returned Writer instance and close it. The SMTP protocol uses the same * stream for issuing commands as it does for returning results. Therefore the returned Writer * actually writes directly to the SMTP connection. After you close the writer, you can execute * new commands. If you do not follow these requirements your program will not work properly. *

* You can use the provided {@link panda.net.smtp.SMTPHeader} class to construct a bare * minimum header. To construct more complicated headers you should refer to RFC 5322. When the * Java Mail API is finalized, you will be able to use it to compose fully compliant Internet * text messages. The DotTerminatedMessageWriter takes care of doubling line-leading dots and * ending the message with a single dot upon closing, so all you have to worry about is writing * the header and the message. *

* Upon closing the returned Writer, you need to call {@link #completePendingCommand * completePendingCommand() } to finalize the transaction and verify its success or failure from * the server reply. *

* * @return A DotTerminatedMessageWriter to which the message (including header) can be written. * Returns null if the command fails. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. * @see #sendShortMessageData(String) ***/ public Writer sendMessageData() throws IOException { return sendMessageData(null); } public Writer sendMessageData(Writer dbg) throws IOException { if (!SMTPReply.isPositiveIntermediate(data())) { return null; } if (dbg != null) { return new DotTerminatedMessageWriter(new MultiWriter(dbg, _writer)); } return new DotTerminatedMessageWriter(_writer); } /*** * A convenience method for sending short messages. This method fetches the Writer returned by * {@link #sendMessageData sendMessageData() } and writes the specified String to it. After * writing the message, this method calls {@link #completePendingCommand * completePendingCommand() } to finalize the transaction and returns its success or failure. *

* * @param message The short email message to send. This must include the headers and the body, * but not the trailing "." * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean sendShortMessageData(String message) throws IOException { Writer writer; writer = sendMessageData(); if (writer == null) { return false; } writer.write(message); writer.close(); return completePendingCommand(); } /*** * A convenience method for a sending short email without having to explicitly set the sender * and recipient(s). This method sets the sender and recipient using {@link #setSender setSender * } and {@link #addRecipient addRecipient }, and then sends the message using * {@link #sendShortMessageData sendShortMessageData }. *

* * @param sender The email address of the sender. * @param recipient The email address of the recipient. * @param message The short email message to send. This must include the headers and the body, * but not the trailing "." * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean sendSimpleMessage(String sender, String recipient, String message) throws IOException { if (!setSender(sender)) { return false; } if (!addRecipient(recipient)) { return false; } return sendShortMessageData(message); } /*** * A convenience method for a sending short email without having to explicitly set the sender * and recipient(s). This method sets the sender and recipients using {@link #setSender(String) * setSender} and {@link #addRecipient(String) addRecipient}, and then sends the message using * {@link #sendShortMessageData(String) sendShortMessageData}. *

* Note that the method ignores failures when calling {@link #addRecipient(String) addRecipient} * so long as at least one call succeeds. If no recipients can be successfully added then the * method will fail (and does not attempt to send the message) *

* * @param sender The email address of the sender. * @param recipients An array of recipient email addresses. * @param message The short email message to send. This must include the headers and the body, * but not the trailing "." * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean sendSimpleMessage(String sender, String[] recipients, String message) throws IOException { boolean oneSuccess = false; int count; if (!setSender(sender)) { return false; } for (count = 0; count < recipients.length; count++) { if (addRecipient(recipients[count])) { oneSuccess = true; } } if (!oneSuccess) { return false; } return sendShortMessageData(message); } /*** * Logout of the SMTP server by sending the QUIT command. *

* * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean logout() throws IOException { return SMTPReply.isPositiveCompletion(quit()); } /*** * Aborts the current mail transaction, resetting all server stored sender, recipient, and mail * data, cleaing all buffers and tables. *

* * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean reset() throws IOException { return SMTPReply.isPositiveCompletion(rset()); } /*** * Verify that a username or email address is valid, i.e., that mail can be delivered to that * mailbox on the server. *

* * @param username The username or email address to validate. * @return True if the username is valid, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean verify(String username) throws IOException { int result; result = vrfy(username); return (result == SMTPReply.ACTION_OK || result == SMTPReply.USER_NOT_LOCAL_WILL_FORWARD); } /*** * Fetches the system help information from the server and returns the full string. *

* * @return The system help string obtained from the server. null if the information could not be * obtained. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public String listHelp() throws IOException { if (SMTPReply.isPositiveCompletion(help())) { return getReplyString(); } return null; } /*** * Fetches the help information for a given command from the server and returns the full string. *

* * @param command The command on which to ask for help. * @return The command help string obtained from the server. null if the information could not * be obtained. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public String listHelp(String command) throws IOException { if (SMTPReply.isPositiveCompletion(help(command))) { return getReplyString(); } return null; } /*** * Sends a NOOP command to the SMTP server. This is useful for preventing server timeouts. *

* * @return True if successfully completed, false if not. * @exception SMTPConnectionClosedException If the SMTP server prematurely closes the connection * as a result of the client being idle or some other reason causing the server * to send SMTP reply code 421. This exception may be caught either as an * IOException or independently as itself. * @exception IOException If an I/O error occurs while either sending a command to the server or * receiving a reply from the server. ***/ public boolean sendNoOp() throws IOException { return SMTPReply.isPositiveCompletion(noop()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy