| By Aaron Johnson | Article Rating: |
|
| September 27, 2006 04:00 PM EDT | Reads: |
13,674 |
James ships with a number of Mailets and Matchers that you can use without writing a line of code, but the developers at Javazon will have to write their own Matcher and Mailet to handle the bounces generated from their e-mail campaigns.
So the first thing they're going to need to do is create a class that intercepts the bounced e-mails. A matcher class can be created in one of two ways: a) create a class that implements the org.apache.mailet.Matcher interface, or b) create a class that extends the org.apache.mailet.GenericMatcher class. Because GenericMatcher already implements both Matcher and MatcherConfig and because it provides a simple version of the lifecycle methods, the path of least resistance is to extend the GenericMatcher. The NewsletterMatcher class is going to "match" only the recipients where the address of the recipient starts with the string "deals-":
public class NewsletterMatcher extends GenericMatcher {
public Collection match(Mail mail) throws MessagingException {
Collection matches = new ArrayList();
Collection recipients = mail.getRecipients();
for (Iterator i=recipients.iterator(); i.hasNext();) {
String recipient = (String)i.next();
if (recipient.startsWith("deals-")) {
recipients.add(recipient);
}
}
return matches;
}
}
The NewsletterMatcher class, as you can see, returns a Collection of String objects, each presumably an e-mail that has bounced. To do something with these matches, developers will need to write a class that either implements the org.apache.mailet.Mailet interface or a class that extends the org.apache.mailet.GenericMailet class. Again, it will be simpler to extend the GenericMailet class:
public class NewsletterMailet extends GenericMailet {
private static CustomerManager mgr = CustomerManager.getInstance();
public void service(Mail mail) throws MessagingException {
Collection recipients = mail.getRecipients();
for (Iterator i=recipients.iterator(); i.hasNext();) {
String recipient = (String)i.next();
if (recipient.startsWith("deals-")) {
int atIndex = recipient.indexOf("@");
String rec = recipient.substring(0,atIndex)
.replaceAll("=", "@")
.replaceAll("deals-", "");
mgr.recordBounce(rec);
mail.setState(Mail.GHOST);
}
}
}
}
In the example above, the NewsletterMailet class overrides the service() method in the GenericMailet class, loops over the list of recipients in the given e-mail message and then checks to see if the recipient e-mail address starts with the string "deals-". If the recipient e-mail address starts with "deals-" then the class decodes the original recipient address by retrieving what is generally the username part of the e-mail address, replacing the equals sign (=) with an @ sign and then replacing the "deals-" prefix. Then the Newsletter mailet class uses CustomerManager (a class that the Javazon developers use to manage customer information) to record the bounced e-mail. If you were to step through the process, you'd see the recipient e-mail address start something like this:
deals-ajohnson=cephas.net@javazon.com
and then change to this:
deals-ajohnson=cephas.net
and finally to this:
ajohnson@cephas.net
The last step is to wire the mailet and matcher classes together in the Apache James configuration file, which is usually located here:
$JAMES/apps/james/SAR-INF/config.xml
You'll need to make a number of entries. First, you'll need to let James know where it should look for the mailet and matcher classes you've created by creating <mailetpackage> and <matcherpackage> entries inside the <mailetpackages> and <matcherpackages> elements:
<mailetpackages>
...
<mailetpackage>com.javazon.mailets</mailetpackage>
</mailetpackages>
<matcherpackages>
...
<matcherpackage>com.javazon.matchers</matcherpackage>
</matcherpackages>
Then add references to the matcher and the mailet using a <mailet> element like this:
<mailet match="NewsletterMatcher" class="NewsletterMailet">
<processor>transport</processor>
</mailet>
The match attribute of the mailet element specifies the name of the matcher class that should be instantiated when the matcher is invoked by the spool processor and the class attribute specifies the name of the mailet that you want invoked should the matcher class return any hits.
After adding these configuration entries and adding the compiled classes to the $JAMES/apps/james/SAR-INF/lib/ directory, restart the James process.
Testing
To test the configuration/application,
you'll have to have a James server configured and available via the
Internet via port 25 with a valid DNS name and a corresponding MX
record. As an example, the system administrator at Javazon would
configure a machine with James, make it available to the Internet on
port 25, and assign it a domain name like bounces.javazon.com. The
developers could then send an invalid e-mail using JavaMail to:
(an account that probably doesn't exist on the main javazon.com mail server) with a return path of:
deals-bounceme=javazon.com@bounces.javazon.com.
The bounced e-mail will be sent to the server associated with the MX record for the domain name bounces javazon.com, which should be the server the system administrator set up above. The NewsletterMatcher class should 'match' on the "deals-" prefix and then pass it to the NewsletterMailet, which should record the bounce using the CustomerManager instance.
Conclusion
After reading this article, you should
hurry on over to the Apache James Web site, download the latest
distribution, and read the documentation. There are a number of other
interesting ways you can improve your e-mail processing by extending
James using mailets and matchers.
References
JavaMail
Published September 27, 2006 Reads 13,674
Copyright © 2006 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Aaron Johnson
Aaron Johnson is a senior software engineer at Jive Software. He lives with his wonderful wife, young son and dog in a Portland, Oregon. You can find out more by reading his blog at http://cephas.net/blog/.
- Kindle 2 vs Nook
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- Confessions of a Ulitzer Addict
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- It's the Java vs. C++ Shootout Revisited!
- Cloud Computing Can Revitalize Your Career as Software Developer
- IBM Could "Reinvent" Java: Mills
- Oracle & Cloud Computing: Exclusive Q&A with SVP Richard Sarwal
- A Brief History of Cloud Computing
- Kindle 2 vs Nook
- Cloud CEOs, CTOs & SVPs to Speak at 4th International Cloud Computing Expo
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- The Difference Between Web Hosting and Cloud Computing
- Cloud Computing Expo: Exclusive Q&A with Yahoo! SVP Cloud Computing
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- My Thoughts on Ulitzer
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- The i-Technology Right Stuff
- JavaServer Faces (JSF) vs Struts
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- What's New in Eclipse?
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- i-Technology Predictions for 2007: Where's It All Headed?









































