Académique Documents
Professionnel Documents
Culture Documents
html
http://www.javaworld.com/cgi-bin/mailto/x_java.cgi
Sponsored by:
17
2007/8/8 11:21
http://www.javaworld.com/javaworld/jw-10-2001/jw-1026-jamesmail.html
http://www.javaworld.com/cgi-bin/mailto/x_java.cgi
design the communication flow for an email-based application, how to set up JAMES, and how to process user messages. Note: You can download this article's source code from Resources.
For instance, a seller reading about request 79834 who wants to indicate his availability would send a message to:
request-available-79834@mydomain.com
When the server receives the seller's email, it can identify the request and availability status from the target address, and identify the seller by way of his email address. If this information is sensitive, you could include a hash parameter based on the seller's account and the request ID instead of the plain request number. The encoded address would then look like this:
request-available-79834-a87bc8e0d0ea8@mydomain.com
The hash parameter a87bc8e0d0ea8 confirms that the message was not from a seller indicating availability for someone else. Note that the seller need not type the special address; the email inserts it for both available and unavailable responses in the header and message body. The email contains the special email address that indicates availability in the Reply-To header line. Usually, when the seller hits the Reply button on his email client, that client sends a message addressed to the special email address. The unavailability-indication address resides in the CC header line. When the seller hits the Reply to All
27 2007/8/8 11:21
http://www.javaworld.com/javaworld/jw-10-2001/jw-1026-jamesmail.html
http://www.javaworld.com/cgi-bin/mailto/x_java.cgi
button on his email client, the unavailability-indication address appears in the list of recipients. The seller can then delete the other address that indicates availability. The email's body contains the special email addresses in the instructions; most email software will make the address clickable. Also, if you send HTML email, you can use mailto: links easily generate messages to the appropriate address.
MailetConfig,
analogous to the Servlet API's ServletConfig, allows the mailet container to pass initialization parameters to the mailet.
Other useful Mailet API classes and interfaces include Mail, MailAddress, and MailetContext. The Mail interface wraps a MimeMessage object with SMTP delivery information, including the sender's address, a recipient's Collection, the connecting machine's remote IP address, and the message state in the mailet container. MailAddress, a more rigorous implementation of JavaMail's InternetAddress, provides helper methods to find an email address's domain and user part. The MailetContext is analogous to the ServletContext as it provides access to the mailet container. For the scheduling system, you will build a simple matcher that checks for addresses matching the address specification discussed above, and a mailet to process the
37
2007/8/8 11:21
http://www.javaworld.com/javaworld/jw-10-2001/jw-1026-jamesmail.html
http://www.javaworld.com/cgi-bin/mailto/x_java.cgi
As mentioned above, you could validate the address in the matcher; instead, we'll leave it to the mailet to determine the validity. While it is unlikely that this kind of address would have errors, it's better to have it match and then let the mailet catch any errors and reply with error messages.
47
2007/8/8 11:21
http://www.javaworld.com/javaworld/jw-10-2001/jw-1026-jamesmail.html
http://www.javaworld.com/cgi-bin/mailto/x_java.cgi
The second section, taking these settings, uses JDBC to store the result. However, before it can store anything via JDBC, you need a handle to a database connection pool. The mailet will get a reference to a pool during the init() method. Because much of this code is specific to Avalon, the underlying application framework upon which JAMES is built, it is not necessary to understand the specifics. Nonetheless, note that it gives a reference to a database connection pool:
protected DataSourceComponent datasource; public void init() throws MessagingException { try { //Get a reference to the Avalon component manager ComponentManager componentManager = (ComponentManager)getMailetContext() .getAttribute(Constants.AVALON_COMPONENT_MANAGER); // Get the list of possible data sources DataSourceSelector datasources = (DataSourceSelector) componentManager.lookup(DataSourceSelector.ROLE); // Get the data source we need datasource = (DataSourceComponent)datasources.select("maildb"); } catch (Exception e) {
57
2007/8/8 11:21
http://www.javaworld.com/javaworld/jw-10-2001/jw-1026-jamesmail.html
http://www.javaworld.com/cgi-bin/mailto/x_java.cgi
With your database connection pool, you can now write the service() method's second half:
Connection conn = datasource.getConnection(); String sql = "UPDATE SellerRequest SET available = ? WHERE seller_email = ? AND request_id = ?"; PreparedStatement stmt = conn.prepareStatement(sql); stmt.setBoolean(1, sellerAvailable); stmt.setString(2, sellerAddress); stmt.setInt(3, Integer.parseInt(requestID)); stmt.execute(); stmt.close(); conn.close(); mail.setState(Mail.GHOST); }
The second-to-last line above sets the message's state to Mail.GHOST and indicates to the mailet container that this message should not be processed further. Mailets that filter a message and want let it continue processing should leave the state as is. Again, in the final code version, you'll wrap everything in the service() method inside a try/catch block so that if any errors occur parsing the address or the message, or if there is a problem with the database connection, you can bounce a message back to the sender. You may also want to notify the seller that his response was successfully received and processed.
67
2007/8/8 11:21
http://www.javaworld.com/javaworld/jw-10-2001/jw-1026-jamesmail.html
http://www.javaworld.com/cgi-bin/mailto/x_java.cgi
The above configuration block can appear anywhere in the root processor, but should be before the final matcher/mailet setting that uses ToProcessor to send messages to the transport processor. With this in place, restart JAMES and the new matcher and mailet should be initialized and begin processing. The log files should report whether or not they successfully loaded and if they encountered any problems.
Other more exotic ideas include integrating JAMES with a fax server for email-fax-email integration. Or perhaps an application could scan for repeatedly forwarded messages to break chain messages before they clog up a mail server. Or, for the truly pious mail server administrator, a matcher could check the percentage of skin tone in attached images to spot email containing explicit images. Email is indeed the Internet's killer app, and JAMES gives Java developers the tools they need to build email-based applications.
Author Bio
Serge Knystautas is the lead technical guru and Java developer at Loki Technologies. He donated the code that started the JAMES project nearly 3 years ago, and he continues as an active contributor. He's been using Java since 1.0 beta (1995) and contributes to JSR 052, which aims to codify a standard tag library for JavaServer Pages.
All contents copyright 1995-2007 Java World, Inc. http://www.javaworld.com
77
2007/8/8 11:21