9
votes

PROBLEM:

I'm trying to use JavaMail to send email from an EC2 Ubuntu 12.04 Server but it's not working.


BACKGROUND:

I intend to send an auto generated mail from a Tomcat Server to a few team members. I used JavaMail 1.4.7 for this task and I've successfully tried it on a local installation of Tomcat (on a personal laptop).

The next step was where I put this module on an EC2 Server but it started failing with the below given error:


ERROR:

DEBUG SMTP: AUTH LOGIN failed javax.mail.AuthenticationFailedException: 535-5.7.1 Username and Password not accepted. Learn more at 535 5.7.1 http://support.google.com/mail/bin/answer.py?answer=14257 j13sm1603739pat.17 - gsmtp

at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:826)
at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:761)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:685)
at javax.mail.Service.connect(Service.java:295)
at javax.mail.Service.connect(Service.java:176)

Code Snippet:

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
Properties props = new Properties();
props.put("mail.smtps.host","smtp.gmail.com");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtps.auth", "true");
props.put("mail.smtp.debug", "true");
props.put("mail.smtp.port", 465);
props.put("mail.smtp.socketFactory.port", 465);
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.ssl.enable", true);

Session session = Session.getDefaultInstance(props);
session.setDebug(debug);

Message msg = new MimeMessage(session);
InternetAddress addressFrom = new InternetAddress("[email protected]");
msg.setFrom(addressFrom);

InternetAddress[] addressTo = new InternetAddress[recipients.length];
for (int i = 0; i < recipients.length; i++) {
addressTo[i] = new InternetAddress(recipients[i]);
}
msg.setRecipients(Message.RecipientType.TO, addressTo);
msg.setSubject("test subject");
msg.setContent("test message", "text/plain");
Transport tp = session.getTransport("smtp");
tp.connect(SMTP_HOST_NAME, "[email protected]", "dummypassword");
tp.sendMessage(msg, addressTo);
tp.close();

ADDITIONAL INFO:

  1. I've added permissions for all ports on the EC2 instance. Also, I've added explicit permissions for ports 465(SMTPS) and 25(SMTP).
  2. I've cross checked the correctness of the username and password provided in the code.
1
Have you tried using the Authenticator as per mkyong.com/java/… instead of just putting the username/password in the connect? Not sure it matters.Daniel Moses
I started off with that example and it wasn't working. It was throwing the same exception. Then I went on to provide the username/password in the connect() method but still it was throwing the same error.Michael Massey
Using an Authenticator doesn't matter. The error is coming from Gmail, not from JavaMail. You may think you're using the correct usernme and password, but you're not.Bill Shannon
Well, I suppose it's possible that Gmail is rejecting your username and password no matter what it is if the connection comes from some place it doesn't like, but you'll need to ask Google about that.Bill Shannon
Hi Bill, as I've mentioned in the Question's Background that the same piece of code is working fine from my local machine. So, we can rule out the possibility of any error in the username/password.Michael Massey

1 Answers

7
votes

In the past, spam sent from servers within EC2 has been a major problem for both Amazon and mail service providers. Initially, Amazon deliberately had insufficient DNS information to pass anti-spam checking of common email services (lack of DNS reverse lookup PTR records), then Amazon introduced low mail quotas, followed approval processes to give full access to EC2 or SES mail (provides specific technical setup to fully enable outgoing email).

Here's a link describing some of the history: http://shlomoswidler.com/2009/07/sending-email-from-ec2.html

While the error you're getting is a failed authentication at Gmail server, it may be (probably is) because Gmail identifies your sender IP address as a potential spammer, because you didn't setup Amazon reverse DNS lookup properties correctly.

  1. Setup Amazon Reverse DNS lookup details, so that your mail is not detected as spam by Gmail. It seems this can only be done by submitting a request form to lift Email Sending quota. From Amazon EC2 IP Information FAQs:

    Q: Can I configure the reverse DNS record for my Elastic IP address?

    Yes, you can configure the reverse DNS record of your Elastic IP address (submit the Request to Remove Email Sending Limitations Form). Note that a corresponding forward DNS record pointing to that Elastic IP address must exist before we can create the reverse DNS record.

    Here's an example of an email sent out by Amazon when an email quota is exhausted - again spelling out request & approval for DNS PTR configuration: http://www.practicalclouds.com/content/guide/sending-email-ec2-instances

  2. Precisely follow all the instructions in the link included in you Gmail error message: http://support.google.com/mail/bin/answer.py?answer=14257. This will reset your Gmail account status, if Gmail thinks your account is spamming from your IP address.

  3. Alternatively, you can send mail via Amazon SES, also requiring request, approval and appropriate Amazon-provided configuration. This allows mail to be sent via com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient.sendEmail. If you use this, add authorisation for your code to sendmail: Unable to send email from Amazon EC2 Server in Java.