Skip to content

Latest commit

 

History

History
184 lines (134 loc) · 7.23 KB

README.md

File metadata and controls

184 lines (134 loc) · 7.23 KB

Background

Little Timmy has a lemonade stand. He's working on marketing his product and noticed that nearly half of his customers are paying via credit card with his nifty new mobile payment app. Timmy would love to capture the contacts in his SalesForce.com account. This will allow him to start a marketing campaign to let his customers know when and where he'll be setting up next!

A Mule Implementation

In this example, we'll be using Mule to connect to Timmy's gmail acccount. He gets BCC'd with a copy of the receipt that the customers get. This will allow us to:

  • Poll his gmail account for new receipts
  • Parse the contact information (First Name, Last Name, Email)
  • We'll also categorize the contact for him by hard coding the LeadSource field as Lemonade Customer
  • To help him remember their last order, we'll use the email body and insert it into the Contact's description

Gmail to SalesForce Flow Diagram

Gmail to SalesForce Flow Diagram

View the Source

First Some SalesForce Setup

We'll be using the Mule Salesforce Connector's Upsert function (creates a new record or updates an existing). But first, we need to correlate identity between the GMail account and the SalesForce account. This is called an ExternalID field. We'll use the email address.

In order to do this, you'll have to create an ExternalID field inside of SalesForce. This can be done in just a few, simple steps:

#1 - Find the Setup Menu under your Account Menu

Setup Menu

#2 - Select the 'Customize/Contacts/Fields' option from the left nav

Contact Fields

#3 - Add the Custom Field Custom Field

Setting up the SalesForce Endpoint

Once we have the new field in place, ensure that Mule has the correct endpoint settings:

  • The sObject type should be set to Contact
  • The External ID field should match your configured field

SalesForce Endpoint Dialog

XML Source

<sfdc:upsert config-ref="Salesforce"  doc:name="Salesforce" externalIdFieldName="OriginalEmail__c" type="Contact"> 			
    <sfdc:objects ref="#[payload]"/>
</sfdc:upsert>

A Word About Payloads, Filters and Transformers

When the message arrives from Gmail, it has useful variables in the message headers. Here are just a few inbound properties which we can use to transform our payload for SalesForce:

    bccAddresses=Mule Test <[email protected]>
    ccAddresses=
    contentType=multipart/alternative; boundary=089e013cb962bdb55b04dd09ca19
    fromAddress=Timmy Smith <[email protected]>
    replyToAddresses=Timmy Smith <[email protected]>
    sentDate=Sat May 18 22:27:12 CDT 2013
    subject=Receipt
    toAddresses=Bill Murray <[email protected]>

SalesForce Upserts expects a List<Map> payload containing values for the fields you wish to update. In order to convert the payload, we've created a simple transformer by extending Mule's AbstractMessageTransformer (extend AbstractTransformer if you only want the payload).

/**
 * Custom transformer which will read the inbound message properties from an email
 * message and convert it into a list of maps (contacts) for SalesForce.
 * <br/><br/>
 * Technically, there could be multiple contacts listed on the To: email address line 
 * but we're just going to do the simple thing here and treat it as a single contact
 * for the sake of this example.
 */
public class EmailToSalesForceContactsList extends AbstractMessageTransformer {

	public static final String FIELD_FIRST_NAME = "FirstName";
	public static final String FIELD_LAST_NAME = "LastName";
	public static final String FIELD_EMAIL = "Email";
	public static final String FIELD_EXTERNAL_ID = "OriginalEmail__c";
	public static final String FIELD_LEAD_SOURCE = "LeadSource";
	public static final String FIELD_DESCRIPTION = "Description";
	
	public static final String VALUE_LEAD_SOURCE = "Lemonade Customer";
	
	EmailToSalesForceContactsList() {
		setReturnDataType(DataTypeFactory.create(List.class));
	}

	public Object transformMessage(MuleMessage message, String outputEncoding)
			throws TransformerException {
		try {
			List<Map<String, String>> contacts = createContactsFromEmail((String) message.getInboundProperty("toAddresses"));
			for (Map<String, String> contact : contacts) {
				contact.put(FIELD_DESCRIPTION, message.getPayloadAsString());
			}
			return contacts;
		} catch (Exception e) {
			throw new TransformerException(this, e);
		}
	}

	/**
	 * Create the customer from the message meta data
	 */
	protected List<Map<String, String>> createContactsFromEmail(String email) throws AddressException {
		InternetAddress address = new InternetAddress(email);
		List<Map<String, String>> contacts = new ArrayList<Map<String, String>>();
		Map<String, String> contact = new HashMap<String, String>();
		String name = address.getPersonal();
		contact.put(FIELD_FIRST_NAME, parseFirstName(name));
		contact.put(FIELD_LAST_NAME, parseLastName(name));
		contact.put(FIELD_EMAIL, address.getAddress());
		contact.put(FIELD_LEAD_SOURCE, VALUE_LEAD_SOURCE);
		contact.put(FIELD_EXTERNAL_ID, address.getAddress());
		contacts.add(contact);

		return contacts;
	}

	/**
	 * Split the name up and use all of the fields except the last. 
	 * This isn't really very reliable but it gets the point across.
	 */
	protected String parseFirstName(String name) {
		String[] values = name.split("\\W+");
		Object[] firstNameElements = ArrayUtils.subarray(values, 0,
				values.length - 1);
		return StringUtils.join(firstNameElements);
	}

	/**
	 * Split the name and use the last field. Again, not really too reliable
	 * but it's a demo :-)
	 */
	protected String parseLastName(String name) {
		String[] values = name.split("\\W+");
		return values[values.length - 1];
	}
}

When it comes out the other end, we have our List of Maps to send to SalesForce!

Sending the Email

To emulate Timmy's fancy credit card app, we'll just have to send an email manually. Go ahead and just send an email and BCC the account which is being monitored.

Sending an test email

Verify the Update in SalesForce

The flow should pick it up and create or update the SalesForce contact:

SalesForce Results

Configuration Settings

The flow includes a reference to a conf.properties file which is not included with this project (we can't be handing out our gmail our salesforce credentials now can we?). In order to run the project, you'll need to create your own:

src/main/resources/conf.properties:

imap.user=username%40mydomain.com
imap.password=1f0rg0t1t!
imap.host=imap.gmail.com
imap.port=993

[email protected]
sf.password=1f0rg0t1tT00!
sf.url=https://login.salesforce.com/services/Soap/u/25.0
sf.token=get this from your SF account settings

Example Provided By Confluex

For more information on Confluex and how we can help your organization overcome your integration challenges, please visit our website at http://www.confluex.com.