Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Send Email CSV Attachment Data to Salesforce

DZone's Guide to

Send Email CSV Attachment Data to Salesforce

Learn how to use a Mule application to send information to Salesforce every time an email with a CSV file attached is received.

· Integration Zone ·
Free Resource

The new Gartner Critical Capabilities report explains how APIs and microservices enable digital leaders to deliver better B2B, open banking and mobile projects.

I had a requirement to send information to Salesforce every time I got an email with a CSV File attached. With a Mule application, it seems like a pretty straightforward thing, so now I'll try to explain how we can do it.

Let's create a simple application in Anypoint Studio.

Before we start dragging components, we need to make sure we have activated IMAP in our email service; in this case, I'm using Google with a non-business account (regular account).

Let's grab the IMAP connector in the inbound flow part just like this:

alt

The configuration of the connector is simply to add the authentication properties, and that's it.
alt

Then you can add a filter expression component to filter those emails by subject; this step is basically optional. The expression to validate the subject will be something like this:
#[message.inboundProperties.subject contains 'csv file']

Then we need to add an expression transformer to get the attachment list in the incoming email. This is the component in the XML version (for some reason in the UI, I couldn't set up the configuration):

<expression-transformer doc:name="Expression"> <return-argument evaluator="attachments-list" expression="*.csv"/> </expression-transformer>

and then a Collection-Splitter component:
<collection-splitter doc:name="Collection Splitter"/>

In my case, I couldn't really figure out how to extract the Streaming part of the file with a MEL expression, so I created a simple Java class instead. This class basically extracts the InputStream body of the file, and then I just return that value. So you need to add the Java component and select your Java class. Here's the snippet:

import java.io.IOException;  
import java.io.InputStream;

import javax.activation.DataHandler;  
import javax.activation.DataSource;

import org.mule.api.MuleMessage;  
import org.mule.api.transformer.TransformerException;  
import org.mule.transformer.AbstractMessageTransformer;

public class ProcessAttachments extends AbstractMessageTransformer{  
    @Override
    public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
        DataHandler attachments = (DataHandler) message.getPayload();
        DataSource source = attachments.getDataSource();
        InputStream stramInfo = null;
        try {
            stramInfo = source.getInputStream();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return stramInfo;
    }
}

Then just I added a ByteArray to the Object component and Dataweave to read the CSV body (for me, was easy to import a schema sample data from the actual file I want to read in order to map the data correctly).

TIP: Sometimes it is better to drag the Salesforce connector in order to see the full list of fields in Dataweave available.

My Dataweave component looks like this:

Basically, the mapping should look like this:

%dw 1.0
%output application/java
---
payload map ((payload01 , indexOfPayload01) -> {  
    Name: payload01.PACE_JOB_NAME,
    AccountNumber: payload01.PACE_JOB_Number
})

Then we need to set the Salesforce connector for "Create Bulk" and then select the SObject where we want to insert the data from the CSV file. That's it!

The full code looks like this:

<mule xmlns:sfdc="http://www.mulesoft.org/schema/mule/sfdc" xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata" xmlns:imaps="http://www.mulesoft.org/schema/mule/imaps" xmlns:imap="http://www.mulesoft.org/schema/mule/imap" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw" xmlns:azure-storage="http://www.mulesoft.org/schema/mule/azure-storage" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/azure-storage http://www.mulesoft.org/schema/mule/azure-storage/current/mule-azure-storage.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/imap http://www.mulesoft.org/schema/mule/imap/current/mule-imap.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/imaps http://www.mulesoft.org/schema/mule/imaps/current/mule-imaps.xsd
http://www.mulesoft.org/schema/mule/sfdc http://www.mulesoft.org/schema/mule/sfdc/current/mule-sfdc.xsd">
    <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
    <imaps:connector name="IMAP" validateConnections="true" doc:name="IMAP" deleteReadMessages="false">
    </imaps:connector>
    <file:connector name="File" autoDelete="true" streaming="true" validateConnections="true" doc:name="File"/>
    <sfdc:config name="Salesforce__Basic_Authentication" username="saleeforceUserName" password="PAssword" securityToken="mysecuritytokeb" doc:name="Salesforce: Basic Authentication"/>
    <flow name="demoFlow">
    <imaps:inbound-endpoint host="imap.gmail.com" port="993" user="hidroc8354%40gmail.com" password="mypassword" responseTimeout="10000" doc:name="IMAP" connector-ref="IMAP"/>
        <expression-filter expression="#[message.inboundProperties.subject contains 'csv file']" doc:name="Expression"/>
        <expression-transformer doc:name="Expression">
            <return-argument evaluator="attachments-list" expression="*.csv"/>
        </expression-transformer>
        <collection-splitter doc:name="Collection Splitter"/>
        <custom-transformer class="com.sitetraker.ProcessAttachments" doc:name="Extract attachment"/>
        <byte-array-to-object-transformer doc:name="Byte Array to Object"/>
        <dw:transform-message doc:name="Transform Message" metadata:id="8a5a65bf-c148-4c27-99dc-55978eb4feb3">
            <dw:input-payload mimeType="application/csv"/>
            <dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
payload map ((payload01 , indexOfPayload01) -> {
Name: payload01.PACE_JOB_NAME,
AccountNumber: payload01.PACE_JOB_Number
})]]></dw:set-payload>
        </dw:transform-message>
        <sfdc:create-bulk config-ref="Salesforce__Basic_Authentication" type="Account" doc:name="Salesforce">
            <sfdc:objects ref="#[payload]"/>
        </sfdc:create-bulk>
        <logger level="INFO" doc:name="Logger" message="#[payload]"/>
    </flow>
</mule>

The new Gartner Critical Capabilities for Full Lifecycle API Management report shows how CA Technologies helps digital leaders with their B2B, open banking, and mobile initiatives. Get your copy from CA Technologies.

Topics:
salesforce ,mule ,csv ,mulesoft ,anypoint studio ,integration ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}