• Hitesh
  • NEWBIE
  • 0 Points
  • Member since 2008

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 1
    Questions
  • 1
    Replies

Hi,

We need some help on creating case with associated contact detail.

The New emailAgent uses the Partner API classes to create the new case. But it creates the cases with description and subject only.

Can we associate contact detail (using the from field "from" the email) using Partner API for given case? Or is there any other alternative.

Thanks in Advance .........

Hitesh

  • August 13, 2008
  • Like
  • 0

I've seen a number of posts recently for advice on how to extend the functionality of Email To Case in order to provide some specific functionality that isn't currently provided.  For example, several people have asked how they can set the name or email address of the email sender on the Case if the contact is not found.  Others have said they do not want Activities created for all Emails being attached to Cases and would like for these to be suppressed.  While I understand that these are features that may be in the works for future releases, it is not too difficult to add this functionality yourself today using the Partner API.

 

To get started, you will need to open the Email Agent project in eclipse (or any other Java IDE you are familiar with, but the distribution includes an eclipse project specification).  In my example I have chose to add a new package and class in order to keep this code separate from the core Email To Case code.  I’ve called it com.sforce.support.CaseProcessor.java. 

 

The CaseProcessor class will utilize the Partner API to retrieve all the cases that have been created by the Email Agent for a call to handleEmailMessage.  The constructor here accepts the existing SOAP binding as well as the returned SaveResult array in order to retrieve the necessary API Objects.

 

Note that the SaveResult array returned from handleEmailMessage is returning the result of creating Case and EmailMessage objects, the Ids included are those of the EmailMessages.  In order to retrieve the corresponding cases, it is neccessary to retrieve the Email Objects first, find their Parent Ids, and then use these Ids to retrieve the Case Ids. 

 

The CaseProcessor has a couple of methods used to illustrate functionality that is possible through the API.  For example, the setContactInfo class will retrieve a Case object and then check to see if the Case has a contact or not.  If there is no Contact for the Case, the sender of the email corresponding to this case will be used to set the Sender Email and Sender Name fields.

 

Another example is the deleteAllActivities method that will remove all of the Activities that were created by the handleEmailMessage call.  This is handy if you don’t want to use these activities and don’t want to go through the trouble of closing them manually.

 

In order to integrate this functionality with the Email Agent, it is necessary to add some code to the GenericClient class included in the Email To Case distribution.  In the handleMessage method an instance of CaseProcessor is instantiated passing in the binding and the results of the handleEmailMessage call.  While looping through the results of the messages, a call to the caseProcessor setContactInfo method is made for every message that was processed successfully.  Finally, the deleteAllActivities method is invoked and then the save method is called to update the cases that were updated during the looping through email messages results.

 

Here is what this looks like, though your GenericClient code might look slightly different than mine:

 

Code:

. . .
        try {

            //SOAP API call to handle loading batch of email messages into cases
            SoapBindingStub soapBinding = getBinding();
            SaveResult[] results = soapBinding.handleEmailMessage(records);
            CaseProcessor caseProcessor = new CaseProcessor(soapBinding, results);

            for (int i = 0; results != null && i < results.length; i++) {
                SaveResult r = results[i];

                postProcessParsedMessage(parsedMsgs[i], r.isSuccess());

                if (r.isSuccess()) {
                    logger.info(Calendar.getInstance().getTime().toString() + ":" + pSUCCESS +":" + i + " ID=" + r.getId() + " "+ pSUCCESS +"=" + r.isSuccess());
                    successMsgs.add(messages[i]);
                    caseProcessor.setContactInfo(r.getId(), (InternetAddress[]) messages[i].getFrom());

                } else {
                    String sMessage = r.getErrors(0).getMessage() == null — "" : r.getErrors(0).getMessage();
                    logger.error(Calendar.getInstance().getTime().toString() + ":"+ pERROR +":" + i + ": " + sMessage);
                    errorMsgs.add(messages[i]);
                }
            }

            if (readbox != null && this instanceof ImapClient) {
                inbox.copyMessages((Message[])successMsgs.toArray(new Message[successMsgs.size()]), readbox);
            }
            if (errorbox != null && this instanceof ImapClient) {
                if(errorMsgs.size() > 0) {
                    logger.info("Copying " + errorMsgs.size() + " messages to error mailbox");
                }
                inbox.copyMessages((Message[])errorMsgs.toArray(new Message[errorMsgs.size()]), errorbox);
            }

            //By now the messages are copied to either the Error box or the Processed Box, so mark them for delete.
            for (int i = 0; results != null && i < results.length; i++) {
                messages[i].setFlag(Flags.Flag.DELETED, true);
            }

            caseProcessor.deleteAllActivities();
            caseProcessor.save();

        } catch (AxisFault e) {
. . .


 
Here is the source for the CaseProcessor class:

Code:

package com.sforce.support;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.xml.namespace.QName;

import org.apache.axis.message.MessageElement;
import org.apache.log4j.Logger;

import com.sforce.soap.partner.DeleteResult;
import com.sforce.soap.partner.ID;
import com.sforce.soap.partner.SaveResult;
import com.sforce.soap.partner.SoapBindingStub;
import com.sforce.soap.partner.sobject.SObject;
import com.sforce.util.TextUtil;


public class CaseProcessor {

    static Logger logger = Logger.getLogger(CaseProcessor.class.getName());

    private static final String CASE_FIELD_LIST;
    private static final String EMAIL_FIELD_LIST;

    private static final String CASE_NUM = "CaseNumber";
    private static final String SUBJECT = "Subject";
    private static final String CONTACT_ID = "ContactId";
    private static final String PRIORITY = "Priority";
    private static final String REASON = "Reason";
    private static final String STATUS = "Status";
    private static final String PHONE = "SuppliedPhone";
    private static final String COMPANY = "SuppliedCompany";
    private static final String EMAIL = "SuppliedEmail";
    private static final String NAME = "SuppliedName";

    private static final int IDX_CASE_NUM = 0;
    private static final int IDX_SUBJECT = 1;
    private static final int IDX_CONTACT_ID = 2;
    private static final int IDX_PRIORITY = 3;
    private static final int IDX_REASON = 4;
    private static final int IDX_STATUS = 5;
    private static final int IDX_PHONE = 6;
    private static final int IDX_COMPANY = 7;
    private static final int IDX_EMAIL = 8;
    private static final int IDX_NAME = 9;

    private static final String CASE_ID = "ParentId";
    private static final String ACTIVITY_ID = "ActivityId";

    private static final int IDX_CASE_ID = 0;
    private static final int IDX_ACTIVITY_ID = 1;

    private static final String[] CASE_FIELDS;
    private static final String[] EMAIL_FIELDS;

    static {
        CASE_FIELDS = new String[10];
        CASE_FIELDS[IDX_CASE_NUM] = CASE_NUM;
        CASE_FIELDS[IDX_CONTACT_ID] = CONTACT_ID;
        CASE_FIELDS[IDX_PRIORITY] = PRIORITY;
        CASE_FIELDS[IDX_REASON] = REASON;
        CASE_FIELDS[IDX_STATUS] = STATUS;
        CASE_FIELDS[IDX_SUBJECT] = SUBJECT;
        CASE_FIELDS[IDX_COMPANY] = COMPANY;
        CASE_FIELDS[IDX_EMAIL] = EMAIL;
        CASE_FIELDS[IDX_NAME] = NAME;
        CASE_FIELDS[IDX_PHONE] = PHONE;

        CASE_FIELD_LIST = TextUtil.arrayToString(CASE_FIELDS);

        EMAIL_FIELDS = new String[2];
        EMAIL_FIELDS[IDX_CASE_ID] = CASE_ID;
        EMAIL_FIELDS[IDX_ACTIVITY_ID] = ACTIVITY_ID;

        EMAIL_FIELD_LIST = TextUtil.arrayToString(EMAIL_FIELDS);
    }

    private SoapBindingStub binding;
    private SObject[] cases;
    private SObject[] emails;
    private HashMap emailCaseIdLookup = new HashMap();
    private HashMap emailActivityIdLookup = new HashMap();
    private ArrayList updatedCases = new ArrayList();

    public CaseProcessor(SoapBindingStub binding, SaveResult[] results) throws RemoteException {

        this.binding = binding;
        ID[] idList = new ID[results.length];
        for(int i=0; i< results.length; i++) {
            idList[i] = results[i].getId();
        }

        retrieveEntities(idList);
    }

    private void retrieveEntities(ID[] ids) throws RemoteException {

        emails = binding.retrieve(EMAIL_FIELD_LIST, "EmailMessage", ids);

        if (emails != null) {
            cases = new SObject[emails.length];
            ID[] caseIds = new ID[emails.length];
            for (int i=0; i<emails.length; i++) {
                SObject email = emails[i];
                MessageElement[] fields = email.get_any();
                ID caseId = new ID(fields[IDX_CASE_ID].getValue());
                ID activityId = new ID(fields[IDX_ACTIVITY_ID].getValue());
                ID emailId = email.getId();
                caseIds[i] = caseId;
                emailCaseIdLookup.put(emailId, caseId);
                emailActivityIdLookup.put(emailId, activityId);
            }

            cases = binding.retrieve(CASE_FIELD_LIST, "Case", caseIds);

        }
    }

    /**
     * @param target  ID of email that is attached to Target Case, this is provided in SaveResult of handleEmailMessage call
     * @param email   Email address from Message, the first one is used.
     * @return        true on success, false otherwise
     * @throws RemoteException
     * @throws MessagingException
     */
    public boolean setContactInfo(ID target, InternetAddress[] email) throws RemoteException, MessagingException {

        if (email == null || email.length <=0 || cases == null) return false;

        Address addy = email[0];
        InternetAddress from;
        if (addy instanceof InternetAddress) {
            from = (InternetAddress) addy;
        } else {
            from = new InternetAddress(addy.toString());
        }

        ID caseId = (ID) emailCaseIdLookup.get(target);

        for(int i=0; i < cases.length; i++) {
            if (cases[i].getId().equals(caseId)) {
                SObject _case = cases[i];
                MessageElement[] fields = _case.get_any();
                String contactId = getValue(fields, CONTACT_ID);
                if(contactId == null) {
                    SObject updateCase = new SObject();
                    updateCase.setType("Case");
                    updateCase.setId(caseId);
                    MessageElement[] ufields = new MessageElement[2];
                    ufields[0] = new MessageElement(new QName(EMAIL), from.getAddress());
                    ufields[1] = new MessageElement(new QName(NAME), from.getPersonal());
                    updateCase.set_any(ufields);
                    updatedCases.add(updateCase);
                }
            }
        }

        return true;
    }

    public boolean deleteActivity(ID target) throws RemoteException, MessagingException {
        ID activityId = (ID) emailActivityIdLookup.get(target);

        if(activityId != null) {
            DeleteResult[] deleteResults = binding.delete(new ID[] {activityId});
            return deleteResults[0].isSuccess();
        }

        return false;
    }

    public boolean deleteAllActivities() throws RemoteException {
        ID[] ids = (ID[]) emailActivityIdLookup.values().toArray(new ID[emailActivityIdLookup.size()]);
        DeleteResult[] deleteResults = binding.delete(ids);

        boolean returnCd = true;

        for (int i=0; i < deleteResults.length; i++) {
            returnCd &= deleteResults[i].isSuccess();
        }

        return returnCd;

    }

    public boolean reAssignCase(ID target, ID assignee) throws RemoteException, MessagingException {

        return true;
    }

    private String getValue(MessageElement[] fields, String fieldname) {
        if(fields == null || fieldname == null) return null;

        for (int i=0; i< fields.length; i++) {
            if(fields[i].getName().equals(fieldname)) {
                return fields[i].getValue();
            }
        }

        return null;
    }

    public void save() {
        try {
            SaveResult[] saveResults = binding.update((SObject[]) updatedCases.toArray(new SObject[updatedCases.size()]));
            // loop through the results, checking for errors
            for (int j = 0; j < saveResults.length; j++) {
                if (!saveResults[j].isSuccess()) {
                }
            }
        } catch (Exception ex) {
            logger.error("Error updating case information", ex);
        }
    }

}


 

I hope this is helpful to some of you,

Good luck