+ Start a Discussion
Medhanie Habte 37Medhanie Habte 37 

Bulkify a trigger to assign WhoId from an Email Message to a Task

Greetings, I've created this trigger which creates a task each time an email message is sent. Now I understand that may result in a duplicate task as email messages create tasks, but we wanted to figure a workaround that will allow creating tasks that can be populated on some custom fields and reports we have specific to a business process.

I feel good about what we have, but am wondering if there is a way to bulify the trigger by moving the SOQL query into a list, so I don't have to query within the trigger?
 

trigger EmailToTask on EmailMessage (after insert) {

    for (EmailMessage e : Trigger.new) {
       if (e.RelatedToId != NULL) {
       Task t =  new Task();
       t.ActivityDate  = date.today();
       t.Description   = e.TextBody;
       t.Move_Type__c  = 'Personal Note/Email from Donor';
       t.Priority      = 'Normal';
       t.Status        = 'Completed';
       t.Subject       = e.Subject;
       t.WhatId        = e.RelatedToId;
       t.WhoId		   = [SELECT Id FROM Contact WHERE Email = :e.ToAddress OR npe01__WorkEmail__c = :e.ToAddress OR npe01__HomeEmail__c = :e.ToAddress].Id;
       insert t;
    }
    }
    }
Best Answer chosen by Medhanie Habte 37
Medhanie Habte 37Medhanie Habte 37

No problem, I was able to bulkify my trigger by creating a list, then going for a map which based on the SOQL query prints the email address associated with a matching contact Id, querying for a home, work and preferred email address. I achieved 100% code coverage with it.
 
trigger EmailToTask on EmailMessage (after insert) {
    list<Task> lstTask          = new list<Task>();
    map<String,Id> mapEmail     = new map<String,Id>();
    
    for(Contact con: [SELECT Id,Email,npe01__WorkEmail__c,npe01__HomeEmail__c FROM Contact]){
        if(string.isNotBlank(con.Email))
            mapEmail.put(con.Email,con.Id);
        if(string.isNotBlank(con.npe01__WorkEmail__c))
            mapEmail.put(con.npe01__WorkEmail__c,con.Id);
        if(string.isNotBlank(con.npe01__HomeEmail__c))
			mapEmail.put(con.npe01__HomeEmail__c,con.Id);
    }

  for (EmailMessage e : Trigger.new) {
       if (e.RelatedToId != NULL 
	   && (mapEmail <> NULL && !mapEmail.isEmpty())
          ) {
           Task t =  new Task();
           t.ActivityDate  = date.today();
           t.Description   = e.TextBody;
           t.Move_Type__c  = 'Personal Note/Email from Donor';
           t.Priority      = 'Normal';
           t.Status        = 'Completed';
           t.Subject       = e.Subject;
           t.WhatId        = e.RelatedToId;
           if(mapEmail.containsKey(e.ToAddress)){
                t.WhoId = mapEmail.get(e.ToAddress);
           }     
           lstTask.add(t);
        }
    }
    if(lstTask <> NULL && !lstTask.isEmpty()){
        insert lstTask;
    }
}

 

All Answers

sukanya banekarsukanya banekar
Hi Medhanie,

You can add task in list and insert that list ouside for loop to make it bulkify. Also don't write query inside for loop
 
trigger EmailToTask on EmailMessage (after insert) {
    list<Task> lstTask= new list<Task>();
	map<String,Id> mapEmail = new map<String,Id>();
	map<String,Id> mapWorkEmail = new map<String,Id>();
    map<String,Id> mapHomeEmail = new map<String,Id>();	
	for(Contact con: [SELECT Id,Email,npe01__WorkEmail__c,npe01__HomeEmail__c FROM Contact]){
		if(string.valueOf(con.Email).isNotBlank)
			mapEmail.put(con.Email,con.Id);
		if(string.valueOf(con.npe01__WorkEmail__c).isNotBlank)
			mapWorkEmail.put(con.npe01__WorkEmail__c,con.Id);
		if(string.valueOf(con.npe01__HomeEmail__c).isNotBlank)
			mapHomeEmail.put(con.npe01__HomeEmail__c,con.Id);
	}

    for (EmailMessage e : Trigger.new) {
       if (e.RelatedToId != NULL 
	   && (mapEmail <> NULL && !mapEmail.isEmpty()
	       || mapWorkEmail <> NULL && !mapWorkEmail.isEmpty()
		   || mapHomeEmail <> NULL && !mapHomeEmail.isEmpty())
		   ) {
		   Task t =  new Task();
		   t.ActivityDate  = date.today();
		   t.Description   = e.TextBody;
		   t.Move_Type__c  = 'Personal Note/Email from Donor';
		   t.Priority      = 'Normal';
		   t.Status        = 'Completed';
		   t.Subject       = e.Subject;
		   t.WhatId        = e.RelatedToId;
		   if(mapEmail.containsKey(e.ToAddress)){
				t.WhoId =mapEmail.get(e.ToAddress);
		   }
		   else if(mapWorkEmail.containsKey(e.ToAddress )){
				t.WhoId =mapWorkEmail.get(e.ToAddress);
		   }
		   else if(mapHomeEmail.containsKey(e.ToAddress )){
				t.WhoId =mapHomeEmail.get(e.ToAddress);
		   }
		   lstTask.add(t);
		}
    }
	if(lstTask <> NULL && !lstTask.isEmpty()){
		insert lstTask;
	}
}
Let me know if you need any help.

Thanks,
Sukanya Banekar
Medhanie Habte 37Medhanie Habte 37
Hi there, Almost there, the only thing that's missing that I get this message "Initial term must be a concrete object string" around line 8.

    if(string.valueOf(con.Email).isNotBlank)
            mapEmail.put(con.Email,con.Id);

Is there anything else I should add.
Medhanie Habte 37Medhanie Habte 37
Ah I figured it out!

For if string, the .isNotBlank should be populated in string.IsNotBlank

Incorrect
 if(string.valueOf(con.Email).isNotBlank)
            mapEmail.put(con.Email,con.Id);

Correct 
if(string.isNotBlank(con.Email))
            mapEmail.put(con.Email,con.Id);
sukanya banekarsukanya banekar
Hi,
Yes, I didnot check with the syntax and just posted the answer.

 
Medhanie Habte 37Medhanie Habte 37

No problem, I was able to bulkify my trigger by creating a list, then going for a map which based on the SOQL query prints the email address associated with a matching contact Id, querying for a home, work and preferred email address. I achieved 100% code coverage with it.
 
trigger EmailToTask on EmailMessage (after insert) {
    list<Task> lstTask          = new list<Task>();
    map<String,Id> mapEmail     = new map<String,Id>();
    
    for(Contact con: [SELECT Id,Email,npe01__WorkEmail__c,npe01__HomeEmail__c FROM Contact]){
        if(string.isNotBlank(con.Email))
            mapEmail.put(con.Email,con.Id);
        if(string.isNotBlank(con.npe01__WorkEmail__c))
            mapEmail.put(con.npe01__WorkEmail__c,con.Id);
        if(string.isNotBlank(con.npe01__HomeEmail__c))
			mapEmail.put(con.npe01__HomeEmail__c,con.Id);
    }

  for (EmailMessage e : Trigger.new) {
       if (e.RelatedToId != NULL 
	   && (mapEmail <> NULL && !mapEmail.isEmpty())
          ) {
           Task t =  new Task();
           t.ActivityDate  = date.today();
           t.Description   = e.TextBody;
           t.Move_Type__c  = 'Personal Note/Email from Donor';
           t.Priority      = 'Normal';
           t.Status        = 'Completed';
           t.Subject       = e.Subject;
           t.WhatId        = e.RelatedToId;
           if(mapEmail.containsKey(e.ToAddress)){
                t.WhoId = mapEmail.get(e.ToAddress);
           }     
           lstTask.add(t);
        }
    }
    if(lstTask <> NULL && !lstTask.isEmpty()){
        insert lstTask;
    }
}

 
This was selected as the best answer