function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Michael MMichael M 

Email send class not working

Hello, I have a class that is supposed to send a VF template. The debug logs are saying it is sent, but the email is not going out. Can someone help to fix my email class? What am I missing? 

CLASS
Global class LeadOwnerEmail implements Schedulable{
 Global void execute(SchedulableContext SC) {
        
List<User> uList = [select id, email from user where id in (select  ownerid from community_lead__c)];    
List<Id> listids= new List<Id>();

for(User u :uList) {
 EmailTemplate et=[Select id from EmailTemplate where name = 'LeadOwnerEmail'];
 Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();     
mail.setTargetObjectId(u.id);
mail.setSenderDisplayName('Lead Ownership');
 mail.setTemplateId(et.id);
    mail.setSaveAsActivity(false);
 String[] toAddresses = new String[] {u.email};
mail.setToAddresses(toAddresses);
     system.debug('**To Addresses: ' + u.email);
//mail.setReplyTo(liaisonEmail);
       try { 
 Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
           system.debug('**SENT!!!');
   return;
    } catch (Exception e) {
    System.debug(e.getMessage());
   }
    }
}
}


VF EMAIL
<messaging:emailTemplate subject="Your Team's Leads- Owner Assignments" recipientType="User" relatedToType="User">

 <messaging:htmlEmailBody >
   Hi {!RelatedTo.firstName},
  <p>The following leads have not yet been updated:</p>
   <c:leadsinfo ToID="{!RelatedTo.Id}" />
 <p>To update these leads, click on the "Lead Status" field located  in the upper right on the lead page layout.</p>
 </messaging:htmlEmailBody>

</messaging:emailTemplate>
Best Answer chosen by Michael M
David Zhu 🔥David Zhu 🔥
Since your code invokes sendemail method in the loop, it hits governor limit. You need to batch it before sending.
In addition to that, soql query on Emailtemplate needs to move out of the loop as well.
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
EmailTemplate et=[Select id from EmailTemplate where name = 'LeadOwnerEmail'];

for(User u :uList) {
    
    Messaging.SingleEmailMessage  mail = new Messaging.SingleEmailMessage ();     
    mail.setTargetObjectId(u.id);
    mail.setSenderDisplayName('Lead Ownership');
    mail.setTemplateId(et.id);
    mail.setSaveAsActivity(false);
    // String[] toAddresses = new String[] {u.email};
    //mail.setToAddresses(listemails);
    system.debug('**To Addresses: ' + u.email);
    emails.add(mail);
    //mail.setReplyTo(liaisonEmail);
    
}

if (emails.size() > 0) {
    Messaging.sendEmail(emails,false);
    system.debug('**SENT!!!');
}

 

All Answers

David Zhu 🔥David Zhu 🔥
You may check the Access Level of Email Deliverability setting on your sandbox. It should be "All Email"
Michael MMichael M
Hi David, Deliverability is indeed set to "All Email". I figured out the problem- but this leads to a new problem :). The problem was my return; . So it stopped the loop after 1, when there are really 12 emails in this list. Now the problem is this error: "Line: 21, Column: 1
System.LimitException: Too many Email Invocations: 11". Any tips for what I can write in my code to fix this? 

Here's the current code:
Global class LeadOwnerEmail implements Schedulable{
 Global void execute(SchedulableContext SC) {
        
List<User> uList = [select id, email from user where id in (select  ownerid from community_lead__c)];    
List<Id> listids= new List<Id>();
List<string> listemails = new List<string>();     
     for (user uu : uList){
         listids.add(uu.id);
         listemails.add(uu.email);
     }
     
for(User u :uList) {
 EmailTemplate et=[Select id from EmailTemplate where name = 'LeadOwnerEmail'];
 Messaging.SingleEmailMessage  mail = new Messaging.SingleEmailMessage ();     
mail.setTargetObjectId(u.id);
mail.setSenderDisplayName('Lead Ownership');
 mail.setTemplateId(et.id);
    mail.setSaveAsActivity(false);
// String[] toAddresses = new String[] {u.email};
//mail.setToAddresses(listemails);
     system.debug('**To Addresses: ' + u.email);
//mail.setReplyTo(liaisonEmail);
       try { 
 Messaging.sendEmail(new Messaging.SingleEmailMessage [] { mail });
           system.debug('**SENT!!!');
  // return;
    } catch (Exception e) {
    System.debug(e.getMessage());
   }
    }
}
}
David Zhu 🔥David Zhu 🔥
Since your code invokes sendemail method in the loop, it hits governor limit. You need to batch it before sending.
In addition to that, soql query on Emailtemplate needs to move out of the loop as well.
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
EmailTemplate et=[Select id from EmailTemplate where name = 'LeadOwnerEmail'];

for(User u :uList) {
    
    Messaging.SingleEmailMessage  mail = new Messaging.SingleEmailMessage ();     
    mail.setTargetObjectId(u.id);
    mail.setSenderDisplayName('Lead Ownership');
    mail.setTemplateId(et.id);
    mail.setSaveAsActivity(false);
    // String[] toAddresses = new String[] {u.email};
    //mail.setToAddresses(listemails);
    system.debug('**To Addresses: ' + u.email);
    emails.add(mail);
    //mail.setReplyTo(liaisonEmail);
    
}

if (emails.size() > 0) {
    Messaging.sendEmail(emails,false);
    system.debug('**SENT!!!');
}

 
This was selected as the best answer
Michael MMichael M
Thans alot. I have never written a batch class before. Would you mind showing me what I need to add to my current code to batch it?
David Zhu 🔥David Zhu 🔥
I have put the code in my last reply. you may use it.
Michael MMichael M
I am still getting the same error: "System.LimitException: Too many Email Invocations: 11"

Global class LeadOwnerEmail implements Schedulable{
 Global void execute(SchedulableContext SC) {
        
List<User> uList = [select id, email from user where id in (select  ownerid from community_lead__c)];    
List<Id> listids= new List<Id>();
List<string> listemails = new List<string>();     
     for (user uu : uList){
         listids.add(uu.id);
         listemails.add(uu.email);
         
         List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
EmailTemplate et=[Select id from EmailTemplate where name = 'LeadOwnerEmail'];
for(User u :uList) {
    Messaging.SingleEmailMessage  mail = new Messaging.SingleEmailMessage ();    
    mail.setTargetObjectId(u.id);
    mail.setSenderDisplayName('Lead Ownership');
    mail.setTemplateId(et.id);
    mail.setSaveAsActivity(false);
    // String[] toAddresses = new String[] {u.email};
    //mail.setToAddresses(listemails);
    system.debug('**To Addresses: ' + u.email);
    emails.add(mail);
    //mail.setReplyTo(liaisonEmail)
if (emails.size() > 0) {
    Messaging.sendEmail(emails,false);
    system.debug('**SENT!!!');
}
}
     }
    }}
Herish SurendranHerish Surendran
Hi Michael. You have put a for loop inside a for loop. Thats why it is showing System.LimitException: Too many Email Invocations: 11.

I have done that change to your code.
Global class LeadOwnerEmail implements Schedulable{
		Global void execute(SchedulableContext SC) {
        
			List<User> uList = [select id, email from user where id in (select  ownerid from community_lead__c)];    
			List<Id> listids= new List<Id>();
			List<string> listemails = new List<string>();     
			for (user uu : uList){
				listids.add(uu.id);
				listemails.add(uu.email);
			}
			
			List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
			EmailTemplate et=[Select id from EmailTemplate where name = 'LeadOwnerEmail'];
			for(User u :uList) {
				Messaging.SingleEmailMessage  mail = new Messaging.SingleEmailMessage ();    
				mail.setTargetObjectId(u.id);
				mail.setSenderDisplayName('Lead Ownership');
				mail.setTemplateId(et.id);
				mail.setSaveAsActivity(false);
				// String[] toAddresses = new String[] {u.email};
				//mail.setToAddresses(listemails);
				system.debug('**To Addresses: ' + u.email);
				emails.add(mail);
				//mail.setReplyTo(liaisonEmail)
				if (emails.size() > 0) {
					Messaging.sendEmail(emails,false);
					system.debug('**SENT!!!');
				}
			}
     
    }
}
If this solves your question, mark this as solved.
 
Michael MMichael M
Hi Herish, Thank you very much for your insight. I udpated the code, and now it sent the email, however there are 2 issues:
1) It sends multiple emails per user. I only want it to send 1 email per user.
2) The chart on the VF Template is blank. When I test send the email from the VF template, the chart is full of data, but in these emails it is coming up blank. 

Any idea how I can fix these?
Herish SurendranHerish Surendran
Can you send the whole code of vf template
Michael MMichael M
Yes. The template calls a Component, which has Controller class. Here is all of that:\

VF TEMPLATE
<messaging:emailTemplate subject="Your Team's Leads- Owner Assignments" recipientType="User" relatedToType="User">
 <messaging:htmlEmailBody >
   Hi {!RelatedTo.firstName},
  <p>The following leads have not yet been updated:</p>
   <c:leadsinfo ToID="{!RelatedTo.Id}" />
 <p>To update these leads, click on the "Lead Status" field located  in the upper right on the lead page layout.</p>
 </messaging:htmlEmailBody>
</messaging:emailTemplate>

COMPONENT
(This is saved as leadsinfo.vfc)
<apex:component controller="LeadsInfoController" access="global">
    <apex:attribute name="ToID" type="ID" description="the lead owner ID" assignTo="{!salesRepID}"/>
     
        <apex:datatable value="{!InactiveLeads}" var="item" border="1">
                    <apex:column headervalue=" Name ">
                        <apex:outputText value="{!item.name}"/>
                    </apex:column>

                     <apex:column headervalue=" Created Date ">
                        <apex:outputText value="{!item.CreatedDate}"/>
                    </apex:column>
       </apex:datatable>
</apex:component>

CONTROLLER
public class LeadsInfoController {
  //capture the user id
    public ID salesRepID {get; set;}
    public List<community_lead__c> ClsInfo = new List<community_lead__c>();

    public List<community_lead__c> getInactiveLeads() {
        ClsInfo = [select Name, CreatedDate  from community_lead__c where  ownerId =: salesRepID];
        return ClsInfo;
    }
}
Michael MMichael M
Hey Herish, I found the problem: when I change this line of my SingleEmailMessage class, it worked:
            List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
            EmailTemplate et=[Select id from EmailTemplate where name = 'LeadOwnerEmail'];
            for(User u :uList) {
                Id userid = u.id;
                //Messaging.SingleEmailMessage  mail = new Messaging.SingleEmailMessage ();    
                 Messaging.SingleEmailMessage mail =   Messaging.renderStoredEmailTemplate(et.id, u.id, u.id);
Herish SurendranHerish Surendran
That's great. Just checking why the chart is not showing up in the mail.