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
Harjeet Singh 28Harjeet Singh 28 

Send an email to email address specified in email input field on VF page

Hi All,

I ahve created one input form where users can fill in their details and save records.The input form is a VF page and save record logic implemented in controller and everything works fine.
Now my issue is when the record is saved then an email should go to the email id specified in input form.This email id can be external also(not a salesforce user). If its a Salesforce user I can go with PB,Workflow rules/email alerts etc.
Below is my VF page
<apex:page standardController="Driver_Survey__c" extensions="GrabSurveyForDriverController" sidebar="false" lightningStylesheets="true">
    
    
    <apex:form > 
        
        <apex:pageBlock mode="edit" >
            <apex:pageBlockSection columns="1" collapsible="false" title="Driver Information"  >
                <apex:inputField label="Name" value="{!survey.Name__c}" required="true"/>
                <apex:inputField label="Mobile" value="{!survey.Mobile__c}" required="true" />
                <apex:inputField label="Email" value="{!survey.Email__c}" required="true" />
            </apex:pageBlockSection>

           
            <apex:pageBlockButtons >
             
                <apex:commandButton value="Save" action="{!doFullSave}"/>
                <apex:commandButton value="Cancel" action="{!doCancel}" immediate="true"/>
        
            </apex:pageBlockButtons> 
        </apex:pageBlock>
      
    </apex:form>
</apex:page>

Below is my controller
public class SurveyForDriverController{

    public Grab_Driver_Survey__c survey{get;set;}
     
    public SurveyForDriverController(ApexPages.StandardController controller){
         survey=new Driver_Survey__c();
       
    }
    
    public PageReference doFullSave(){
    
       	insert survey; 
        system.debug('message110>>'+survey );
        
      
        system.debug('message2>>'+survey );
        PageReference pageRef = new PageReference('/'+survey.Id);
        pageRef.setRedirect(true);
        return pageRef;
    }
    public PageReference doCancel(){
        PageReference pageRef = new PageReference('/');
            pageRef.setRedirect(true);
            return pageRef;
    }    
}

Below is screenshot of the vf page
User-added imageSo whatever email id specified in the Email field above will receive an email upon the record save.
On VF Page I am using input field for Email and at object level I have Text field as "Email" to store the value from VF page to object

Kindly help

Many thanks in advance​​​​​​​
Nubes Elite Technologies Pvt. LtdNubes Elite Technologies Pvt. Ltd
Hi Harjeet,

You can check the below code.

VF Code
<apex:inputField value="{! contact.firstname}"/> 
  <apex:inputField value="{! contact.lastname}"/>    
  <apex:inputField value="{! contact.Title}"/>
  <apex:inputField value="{! contact.email}"/>
  <apex:inputField value="{! contact.phone}"/>     
  <apex:inputField value="{!contact.MailingStreet}"/>
  <apex:pageBlockButtons location="bottom" >  
  <apex:commandbutton value="Submit" action="{!save}"/>
  </apex:pageBlockButtons>

Controller Part
Messaging.reserveSingleEmailCapacity(2);
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

String[] toAddresses = new String[] {  'abcd@gmail.com' };

mail.setToAddresses(toAddresses);  
mail.setReplyTo('xyz@yahoo.com');

mail.setSenderDisplayName('ABC');
mail.setSubject('Your upcoming shift with ABC');
mail.setBccSender(false);
mail.setPlainTextBody('Hi,I am sending a email');

And also create a new variable in your extension that holds the contact provided by the standard controller
 
public Contact c {get; set;}
public classname (standardController con) {
    c = con.getRecord();
    // It will show only the fields available on your page, for all other field you need to show you have to query as below. 
    // c = [SELECT Id, Email FROM Contact WHERE Id = :con.getRecord().Id];
}

Thank
http://www.nubeselite.
Development | Training | Consulting
​​​​​​​Please mark this as solution if your problem is resolved.
Harjeet Singh 28Harjeet Singh 28
Hi Nubes,

Thanks for your response.Actually I got the working solution from myself only.I am calling singlememailmessaging inside Save method and storing email id and loop through the same to send the email .

Currently I am looking a way to optimized the code in a way that I dont need to hardcode the text of email in controller

If you can help/guide me on same that would be great

Many thanks in advance
Khan AnasKhan Anas (Salesforce Developers) 
Hi Harjeet,

Greetings to you!

Please try the below code, I have tested in my org and it is working fine. Kindly modify the code as per your requirement.

Visualforce:
<apex:page standardController="Driver_Survey__c" extensions="GrabSurveyForDriverController" sidebar="false" lightningStylesheets="true">
    
    
    <apex:form > 
        
        <apex:pageBlock mode="edit" >
            <apex:pageBlockSection columns="1" collapsible="false" title="Driver Information"  >
                <apex:inputField label="Name" value="{!survey.Name__c}" required="true"/>
                <apex:inputField label="Mobile" value="{!survey.Mobile__c}" required="true" />
                <apex:inputField label="Email" value="{!survey.Email__c}" required="true" />
            </apex:pageBlockSection>
            
            
            <apex:pageBlockButtons >
                
                <apex:commandButton value="Save" action="{!doFullSave}"/>
                <apex:commandButton value="Cancel" action="{!doCancel}" immediate="true"/>
                
            </apex:pageBlockButtons> 
        </apex:pageBlock>
        
    </apex:form>
</apex:page>

Controller:
public class GrabSurveyForDriverController {
    
    public Driver_Survey__c survey{get;set;}
    
    public GrabSurveyForDriverController(ApexPages.StandardController controller){
        survey=new Driver_Survey__c();
        
    }
    
    public PageReference doFullSave(){
        
        insert survey; 
        system.debug('message110>>'+survey );
        
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.toAddresses = new String[] { survey.Email__c };
        mail.subject = 'Subject Test Message';
        mail.plainTextBody = 'This is a test mail';
        Messaging.SingleEmailMessage[] mailss =   new List<Messaging.SingleEmailMessage> {mail};
        Messaging.SendEmailResult[] results = Messaging.sendEmail(mailss);
        
        system.debug('message2>>'+survey );
        PageReference pageRef = new PageReference('/'+survey.Id);
        pageRef.setRedirect(true);
        return pageRef;
    }
    public PageReference doCancel(){
        PageReference pageRef = new PageReference('/');
        pageRef.setRedirect(true);
        return pageRef;
    }    
}

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Thanks and Regards,
Khan Anas
Nikhil SutharNikhil Suthar
Create a emailtTemplate for your email and directly use it as below code.
 "singleMailforadmin.setTreatTargetObjectAsRecipient(false);" :  in your case you have to set it false
List<EmailTemplate> emailTemplate= [
                                SELECT id 
                                FROM EmailTemplate 
                                WHERE DeveloperName = 'Your template name'
                                LIMIT 1
                ];
 List<Messaging.SingleEmailMessage> emails = new 
 List<Messaging.SingleEmailMessage>();
 
  for(Contact con : conList) {
Messaging.SingleEmailMessage singleMailforuser = new Messaging.SingleEmailMessage();
    singleMailforuser.setTargetObjectId(con.Id);
    singleMailforuser.setTemplateId(emailTemplateforuser[0].Id);
    singleMailforadmin.setTreatTargetObjectAsRecipient(false);    //set this to false for inserted email only
    singleMailforadmin.setToAddresses(toAddresses);
    emails.add(singleMailforadmin);
}
 Messaging.sendEmail(emails);

 
Harjeet Singh 28Harjeet Singh 28
Hi Anas,

Thanks for your response. I know the functionality of triggering an email using single email messaging.Actually fault from my side I ddidnt put my question in correct way. I am able to send an email to specified email id in form. What actually I am looking for is an optimised way to fetch the email template in some way so that there is no need of hardcoding the email content directly in controller
Harjeet Singh 28Harjeet Singh 28
Hi Nikhil,

Thanks for your response. I will certainly give it a try because your approach seems to create an email template and fetch the content from there rather hardcoding in controller. Once I give it a try and seems to be working I will let you know.
We should always thrive to optimise our solution and follow the best practices wherever possible

Many thanks in advance
Khan AnasKhan Anas (Salesforce Developers) 
Harjeet, If you are using a template you have to specify the Contact, Lead, or User to send the message to. This makes sure the template merges the correct fields in. You are not able to use the setToAddresses/toAddresses with a template, so the targetObjectId is needed. Only User, Contact, Lead, or Person objects are allowed for targetObjectId, but you are using custom object.

Instead, you can use something like this:
public class GrabSurveyForDriverController {
    
    public Driver_Survey__c survey{get;set;}
    
    public GrabSurveyForDriverController(ApexPages.StandardController controller){
        survey=new Driver_Survey__c();
        
    }
    
    public PageReference doFullSave(){
        
        insert survey; 
        system.debug('message110>>'+survey );
        
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.toAddresses = new String[] { survey.Email__c };
        mail.subject = 'Subject Test Message';
        //mail.plainTextBody = 'This is a test mail';
        String body = 'Please note: A new record has been saved with \n  ';
        body +='<br><br>';
        body += 'Name: '+ survey.Name + '<br><br>' ;
        body += 'Mobile: '+ survey.Mobile__c + '<br><br>';
        body += 'Email: '+  survey.Email__c;
        mail.setHtmlBody(body);
        Messaging.SingleEmailMessage[] mailss =   new List<Messaging.SingleEmailMessage> {mail};
        Messaging.SendEmailResult[] results = Messaging.sendEmail(mailss);
        
        system.debug('message2>>'+survey );
        PageReference pageRef = new PageReference('/'+survey.Id);
        pageRef.setRedirect(true);
        return pageRef;
    }
    public PageReference doCancel(){
        PageReference pageRef = new PageReference('/');
        pageRef.setRedirect(true);
        return pageRef;
    }    
}

Regards,
Khan Anas
Harjeet Singh 28Harjeet Singh 28
Hi Anas,

Thanks for highlighting the same. So according to you what I understood is I can't fetch email content from email template since I am using a custom object.Also the modified solution which you have provided is using main body with concatenated values as compared to plain text 

Many thanks in advance
Harjeet Singh 28Harjeet Singh 28
Hi Anas,

So basically the solution approach which Nikhil has suggested above will not work for me,right? As what I can understand from the Nikhil's approach and your comment above though we can query the template and use in apex but we need to specify targetObjectId and since I am dealing with a custom object this approach doesn't fit in my situation in order to optimised code,right?

Kindly clarify my doubts which will help me to understand the concept more and also help me in designing an optimised solution with Salesforce best practices

Many thanks in advance
Khan AnasKhan Anas (Salesforce Developers) 
setTargetObjectId is required if using a template, optional otherwise. This is the ID of the contact, lead, or user to which the email will be sent. The ID you specify sets the context and ensures that merge fields in the template contain the correct data.

However, you can use the setTreatTargetObjectAsRecipient: If set to false, thetargetObjectId is supplied as the WhoId field for template rendering but isn’t a recipient of the email. The default is true: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_email_outbound_single.htm
 
public class GrabSurveyForDriverController {
    
    public Driver_Survey__c survey{get;set;}
    
    public GrabSurveyForDriverController(ApexPages.StandardController controller){
        survey=new Driver_Survey__c();
        
    }
    
    public PageReference doFullSave(){
        
        insert survey; 
        system.debug('message110>>'+survey );
        
        EmailTemplate et=[SELECT Id FROM EmailTemplate WHERE developername = 'Template_Name' LIMIT 1]; 
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.subject = 'Subject Test Message';
        mail.setToAddresses( new List < String > { survey.Email__c } );  
        mail.setTreatTargetObjectAsRecipient( false );  
        mail.setTemplateId(et.id); 

        /*The ID of the contact, lead, or user*/  
        mail.setTargetObjectId( UserInfo.getUserId() );  

        Messaging.SingleEmailMessage[] mailss =   new List<Messaging.SingleEmailMessage> {mail};
        Messaging.SendEmailResult[] results = Messaging.sendEmail(mailss);
        
        system.debug('message2>>'+survey );
        PageReference pageRef = new PageReference('/'+survey.Id);
        pageRef.setRedirect(true);
        return pageRef;
    }
    public PageReference doCancel(){
        PageReference pageRef = new PageReference('/');
        pageRef.setRedirect(true);
        return pageRef;
    }    
}

I hope it helps you!
Harjeet Singh 28Harjeet Singh 28
Hi Anas,

I just tried your approach as mentioned above.
1. Created one email template for my custom object
2. Reused the code as pecified by you above
I am receiving email with just "subject ",the body of the email as pecified in email template is not appearing.Is reason? or did I miss anything on same?

Many thanks in advance
Nikhil SutharNikhil Suthar
Hi Harjeet,
Did u checked the checkbox Available for use?
please check it.
Harjeet Singh 28Harjeet Singh 28
Hi Nikhil,

Yes I checked the checkbox Available for Use.
I can see the subject but body is blank
Nikhil SutharNikhil Suthar
Hi Harjeet,

What code you used can you post that?
Harjeet Singh 28Harjeet Singh 28
Hi Nikhil,

Below is the code
insert survey; 
        system.debug('message110>>'+survey );
        
        EmailTemplate et=[SELECT Id FROM EmailTemplate WHERE developername = 'TestEmailTemplate' LIMIT 1]; 
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.subject = 'Subject Test Message';
        mail.setToAddresses( new List < String > { survey.Email__c } );  
        mail.setTreatTargetObjectAsRecipient( false );  
        mail.setTemplateId(et.id); 


        mail.setTargetObjectId( UserInfo.getUserId() );  

        Messaging.SingleEmailMessage[] mailss =   new List<Messaging.SingleEmailMessage> {mail};
        Messaging.SendEmailResult[] results = Messaging.sendEmail(mailss);
        
        system.debug('message2>>'+survey );
        PageReference pageRef = new PageReference('/'+survey.Id);
        pageRef.setRedirect(true);
        return pageRef;

The above mentioned code will excute behind Save method and created one Email Template as "TestEmailTemplate" of text type
Nikhil SutharNikhil Suthar
Hi Harjeet, 
When you are using email template you dont have to specify subject of email in code it's already specified in template.
Edit your code like below
String[] toAddress = survey.Email__c;  
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
EmailTemplate et=[SELECT Id FROM EmailTemplate WHERE developername = 'TestEmailTemplate' LIMIT 1]; 
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
		mail.setToAddresses(toAddress);
		mail.setTemplateId(et.id);
		mail.setTargetObjectId( UserInfo.getUserId());
		mail.setTreatTargetObjectAsRecipient( false );
		emails.add(mail);
		
		Messaging.sendEmail(emails); // this will send email

 
Harjeet Singh 28Harjeet Singh 28
Hi Nikhil,

I got your point.I tested again with the revised code and found that the text are coming but the merge field values are not coming
My email template looks like
Please note: A new record has been saved with 
{!Driver_Survey__c.Name__c} 
{!Driver_Survey__c.Email__c} 
{!Driver_Survey__c.Mobile__c}
 and the email which I received looks like
Please note: A new record has been saved with

Merge field values are not populating
 
Nikhil SutharNikhil Suthar
Hi harjeet,
But this time you got your email body in email. (This was your problem)
 
Nikhil SutharNikhil Suthar
And as for you are not getting values in body because you are not getting that values from page.
You are not assigning values of your fields in controller.
Solution:
1.Create wrapper class with fields(use get;set;)
2.initiate survey and assign data that you got from page then use insert 
It should work.