“I've adapted Scott Hammeter's dandy code (http://sfdc.arrowpointe.com/2009/10/06/associate-email-to-salesforce-task-to-opportunity/) so I can relate the tasks created by inbound Email-to-Salesforce emails to active campaigns rather than to open opportunities. The heart of the solution is a constructor in a class called by a beforeInsert task trigger. The construct queries for campaigns related to the contact identified in the task's WhoId:
// Associates a new Task generated by Email to Salesforce to an open opportunity, if one exists for the Account
public void AssociateCampaign(Task[] tasks)
{
/***************
* Variables
***************/
list<Task> l_Tasks = new list<Task>(); // Tasks to update
set<ID> s_ContactIDs = new set<ID>(); // Set of Contact IDs
/***************
* Initial Loop
***************/
for(Task t:tasks) {
// Add Task to working list and collect the Contact ID
if (t.WhatId == null && t.Subject.startsWith('Email:') && t.WhoId != null) {
// only for Contacts
if (String.valueOf(t.WhoId).startsWith('003')){
l_Tasks.add(t);
s_ContactIDs.add(t.WhoId);
}
}
}
/***************
* Create Maps
***************/
// Maps Contact ID to a Campaign ID
map<ID, ID> map_cID_to_camID = new map<ID, ID>();
// Query for the Contact's active Campaigns. Sort CampaignMember by CreatedDate DESC so the Task gets assigned to the campaign to which contact was most recently added
for (CampaignMember cm:[select Id, CampaignId, ContactId, CreatedDate
from CampaignMember
where ContactId in :s_ContactIDs
AND Campaign.IsActive = TRUE
order by CreatedDate DESC
]) {
map_cID_to_camID.put(cm.ContactId, cm.CampaignId);
System.debug('ContactId - CampaignId:' + map_cId_to_camId);
}
/***************
* Process Records
***************/
for (Task t:l_Tasks) {
// If the Contact has a campaign mapped to it, update the Task with that campaign
if (map_cID_to_camID.get(t.WhoId) != null) {
t.WhatId = map_cID_to_camID.get(t.WhoId);
}
}
This works as intended in orgs where the Shared Activities feature has not been enabled: a task created from an Email-to-Salesforce email has the contact's most recent active campaign in the WhatId (label: "Related To") field.
In orgs with Shared Activities enabled, the code fails to do this and WhatId remains null. Research makes me think that the code needs to insert a TaskRelation object for each Task object, with values AccountId = cm.Contact.AccountId IsWhat = TRUE TaskId = Task.Id RelationId = cm.CampaignId.
Has anyone else experienced this issue of needing to insert or update TaskRelation objects in order to populate Task.WhatId through the API?”