Spring, JavaMailSender, and SMTP Authentication
When running a legitimate business that sends large amounts of email, it can be a real challenge to make sure these critical emails are delivered to a user’s Inbox. If your subscribers are actually paying you to send email on their behalf, the situation becomes even more precarious. It is certainly possible to run your own outbound mail server and to get excellent delivery. But to do so you have to be set up and manage things like SPF and DomainKeys entries in DNS, you must continually monitor your sender reputation, and you must act quickly to remove your server from any black lists. Most of all you must be vigilant about securing your mail server from malicious spammers who will use any vulnerability to ruin your hard-won reputation.
I have worked with businesses that send hundreds of thousands of legitimate emails per month. Some of these companies have employees who’s job function it is to monitor and guarantee delivery. Believe me this is a difficult, frustrating, and time-consuming job. For most small businesses it just does not make financial sense to dedicate personnel to this task. I recommend that my clients run their newsletters through paid services such as Constant Contact or AWebber. They handle all the dirty work and let you concentrate on the content.
However, for businesses who must send one-off emails such as notifications, password resets, and private messages, we have to look at third-party email senders. For a recent client I evaluated three: CritSend, MessageGears, and SMTP.com. All three could provide the volume of email (approx 10,000/month) they were sending for just a few hundred dollars a year. This is at least an order of magnitude cheaper than trying to maintain the reputation on a single mail server. And integration can be as simple as pointing your code to a new outbound SMTP server.
Well, at least I thought the integration was that simple. For this project I was using Spring and a JavaMailSenderImpl to direct mail to a SMTP server that required authentication. I learned two tricks that I think are useful enough to share.
My initial spring setup looked like this:
<bean id="critSendMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.critsend.com"/> <property name="port" value="587"/> <property name="username" value="..."/> <property name="password" value="..."/> </bean>
This resulted in the rather cryptic error:
451 Requested action aborted: local error in processing com.sun.mail.smtp.SMTPSendFailedException: 451 Requested action aborted: local error in processing
The first trick was to enable debugging for the SMTP connection:
<bean id="critSendMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.critsend.com"/> <property name="port" value="587"/> <property name="username" value="..."/> <property name="password" value="..."/> <property name="javaMailProperties"> <props> <prop key="mail.debug">true</prop> </props> </property> </bean>
The debugging gave me this information in standard out:
DEBUG SMTP: useEhlo true, useAuth false DEBUG SMTP: trying to connect to host "smtp.critsend.com", port 587, isSSL false 220 mail29.messaging-master.com NO UCE NO UBE NO RELAY PROBES ESMTP DEBUG SMTP: connected to host "smtp.critsend.com", port: 587 EHLO www2 250-mail29.messaging-master.com Hello nice to meet you 250 AUTH PLAIN CRAM-MD5 LOGIN DEBUG SMTP: Found extension "AUTH", arg "PLAIN CRAM-MD5 LOGIN" DEBUG SMTP: use8bit false MAIL FROM:<...@...s.com> 451 Requested action aborted: local error in processing
Oops. Apparently just setting the username and password is not enough to tell JavaMail to use authentication. That lead to the second trick:
<bean id="critSendMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.critsend.com"/> <property name="port" value="587"/> <property name="username" value="..."/> <property name="password" value="..."/> <property name="javaMailProperties"> <props> <prop key="mail.debug">true</prop> <prop key="mail.smtp.auth">true</prop> </props> </property> </bean>
Success:
DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "smtp.critsend.com", port 587, isSSL false 220 mail29.messaging-master.com NO UCE NO UBE NO RELAY PROBES ESMTP DEBUG SMTP: connected to host "smtp.critsend.com", port: 587 EHLO www2 250-mail29.messaging-master.com Hello nice to meet you 250 AUTH PLAIN CRAM-MD5 LOGIN DEBUG SMTP: Found extension "AUTH", arg "PLAIN CRAM-MD5 LOGIN" DEBUG SMTP: Attempt to authenticate AUTH LOGIN 235 Authentication successful. ... 250 Delivery in progress QUIT

Leave a comment