Build a Bulk Emailer for Salesforce with App Engine

Sometimes you just want to send a crapload of email from However, like every PaaS platform there are limits baked into the multi-tenant environment so you don't stomp on other tenants' resources. limits you to 2000 emails per day for each Salesforce license. So if you don't have a lot of Salesforce licenses or a different kind of license, you may be out of luck if you want to send out large volumes. There are a few AppExchange products but they seem more targeted towards marketing purposes.

Google App Engine may be a good solution in this case. With Google App Engine quotas you get 7,000 Mail API calls per day free and can bump that up as high as 1.7M with a paid account.

Here's how to roll your own basic bulk emailer using Google App Engine. Take a look at the video below, but it essentially queries for records, uses the Google Mail Java API to send out individual emails and then send an administrator a notification via Jabber (Google Talk). You can schedule your application (essentially a Servlet) to run on a timed basis using the cron service.

All of this code is at this GitHub repo.

Most of the important code is in the MailServlet class.

package com.jeffdouglas.emailer;

[removed imports]

 * - a simple, schedulable servlet for sending mail
 * with
 * @author Jeff Douglas
 * @version 1.0
 * @see
 * for more details on using Mail with App Engine

public class MailServlet extends HttpServlet {

    private static final Logger logger = Logger.getLogger(ConnectionManager.class.getName());
    private String jabberRecipient = "";

    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {

        String mailerMsg = "No contact found to email!!";
        QueryResult result = null;

        // get a reference to the salesforce connection
        PartnerConnection connection = ConnectionManager.getConnectionManager().getConnection();

        try {
            // query for contacts based upon some criteria -- emailNotSent boolean
            result = connection.query("Select Id, FirstName, LastName, Email " +
                "FROM Contact Where Email = '' Limit 1");
        } catch (ConnectionException e) {
        } catch (NullPointerException npe) {

        // if records were returned then send out email
        if (result != null) {

          for (SObject contact : result.getRecords()) {

            // construct the 'name' for the email recipient
            String contactName = contact.getField("FirstName").toString() + " " + 

  "Sending emil to " + contactName + " at " + 

            /// send the email
            mailerMsg = sendMail(contact.getField("Email").toString(), contactName);

            // send a jabber notification of the status
            sendJabberNotification(jabberRecipient, mailerMsg);


          // TODO - make a call back into salesforce and update these records
          // as having their emails sent. Implementation is up to you.

        } else {
          logger.warning("No results returned from salesforce");



     * Sends an email
     * @param toAddress the email address of the recipient
     * @param toName the name that appears for the recipeint in their email client  
     * @return A String representing the status of the email sent  
    private String sendMail(String toAddress, String toName) {

      String msg = "Email sent successfully to " + toAddress;
      Properties props = new Properties();
      Session session = Session.getDefaultInstance(props, null); 

      String messageBody = "This is the body of my email";

      try {

          Message emailMessage = new MimeMessage(session);
          //  must be the email address of an administrator for the application. see docs
          emailMessage.setFrom(new InternetAddress("","Jeff Douglas"));
            new InternetAddress(toAddress, toName));
          emailMessage.setSubject("My Email Subject");

      } catch (AddressException e) {
          msg = e.toString();
      } catch (MessagingException e) {
          msg = e.toString();
      } catch (UnsupportedEncodingException e) {
          msg = e.toString();

      return msg;

     * Sends a message to any XMPP-compatible chat messaging service (google talk). 
     * See
     * for more detils
     * @param recipient the jid of the jabber recipient of the notification
     * @param msgBody the body of the message to be sent  
    private void sendJabberNotification(String recipient, String msgBody) {

      JID jid = new JID(recipient); msg = new MessageBuilder()

      boolean messageSent = false;
      XMPPService xmpp = XMPPServiceFactory.getXMPPService();

      if (xmpp.getPresence(jid).isAvailable()) {
          SendResponse status = xmpp.sendMessage(msg);
          messageSent = (status.getStatusMap().get(jid) == SendResponse.Status.SUCCESS);
      }"Jabber notifiation sent: " + messageSent);