{{page_title}}

{{page_description}}


I set up my blog that only registered users can post comments to, so I will have better control. And when a new user has signed up, a confirmation email will be sent to him. He has to click a link to activate his account. And I also want the system to send me email when something happens. The requirement is simple: sending email. But it took me a while to get it work inside cloud platform.

Sending email by Java is easy, isn’t it? I mean, JavaMail API was released in 1999, and Spring Framework provides a wrapper API for email since version 1.0. In Java world, we are so familiar with sending email, and it should be trivial to do that in the clouds, right? Not at all. You can read this good post from Jeff Atwood So You’d Like to Send Some Email (Through Code) ” explaining why sending email by code is challenging these days. Our life is ruined by spammers!

When I first tried to play with CloudFoundry, I built a very simple app with Spring Roo, and added some code to send email through my Google email account. It works perfectly on my local machine, and even works in my local Micro Cloud Foundry. I uploaded my app to cloudfoundry.com with excitement, and everything worked, except no email was sent out. I checked my code again and again, and finally I realized it was not my code problem. It seems the SMTP was blocked inside the server. Then I posted a question in CloudFoundry support forum. Derek Collison answered my question instantly. That confirmed my guess: CloudFoundry didn’t provide email service, and the recommendation was to use email service from other providers like SendGrid. Well, since I was not using CloudFoundry for any real application, I could wait.

But I cannot wait any longer. I need to send welcome emails to new registered users and confirm their email addresses are valid. I started looking for email service providers, and found many discussions in StackOverflow, like SendGrid vs PostMark, and SendGrid vs Postmark vs Amazon SES and other email/SMTP API providers. From those discussions, I found this comparison for Transactional Emailing Providers .

The first one is AlphaMail, and it provides 300 free email every month. 300 should be enough for my blog. So I signed up and entered the console. It is not difficult to figure out how to use the console, and I set up my confirmation email project. The email template is stored at server side, so client only sends out the payload object, and values will be inserted into the email message body via their template language Comlang. I think it is a smart strategy, that they can control and monitor email contents, to better prevent spammers.

Their GitHub project alphamail-j2ee-client has a good example, so I downloaded their code, put into my blog project, and tried to send an email through their API. It was amazingly easy. My first email was sent to my Gmail account successfully. Wow! I tried several times more. Ouch, none was in my Inbox. I checked at alpha mail console, and found all emails were bounced back. I read Jeff’s post again and thought it must be an issue of DomainKeys Identified Mail.

At AlphaMail console, I saw this note in the “My Signature” panel:

 Add a new TXT post to your DNS server for the domain jiwhiz.com with the subdomain am182._domainkey and the value: ...

OK, I had to add a TXT record to the DNS server, but how? I sent a question to AlphaMail support. Very quickly, their CTO Timothy Johansson replied to my question, and nicely fixed some bugs in my template as well. I followed his instruction to add a TXT record in my freedns account, and tried to send the emails again. This time, all emails arrived at my inbox.

Now I cloned alphamail-j2ee-client, organized file structure to meet Maven conversion, and added pom.xml file. I put it in to GitHub, so everyone can use it. See jiwhiz/alphamail-java-client.

It is very easy to use it. First, clone to your local repository git clone [email protected]:jiwhiz/alphamail-java-client.git, and run mvn clean install inside alphamail-java-client folder to install it on your local machine. In your project, add this dependency:

    
        com.comfirm.alphamail
        alphamail-java-client
        0.1.0
    

In my blog app, I created a small service ConfirmEmailSender. The interface is :

public interface ConfirmEmailSender {
    void send(UserAccount account);
}

The implementation is

public class ConfirmEmailSenderImpl implements ConfirmEmailSender {
    final static Logger logger = LoggerFactory.getLogger(ConfirmEmailSenderImpl.class);

    private final AlphaMailService mailService;
    private final ConfirmationRepository confirmationRepository;

    private int projectId;
    private String senderName;
    private String senderEmail;
    private String confirmationURL;
    @Inject
    public ConfirmEmailSenderImpl(AlphaMailService mailService, ConfirmationRepository confirmationRepository) {
        this.mailService = mailService;
        this.confirmationRepository = confirmationRepository;
    }
    @Override
    public void send(UserAccount account) {
        String token = UUID.randomUUID().toString();
        String activationLink = getConfirmationURL()+token;
        PayloadObject payload = new PayloadObject(account.getDisplayName(), activationLink);

        EmailMessagePayload message = new EmailMessagePayload().setProjectId(getProjectId()).setReceiverId(0)
                .setSender(new EmailContact(getSenderName(), getSenderEmail()))
                .setReceiver(new EmailContact(account.getDisplayName(), account.getUsername())).setBodyObject(payload);

        try {
            ServiceIdentityResponse response = mailService.queue(message);
            logger.info(String.format("Send email to %s, result is %s ", account.getUsername(), response.getResult()));

            // save record
            UserEmailConfirmation confirmation = new UserEmailConfirmation(account.getUsername(), token,
                    response.getResult().toString());
            confirmationRepository.save(confirmation);

        } catch (AlphaMailServiceException e) {
            e.printStackTrace();
            String logMessage = String.format("AlphaMail returned exception: Error Code: %s, Error Message: %s", e
                    .getResponse().getErrorCode(), e.getResponse().getMessage());
            logger.warn(logMessage);
        }

    }

    public class PayloadObject {
        private String userName;
        private String activationLink;

        public PayloadObject(String userName, String activationLink) {
            this.userName = userName;
            this.activationLink = activationLink;
        }

        public String getUserName() {
            return userName;
        }

        public String getActivationLink() {
            return activationLink;
        }
    }

}

Getter and Setter methods are omitted.

The AlphaMailService and ConfirmationRepository are injected into ConfirmEmailSenderImpl. And in config class, projectId, senderName, senderEmail and confirmationURL are also passed from properties:

    @Bean
    public ConfirmEmailSender confirmEmailSender(){
        ConfirmEmailSenderImpl sender = new ConfirmEmailSenderImpl(alphaMailService(), confirmationRepository);
        sender.setProjectId(environment.getProperty("alphamail.project.confirm.id", int.class));
        sender.setSenderName(environment.getProperty("alphamail.senderName"));
        sender.setSenderEmail(environment.getProperty("alphamail.senderEmail"));
        sender.setConfirmationURL(environment.getProperty("confirmation.url"));
        return sender;
    }

    @Bean
    public AlphaMailService alphaMailService(){
        DefaultAlphaMailService mailService = new DefaultAlphaMailService();
        mailService.setServiceUrl(environment.getProperty("alphamail.url"));
        mailService.setApiToken(environment.getProperty("alphamail.token"));
        return mailService;
    }

The value of alphamail.project.confirm.id is the ID for the project I created for confirmation email in AlphaMail console. alphamail.url and alphamail.token are also available from AlphaMail console. Based on the deployed environment, the confirmation.url can be http://localhost:8080/blog-web/confirmEmail/ for local test or http://www.jiwhiz.com/confirmEmail/ for blog app running in AppFog.

That’s my journey of sending email inside cloud. I didn’t try MailGun, SendGrid or SocketLab. T he services are very similar, and price plans are also competitive. But my current app does not need that volume of emails. AlphaMail is good enough for me now.