Mar 7, 2011

How to Send More than 10 E-mails


Hi All,


This is about how to send more than 10 E-mails. As we know we have a governor limit of sending 10 emails in a process so this is a workaround to send more than E-mails. We can do this by using batch class.


Lets say we have to send all System Administrators details of case logged by them today in a particular format. If suppose we have 15 System Administrators in our organisation, all of them logged 2-3 cases in a day and in the end of the day we want to send the details of case logged only by them in an Email. So here is the code :

global class Batch_CaseEmail implements Database.Batchable<sObject>,Database.Stateful
{
   Map<Id , List<Case>> userCaseMap {get; set;}
   List<Case> allCaseLoggedToday {get; set;}
   
   global Batch_CaseEmail()
   {
       //Map to maintain user id and cases logged by them today
       userCaseMap = new Map<Id, List<Case>>() ;
       
       //All sales rep (System admins)
       List<User> salesRep = new List<User>() ;
       salesRep = [select id , name , Email , ManagerId from User where Profile.Name = 'System Administrator'] ;
       
       //All sales rep ids
       List<Id> salesIds = new List<Id>() ;
       for(User ur : salesRep)
       {
           salesIds.add(ur.Id) ;
       }
      
       //All cases logged today by sales rep
       allCaseLoggedToday = new List<Case>() ;
       allCaseLoggedToday = [select Id, CaseNumber,CreatedById, Owner.name , account.Name , contact.name from Case where CreatedDate = TODAY AND CreatedById in : salesIds] ;
   }

   global Database.QueryLocator start(Database.BatchableContext BC)
   {
      //Creating map of user id with cases logged today by them
      for(Case c : allCaseLoggedToday)
      {
          if(userCaseMap.containsKey(c.CreatedById))
          {
              //Fetch the list of case and add the new case in it
              List<Case> tempList = userCaseMap.get(c.CreatedById) ;
              tempList.add(c);
              //Putting the refreshed case list in map
              userCaseMap.put(c.CreatedById , tempList) ;
          }
          else
          {
              //Creating a list of case and outting it in map
              userCaseMap.put(c.CreatedById , new List<Case>{c}) ;
          }
      }

      //Batch on all system admins (sales rep)
      String query = 'select id , name , Email from User where Profile.Name = \'System Administrator\'';
      return Database.getQueryLocator(query);
   }

   global void execute(Database.BatchableContext BC, List<sObject> scope)
   {
       
      for(Sobject s : scope)
      {
          //Type cast sObject in user object
          User ur = (User)s ;
          
          //If system admin has logged any case today then only mail will be sent
          if(userCaseMap.containsKey(ur.Id))
          {
              //Fetching all cases logged by sys admin
              List<Case> allCasesOfSalesRep = userCaseMap.get(ur.Id) ;
              
              String body = '' ;
              //Creating tabular format for the case details
              body = BodyFormat(allCasesOfSalesRep) ;
              
              //Sending Mail
              Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage() ;
              
              //Setting user email in to address
              String[] toAddresses = new String[] {ur.Email} ;
              
              // Assign the addresses for the To and CC lists to the mail object
              mail.setToAddresses(toAddresses) ;
    
              //Email subject to be changed
              mail.setSubject('New Case Logged');
              
              //Body of email
              mail.setHtmlBody('Hi ' + ur.Name + ',<br/><br/> Details of Cases logged today is as follows : <br/><br/>' + body + '<br/> Thanks');
        
              //Sending the email
              Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
          }
      }
   }
   
   public String BodyFormat(List<Case> lst)
   {
       String str = '' ;
       for(Case cs : lst)
       {
           str += '<tr><td>'+ cs.CaseNumber +'</td>'+'<td>'+ cs.Owner.Name +'</td>'+'<td>'+ cs.Account.Name +'</td>'+'<td>'+ cs.Contact.Name +'</td>'+'</tr>' ;
       }
       str = str.replace('null' , '') ;
       String finalStr = '' ;
       finalStr = '<table border="1"> <td> CaseNumber </td> <td> Owner </td> <td> Account </td> <td> Contact </td> '+ str +'</table>' ;
       return finalStr ;
   }

   global void finish(Database.BatchableContext BC)
   {
   }

}


Now to execute this batch class we can schedule it or simply run this code in system logs for testing :

Batch_CaseEmail controller = new Batch_CaseEmail() ;
Integer batchSize = 1;
database.executebatch(controller , batchSize);



So when we execute it all system administrators will get E-mails in this format 






Thanks.

13 comments:

  1. Why not just send it to everyone at the same time e.g.

    String[] toAddresses = new String[] {'admin1@tquila.com', 'admin2@tquila.com', 'admin2@tquila.com'}

    This would then count as 1 email.

    ReplyDelete
  2. Body of each email is different and is according to the case logged in a day by each user.

    ReplyDelete
  3. Now question is what is the limit for sending emails per day. Then here it is :

    Limit for unlimited edition is 1000 email per day, professional edition is 250 and enterprise edition is 500.
    But if you are sending emails to internal users there is no limit on it.

    Here is some information I received from Salesforce on the daily email limit -

    What COUNTS towards the limit
    * Mass Emails to Contacts
    * Mass Email to Leads
    * Emails send via the API to email addresses
    * Emails send via the API to contacts (Both single and mass emails)
    * Emails send via API to Leads (both Single & Mass Emails)

    What DOES NOT COUNT towards the limit
    * Mass emails to Users
    * Emails via API to User ID’s
    * Emails send from the “Send Email” button on contacts (single emails/email author)
    * Emails send from the “Send Email” button on Leads (single emails/email author)
    * Workflow emails
    * System generated emails

    ReplyDelete
  4. Can I call the method which sends email multiple times to overcome this limitation?
    For eg: sendandAttach() is a method which sends email(content for each recipients is different). Now if I call this method multiple times will the limits still be effective?

    ReplyDelete
  5. I am not techy at all but am in the situation where I have been handed salesforce by our IT department to manage spontaenous volunteers in emergencies and natural disasters! Strange but true... We expect if this happens we will have several thousand people registered as 'customers' and will want to communicate by email with them all, but we have a 500 email limit. Do you know of any plug-ins we can use to by-pass this?

    ReplyDelete
    Replies
    1. This comment has been removed by a blog administrator.

      Delete
  6. Hey, Thanks for this nice code. I am very new to Salesforce. I want to use my templates. So please tell me how to fetch my templates and these templates are specific to the selection of radio buttons I have in a form.

    ReplyDelete
  7. Hi Ankit,

    I am working batch class but i am facing lost of issues. I am running batch class on 2 to 2.5lk records (records by query) in actual system i have 6-7lk records

    1. The query i have written in start method is taking too much time from preparing state to processing state.
    2. Some time i am getting this - "All attempts to execute message failed, message was put on dead message queue" exception.

    I have went through all salesforce docs. They suggest me to optimize query. below is my query.

    Code:

    String query = '';

    query = 'select AccountName,Id, AccountNumber, Type, Total_Balance__c from Account where Total_Balance__c !=0 and CreatedDate = LAST_N_DAYS:3' order by Id';

    System.debug('Enter into START');

    return Database.getQueryLocator(query);

    Thanks,
    Hitesh N. Patel

    ReplyDelete
  8. You wouldn't happen to have test code to go with this would you. Yep, I'm a newbie and it would be appreciated.

    ReplyDelete
  9. Thank you! The code to execute specifying a batch size is what I was missing.

    ReplyDelete
  10. Hi Ankit,

    I am facing issue with Mass Email for Leads.I have enterprise edition and trying to send Mass Email using 'Mass Email Leads' Option and limit is 500 emails but i am getting the error 'This mass email cannot be sent today as your daily limit has only 7 emails remaining. If you are going to send today go back and select 7 or fewer recipients. You may schedule this mailing for delivery at a future date.' .I don't understand the reason.
    I also tried to schedule for future date but getting error.

    Please help

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete