The Mail Services stuff is based on a protocol-independent thread-pooled JMX service. Presently SMTP is in the works. Contributers are welcome. Here is the present plan.
ServerMBean - protocol independent, thread pooling, socket listener,
delegates threads to a configured "protocol" which will be looked up by name
from the JMX bus. Unit tests say that when the garbage collector doesn't
muck things up it performs in 1-5ms per request (despite a bunch of
System.outs and stuff)
SMTPProtocol - Most of what I think we need is there. Mozilla mail is
happy, my unit tests pass. Uses a command pattern and passes off to
handlers for each of the SMTP commands. (Yeah don't hate me because I use
patterns, I use them because I'm lazy and don't want to describe in great
detail what "command pattern" says to those of you who read the GOF)
UserRepository - Plugs in to SMTPProtocol and says Yea or Nea for users
MailListeners - plugs in to SMTPProtocol, 1 or more. I have only 1
presently that says "Hi I got a mail, I'm letting it be garbage collected".
1. Figure out how to have a reasonable protocol independent but non-cracked
JMX setup for things like the UserRepository, MailListeners, etc. (Some
will be used in POP and IMAPProtocol, some won't, but the same ServerMBean
handles them all). I think I've figured it out... It kinda sucks that the
XML garbage will infect some of the code, but that's life I guess.
2. Figure out a nice bridge between RCPT TO: and JMS Queues or topics. I'm
thinking of just posting to 1 JMS topic and letting a message bean sort it
out into mail boxes or forward it to other beans. I'm also thinking of
posting to 2 instead (OnServer, OffServer). Meaning if Bill has an account
on the SMTP server he can send a mail via that server to
"email@example.com". The OffServer topic would be things that
need to be sent elsewhere. The OnServer topic would be things that need to
be written to the DB for later retrieval. The obvious implication is that
you could swap out with your own MDBs and/or MessageListeners that did OTHER
things with the mails (like reply back "Why would you use a virus scanner
that sends me a return receipt for SoBIG.F, if it KNOWS that SoBIG.F forges
the mail headers you big sorry dolt!")
TODO next week (subject to change):
1. Work out both the above issues, writing a mail listener that does
something meaningful with the mails.
2. Figure out what pieces of SMTP I'm missing and any intricacies of SMTP
AUTH that I should have
3. Ditch my ProtocolFactory for JMX.
4. Research encrypted SMTP.
5. Hook up with Nukes so that there is a Mail-Forum bridge of sorts
The basic design lets me implement any Request/Response based protocol on a
multi-threaded basis. I just create a new "Protocol" and configure an
instance that uses it.
Thus far I've got a StaticUserRepository which takes a JMX configuration for user/password. I've also stubbled out a JMSMessageListenerMBean which sends to two queues: "onServer" and "offServer" depending on the mail's destination. It doesnt' work yet, but its coming along.
I volunteer for the encryption-thing. Shouldn't we aim for a implementation of rfc 2487?
Has any thought been given to using the Mailet API, http://james.apache.org/mailet_api_2_1.html ? I'm also not sure what the licensing implications would be but it appears that the Apache James server has a fairly robust SMTP and IMAP implementation which could be adapted. I've worked with mailets under james and found it to be a clean solution for writing email based apps.
I'd volunteer to do some work on SMTP/IMAP for jboss including a possible mailet API. I'm also willing to investigate the possibility of including the code from Apache James if there is sufficient interest.
The mailet API is kind of...well go look at the code and tell me what you think of it. I'm taking the parts of JAMES that I like and leaving the rest behind. You'll notice I took their streams and some of that stuff and left other parts behind. Now the actual mailets...It might be fruitful to create a compatibility API later...Might be early right now.. Jump in. Lets steal the good parts of JAMES and leave the junk out. I don't care for: watchdog, avalon, etc. I think we can do better. What would be cool is if someone understands nio well, we could start using that if it give us a performance boost.. BTW Noel Bergman is planning on refactoring JAMES to smell a little more like our approach (command pattern for protocol).
Yes definitely start sending patches for adding TLS support. Looks like it could be pretty simple to implement.
doesn't sound too difficult. I'm going to start next wednesday (still on holiday..(-:)
Cool. Things are moving along quite nicely. Eric's started POP... If you nail TLS then life could be good. I should have the unit test framework working standalone pretty soon. Be sure to accompany with unit tests.
Ok, I got a working version now.
There is a thing that needs some discussion: After the client says "STARTTLS", I must replace the socket from the class ServerThread with an SSLSocket. To get the socket I added an instance variable "serverThread" and the corresponding public accessor methods to the AbstractProtocol class.
Sounds reasonable. You will call the set method from the ServerThread.run() method?
I'm looking forward to seeing your implementation. I looked into this a while ago for JES but never got around to trying to implement it.
No, I am calling it from my SMTPCommand:
Here is a TAR of my changes. I added new attributes to jboss-service.xml and changed some of the other classes as well as some tests.
Authentication via certificates is not working well. I need to find a client that supports this feature. Mozilla does not seem to send the client-cert, Opera sends it but crashes afterwards. Probably my fault, but I am at it.
If you try it, you need to generate a server-key and put in a keystore. You must set the keystore in jboss-service.xml. And it must be a RSA-key (at least for Nestscape-Messenger). Isn't there a more generic way to add certificates to JBoss?
Here is the missing attachment
I have solved the issue about the certificates. I needed to put the CA-Certificate in the $JAVA_HOME/...../cacerts file. It seems to work quite well now that the setup is right. But I think that we should really have a application for the management of certificates, just like windows. Keytool should not be the last word, I think...
I applied your changed to CVS. I had to make a single change to ServerThreadPool to handle an uncaught IOException.
Thanks! I have implemented a custom mail-header which shows part of the certificate of the sender. The longer I am at it the more I like it. If certificates were mandatory, e-mail would be much harder to abuse. One could for example trace back spam reliably.
In the class org.jboss.mail.smtp.Mail there is a suggestion of writing a new class that represent the mail-headers. If there is no objection, I would do that, because I need this class anyway. Currently the addition of a new header is cumbersome, one needs code for encoding and breaking of long lines that really belongs to a seperate class.