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
VamsiVamsi 

Hi , I have a Email manager class in apex to send an email and when i call the method from the developer console it executes but dont send any email can someone please help me with this

Email manager class 

public class EmailManager {

    public void sendMail(string Address,string subject, string body)
    {
    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
    string [] toaddress = new string[]{address};
    email.setToAddresses(toaddress);
    email.setSubject(subject);
    email.setPlainTextBody(body);
    }
}


developer console 
EmailManager e = new EmailManager();
e.sendMail('xxx@domain.com','test email', 'test apex');
Best Answer chosen by Vamsi
Agustina GarciaAgustina Garcia
Hi,

Your code is fine. The only thing that is left is the sending action. Please add this line at the end of your sendMail method:
 
Messaging.sendEmail( new Messaging.SingleEmailMessage[] { email } );

Not it should work. 

Another advice. There is a limitation about the max number of emails that can be sent a day. You an avoid this limitation just doing this:
 
public class EmailManager {

    public void sendMail(Id userId, String Address,string subject, string body)
    {
       Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
       string [] toaddress = new string[]{address};
       
       //email.setToAddresses(toaddress);

        //Avoid to hit the max number of emails
        mail.saveAsActivity = false;
        mail.setTargetObjectId(userId);
    
       email.setSubject(subject);
       email.setPlainTextBody(body);

       Messaging.sendEmail( new Messaging.SingleEmailMessage[] { email } );
    }
}

Hope this helps.
 

All Answers

Anirudh SinghAnirudh Singh
Hi Vamshi,

In your class, you need to invoke sendEmail method of Messaging Class.

I have corrected the code and it will work fine. I have highlighted the changes I made in bold.
Please find below the code:
public class EmailManager
{
    public void sendMail(string Address, string subject, string body)
    {
        List<Messaging.SingleEmailMessage> singleEmailMessagesList=new List<Messaging.SingleEmailMessage>();
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        List<string> toaddress = new List<string>{address};
        email.setToAddresses(toaddress);
        email.setSubject(subject);
        email.setPlainTextBody(body);
        singleEmailMessagesList.add(email);
        
        Messaging.sendEmail(singleEmailMessagesList);
    }
}

Please let me know if this helps.
If yes, please mark the Question as Solved.


Thanks and Regards,
Anirudh Singh
Agustina GarciaAgustina Garcia
Hi,

Your code is fine. The only thing that is left is the sending action. Please add this line at the end of your sendMail method:
 
Messaging.sendEmail( new Messaging.SingleEmailMessage[] { email } );

Not it should work. 

Another advice. There is a limitation about the max number of emails that can be sent a day. You an avoid this limitation just doing this:
 
public class EmailManager {

    public void sendMail(Id userId, String Address,string subject, string body)
    {
       Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
       string [] toaddress = new string[]{address};
       
       //email.setToAddresses(toaddress);

        //Avoid to hit the max number of emails
        mail.saveAsActivity = false;
        mail.setTargetObjectId(userId);
    
       email.setSubject(subject);
       email.setPlainTextBody(body);

       Messaging.sendEmail( new Messaging.SingleEmailMessage[] { email } );
    }
}

Hope this helps.
 
This was selected as the best answer
Agustina GarciaAgustina Garcia
Sorry, copy - paste error. The 2 new lines I added, they should be:
 
email.saveAsActivity = false;
email.setTargetObjectId(userId);

instead of 
 
mail.saveAsActivity = false;
mail.setTargetObjectId(userId);

 
VamsiVamsi
Thanks Agustina, Its working now !!!!
VamsiVamsi
Hi  Anirudh, By using your code it throws an error at line 13 invalid method exists.
Anirudh SinghAnirudh Singh
Hi Vamshi,

I have tested the code and it is working fine. Have you used the whole code?

Thanks and Regards,
Anirudh Singh
VamsiVamsi
Hi,

I have a trigger which sends an email to each contact when an account is updated. So if the setToAddressess (emailid )is having a blank value then I need to through an error. How can I achieve this.

Thanks in advance .....!!!!!!!!!!1
 
Agustina GarciaAgustina Garcia
From where do you get the emailId for setToAddressess? I would guess they are Contact email field right?

If you are in a trigger, I would check the emailId and in the case this is null, I will store Contact information somehow. Then, at the end of the process apart from having sent email to all contacts after the update, I would send another email to the administrator with the Contacts names that didn't receive any notification because email was blank.

But this is my advice, rather than stop the account update process.
 
VamsiVamsi
Yep, right. Thanks, But i was trying to use the adderror method and its throwing me an error.
Agustina GarciaAgustina Garcia
You can always do:
 
Set<ID> emailValues = new Set<ID>();
for(Account a : Trigger.new)
{
      //Check contact's email value
      if(emailValue != null)
         emailValues.add(emailValue);
      if(emailValue == null)
         a.addError('Email value is empty');
}

//At the end of the trigger
sendEmails(emailValues); //So you would only send a single email to many people
But this has 2 issue:
  1. As you are using the setToAddress method you can hit governors, so take care
  2. If there is a single failure, the process will stop and if the rest of Contact have the information right, they would not recive email.
VamsiVamsi
Thanks for the information Agustina.

But is their any limit to the number of emails sent using singleemailmessage class . Becasuse initially i started hitting  error SINGLE_EMAIL_LIMIT_EXCEEDED, Failed to send email: [] after some emails. But when I add your below code 

1 email.saveAsActivity = false;
2 email.setTargetObjectId(userId);

it solved the Issue. Could you please let me know the difference
VamsiVamsi
Thanks for the information Agustina.

But is their any limit to the number of emails sent using singleemailmessage class . Becasuse initially i started hitting  error SINGLE_EMAIL_LIMIT_EXCEEDED, Failed to send email: [] after some emails. But when I add your below code 

1 email.saveAsActivity = false;
2 email.setTargetObjectId(userId);

it solved the Issue. Could you please let me know the difference
Agustina GarciaAgustina Garcia
Sorry, my fault. I was thinking on Contact Email address that is a string and there is no other way to use it rather than using setToAddresses method where you have to pass a List of emails. 

If you have the contactId and it would be linked somehow with an email, then you can se setTargetObjectId method and avoid hitting max number of emails per day.

But if you do it in this way, you can only send emails inside of a loop, a single email call per Id because setToAddress doesn't allow a list.
VamsiVamsi
Could you please verify that the below code is correct or does it require any modifications. It sends out an email to all contacts when its account is updated.

trigger NotifyEmail on Account (before update)
{

 list<account> acc = [select ID,Email__c,(select Email,AccountID from contacts) from Account where ID IN : trigger.new];
    
    for(account c :acc)
    {
        if(c.contacts.size()>0)
        {
            for(contact cc : c.contacts)
            {
       
                    if(cc.AccountID == c.ID && cc.Email!=null)
                    {
        
                string[] st = new string[]{};
                st.add(cc.Email);
                Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
                message.setToAddresses(st);
                message.setSubject('Testing contact email');
                message.saveAsActivity = false;
                 message.setTargetObjectId(userinfo.getUserId());
                message.setPlainTextBody('contact email success');
                   Messaging.sendEmail(new Messaging.SingleEmailMessage[] {message});
                       }
                
            }
        } 
        else
         {
                           if(c.Email__c!=null)
                        {
                        string[] str= new string[]{};
                           str.add(c.Email__c);
                           Messaging.SingleEmailMessage messages = new Messaging.SingleEmailMessage();
                        messages.setToAddresses(str);
                      messages.saveAsActivity = false;
                     messages.setTargetObjectId(userinfo.getUserId());
                          messages.setSubject('Testing account email');
                        messages.setPlainTextBody('account email success');
                            Messaging.sendEmail(new Messaging.SingleEmailMessage[] {messages});      
           
                        }
          }
    }
}
Agustina GarciaAgustina Garcia
Instead of calling same piece of code inside the loop, I would really recommend to save a List with all c.Email__c that you want to use and just make a single call to the piece of code that send emails
 
trigger NotifyEmail on Account (before update)
{

List<String> emails1 = new List<String>();
List<String> emails2 = new List<String>();

 list<account> acc = [select ID,Email__c,(select Email,AccountID from contacts) from Account where ID IN : trigger.new];
    
    for(account c :acc)
    {
        if(c.contacts.size()>0)
        {
            for(contact cc : c.contacts)
            {
       
                    if(cc.AccountID == c.ID && cc.Email!=null)
                    {
                         emails1.add(cc.EmailL);
                    }
            }
        } 
        else
         {
                        if(c.Email__c!=null)
                        {
                             emails2.add(c.Email__c);
                        }
          }
    }

    if(emails1 != null && emails1.size() > 0)
    {
        Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
        message.setToAddresses(emails1);
        message.setSubject('Testing contact email');
        message.saveAsActivity = false;
        message.setTargetObjectId(userinfo.getUserId());
        message.setPlainTextBody('contact email success');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {message});
    }

    if(emails2 != null && emails2.size() > 0)
    {
        Messaging.SingleEmailMessage messages = new Messaging.SingleEmailMessage();
        messages.setToAddresses(emails2);
        messages.saveAsActivity = false;
        messages.setTargetObjectId(userinfo.getUserId());
        messages.setSubject('Testing account email');
        messages.setPlainTextBody('account email success');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {messages});
    }
}

I'm afrid that 
 
message.setToAddresses(<yourlist>);

line could make you hit max number of emails per day.



 
VamsiVamsi
Thanks for the valuable advises Agustina.....!!!!!. So is their any best way to achieve this scenario without hitting the limit for number of emails. 

I guess is the batch apex the only way to achieve this scenario without hitting the email limit per day.
Agustina GarciaAgustina Garcia
As far as I know a batch apex would not fix this issue. This is a limitation that is not under "governor limits". It is like the max number of callouts you can make a day.

I would ask myself
  1. How many contacts do I have? Could they be also users? If so, you can use "message.setTargetObjectId(contactUser.Id);" and not hit the limit per day. But I would guess that you don't want to have as many users as contacts, so probably this solution is not the best one.
  2. Do I really need to send emails to all these people every time I update an account? Imagine you update 100 accounts a day .... if I were a contact, I would not like to be spammed. Maybe you can save in a temporal object those contacts that should receive the email and the account that would trigger the email. And at the end of the day send a single email to each contact with the information of all the accounts that have been updated and are related to him. For instance, Contact1 will receive an email with information about Account1. And Contact2 will receive an email with information about Account1, Account2 and Account20. This would save some emails. Contact2 will receive 1 email instead of 3.
  3. Although 2nd option is better, you could still hit the number of emails per day. Another option is to try to send emails via Workflow instead of code. Look at the explanation on stackExchange (http://salesforce.stackexchange.com/questions/5376/how-can-you-avoid-hitting-24-hour-limits-on-emails-and-future-calls) (the one below the answer) 
Hope this helps
Agustina

 
Chetan KapaniaChetan Kapania
Hi Agustina Garcia,

Could you help with test class for above mention Email Manager code for testing purpose. 

Regards
Chetan Kapania
Agustina GarciaAgustina Garcia
Hi Chetna,

I'm afraid that you cannot test if an email has been sent. There is no way to see it. However you can always cover the code. Imagine that you have a method that ends calling your EmailManager. Then, if you make a call to the method, the EmailManager would be also referenced and lines would be covered.

Hope it helps
Agustina
Kingslee VeluKingslee Velu
Folks,

I have below code to send email but i didnt get the email in by inbox. Can you guys please advise me on the issue in below code snippet ?

public with sharing class EmailManager {
    public void sendMail(String [] addresses, String [] subjects, String [] messages)
    {
        Messaging.SingleEmailMessage [] emails = new Messaging.SingleEmailMessage [] {};
            Integer totalMails = addresses.size();
        for(Integer i=0; i < totalMails; i++){
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage ();
            email.setSubject(subjects[i]);
            email.setToAddresses(new List<String> {addresses[i]});
            email.setPlainTextBody(messages[i]);
            emails.add(email);
        }
        Messaging.sendEmail(emails);
        
    }
}

String address = 'XXX@yahoo.com';
String subject = 'Speaker Confirmation';
String body = 'Thank You for Speaking at the Conference';
string [] addresses = new String [] {},
          subjects = new string [] {},
          messages = new string [] {};
addresses.add(address);
subjects.add(subject);
messages.add(body);
EmailManager em =new EmailManager();
em.sendMail(addresses, subjects, messages);