Simple SMTP Client

 < Day Day Up > 



Now, let’s look at a simple SMTP client written in Java. The SMTP client is implemented as a class that provides a set of methods to send an e-mail to a specified recipient (Listing 17.8). Two methods exist for the Java SMTP client, smtpc (the class constructor) and send (send the e-mail created by the constructor). One other private method exists internally, which is covered in the smtpc class discussion.

We’ll discuss the Java SMTP client class in two parts (Listing 17.8). The first part discusses the test class (smtptest) that we use to test the smtpc class (lines 4–25), and the second part discusses the actual smtpc class (lines 27–193).

The first class, smtptest (lines 4–25) is used to create a new smtpc object and then send a test e-mail using it. Class smtptest is a Java application and provides a main method (at line 9). Class smtptest performs only two functions; the first is the creation of a new smtpc object using the smtpc constructor (lines 12–18) and the second is the calling of the send method of the smtpc class (line 21). The smtpc constructor is called with the necessary parameters for the e-mail to send. This includes the subject, sender e-mail address, recipient e-mail address, content type, and, finally, the contents of the e-mail. Note that in the example shown, a text e-mail is sent (as both indicated by the content type “text/html” and the obvious HTML tags within the e-mail contents). Invoking the send method then initiates communication with the SMTP server and the configured e-mail is sent.

Now, let’s discuss the smtpc class within Listing 17.8 (lines 27–193). We discuss the support elements of the class first, and then discuss the primary methods that provide the SMTP functionality. After declaring the class at line 27, a set of private variables is created (lines 30–34). These variables are used to hold the e-mail data that’s passed in to the constructor (lines 44–54). Three other objects are created here as well. The first two are the input and output stream objects; a PrintStream is created for output operations through the socket and a BufferedReader is created for input socket operations. These are initialized when the e-mail is to be sent. Finally, a mail server is defined by the String mailServer. This private String is used to identify the IP address of the outgoing SMTP mail server that will be used to send the e-mail.

The smtpc constructor (lines 44–54) is used to create a new smtpc object. This method simply stores the information passed by the caller to local variables in the class in preparation for transmission.

The final two support elements of the smtpc class are the creation of a new exception (lines 60–62) and the private dialog method, which is used to perform a single transaction with the SMTP server (lines 68–113). When an error occurs within a dialog with the SMTP server, rather than return an error message to the method caller, we throw an exception. This allows the calling method to create an exception handler (the catch block) to handle all of the exception cases that are possible with a method that throws the exception. We create a new exception here called MyException that involves creating a new class and method for the exception (lines 60–62). This exception can then be thrown and caught, which we’ll discuss shortly.

The dialog method (lines 68–113) is used to perform a single transaction with the SMTP server. This involves potentially sending a command to the server, then potentially receiving a response, and then verifying that the response was correct (we received what was expected). The first item to note about this method is the declaration (lines 68–70). It’s a private method that’s accessible only to members of the class. It takes two String arguments (the String command and response), and finally it can potentially throw an exception (MyException). We declare our ability to throw this exception early in the method; we’ll see shortly where it’s actually thrown. The first task is to issue the command, if available. Lines 73–77 look at the passed command, and if it’s non-NULL, we send the command to the SMTP server through the client socket using the print method of our PrintStream. Next, we check to see if a response is expected (line 82), and if so, we attempt to read a single line from the socket using the readLine method of the BufferedReader object (representing the input stream of our client socket). Lines 91–93 test to see if the status code (the first numeric identifier returned for SMTP commands) matches what we expect. If so, we simply return. Otherwise, we throw our exception at line 100. Note that we create a new exception, as it’s an object just like any other in Java. We also throw the new MyException at line 107, in the event that there was a problem reading from the socket (such as if a peer closure occurred).

The final method in the smtpc class is the send method that is used to actually send the e-mail (lines 116–191). This method first creates the client socket (line 124) using the Socket method and connects it to the mail server (identified by the previously created mailserver String) and the mail server port (25). We then create our input and output streams over the socket to simplify the I/O operations. A BufferedReader is created to read from the socket (lines 127–129) and a PrintStream is created to write to the socket (line 132).

The actual mail client functionality is implemented in lines 134–185. The dialogs with the mail server are contained within a try block in order to catch the MyException that was created to identify errors in communication with the mail server. Note at lines 181–185, the catch block exists to catch any MyException exceptions that are thrown within any of the dialogs performed. Because the SMTP command/response functionality was explained in the C chapter, we’ll forgo a detailed discussion of it here. Each dialog potentially issues a command, and awaits a valid response before continuing to the next command. When the SMTP dialogs are complete, the close method is called (line 179) to close the client socket.

The final catch blocks (lines 188 and 189) exist to catch exceptions that could be thrown by the Socket constructor method call at line 124.

Listing 17.8 Java Simple SMTP client source.

start example
  1   import java.net.*;   2   import java.io.*;   3   4   public class smtptest {   5   6     //   7     // Java main application for the SMTP test.   8     //   9     public static void main( String[] args ) {  10  11       // Create a new smtpc object  12       smtpc mail = new smtpc(   13           "The Subject",  14           "tim@mtjones.com",  15           "mtj@mtjones.com",  16           "text/html",  17           "<HTML><BODY><H1>This is the mail"+  18           "</H1></BODY></HTML>" );  19  20       // Send the previously created e-mail  21       mail.send();  22  23     }  24  25   }  26  27   class smtpc {  28  29     // Define the local variables  30     private String s_subject;  31     private String s_sender;  32     private String s_recipient;  33     private String s_content_type;  34     private String s_contents;  35     private PrintStream out;  36     private BufferedReader inp;  37  38     // The outgoing SMTP server  39     private String mailserver = "192.168.1.1";  40  41     //  42     //  smtpc class constructor  43     //  44     public smtpc( String subject, String sender,   45                   String recipient, String content_type,  46                   String contents ) {  47  48       s_subject = subject;  49       s_sender = sender;  50       s_recipient = recipient;  51       s_content_type = content_type;  52       s_contents = contents;  53  54     }  55  56     //  57     //  A new exception used to identify SMTP   58     //  communication errors  59     //  60     class MyException extends Exception {  61       public MyException() { super(); }  62     }  63  64  65     //  66     //  Perform a transaction to the SMTP server  67     //  68     private void dialog( String command,   69                            String expected_response )  70                  throws MyException {  71  72       // If a command is available, send it to the server  73       if ( command != null ) {  74  75         out.print( command );  76  77       }  78  79       // If a response is expected, get it and test it  80       // against the desired response.  81  82       if ( expected_response != null ) {  83  84         try {  85  86           // Get a line from the SMTP server through   87           // the socket  88           String line = inp.readLine();  89  90           // Check the status code  91           if (expected_response.equalsIgnoreCase(  92                line.substring( 0,   93                       expected_response.length() ) ) ) {  94  95             return;  96  97           } else {  98  99             // Not the expected response, throw an exception 100             throw new MyException(); 101 102           } 103 104         } catch( IOException e ) { 105 106             // Another error occurred, throw an exception 107             throw new MyException(); 108 109         } 110 111       } 112 113     } 114 115 116     public void send () { 117 118       Socket sock; 119 120       try { 121 122         // Create the client socket and connect 123         // it to the server 124         sock = new Socket( mailserver, 25 ); 125 126         // Create the input stream 127         inp = new BufferedReader( 128                     new InputStreamReader(  129                           sock.getInputStream() ) ); 130 131         // Create the output stream 132         out = new PrintStream( sock.getOutputStream() ); 133 134         try { 135 136           // Look for the initial e-mail salutation 137           this.dialog( null, "220" ); 138 139           // Send HELO and await response 140           this.dialog( "HELO thisdomain.com\n", "250" ); 141 142           // Send the "MAIL FROM" and await response 143           String mailFrom = "MAIL FROM:<" + s_sender + ">\n"; 144           this.dialog( mailFrom, "250" ); 145 146           // Send the "RCTP TO" and await response 147           String rcptTo = "RCPT TO:<" + s_recipient + ">\n"; 148           this.dialog( rcptTo, "250" ); 149 150           // Send the DATA command 151           this.dialog( "DATA\n", "354" ); 152 153           // Send the e-mail source 154           String from = "From: " + s_sender + "\n"; 155           this.dialog( from, null ); 156 157           // Send the e-mail destination 158           String recip = "To: " + s_recipient + "\n"; 159           this.dialog( recip, null ); 160 161           // Send the subject 162           String subject = "Subject: " + s_subject + "\n"; 163           this.dialog( subject, null ); 164 165           // Send the Content Type 166           String ct = "Content-Type: " + s_content_type + "\n"; 167           this.dialog( ct, null ); 168 169           // Send the e-mail body 170           this.dialog( s_contents, null ); 171 172           // Await e-mail receipt acknowledgment 173           this.dialog( "\n.\n", "250" ); 174 175           // End the mail server dialog 176           this.dialog( "QUIT\n", "221" ); 177 178           // Close the client socket 179           sock.close(); 180 181         } catch( MyException e ) { 182 183           System.out.println( e ); 184 185         } 186 187       }  188       catch( UnknownHostException e ) {} 189       catch( IOException e ) {} 190 191     } 192 193   }
end example



 < Day Day Up > 



BSD Sockets Programming from a Multi-Language Perspective
Network Programming for Microsoft Windows , Second Edition (Microsoft Programming Series)
ISBN: 1584502681
EAN: 2147483647
Year: 2003
Pages: 225
Authors: Jim Ohlund

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net