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
SFDC Admin 14SFDC Admin 14 

Anyone made a Visualforce page of the Send Email page from Tasks?

I am trying to find a way to send emails from Salesforce1 and I think the only way might be to make a VF page of the Send Email page.  I need to be able to use email templates and preview it.
Brenda S FinnBrenda S Finn
We have done something similar to what you are requesting, however we did not test it for Salesforce1. We dummied down the standard functionality in the following way. Related To picklist allows user to select Object to which Email is related. We removed this and automatically associate Email with Case which was all we required for our Use Case. We still supported Attachments - done slightly differently and also did not have lookup fields for Additional To, BCC, CC fields. We also set the From field - we do not want them to be able to update it themselves, but that can be changed if it does not meet your requirements. Please let me know if this is helpful.

Here is the basic VF page
<apex:page standardController="Case" extensions="SendCaseEmailController" action="{!populateTemplate}">
    <apex:sectionHeader title="Task" subtitle="Send an Email"/>

    <style>
        .boldText {
            font-weight:bold;
        }
        .labelText {
            font-weight:bold;
            display:inline-block;
            text-align:right;
            width:100px;
        }
        .wideTextArea {
            width:400px;
        }
        .mediumTextField {
            width:200px;
        }
        .longTextField {
            width:400px;
        }
        .extraDeepTextArea {
            width:550px;
            height:200px;
        }

    </style>
    <apex:form>
        <div style="display:none">
            <apex:inputField value='{!Case.Subject}'/>
        </div>
        <apex:pageBlock id="dataSection">
            <apex:pageMessages id="pageMessages" />
            <apex:pageBlockButtons >
                <apex:commandButton value="Send" action="{!send}"/>
                <apex:commandButton value="Cancel" action="{!cancel}" immediate="true" />
            </apex:pageBlockButtons>            
   
            <apex:pageBlockSection title="Edit Email">
                <apex:panelGrid columns="2" cellpadding="5%" cellspacing="5%">
                    <apex:outputLabel styleClass="labelText">To</apex:outputLabel>
                    <apex:inputText id="idRecipient" styleClass="longTextField" required="true"
                        value="{!emailMsg.ToAddress}"/>

                    <apex:outputLabel styleClass="labelText">From</apex:outputLabel>
                    <apex:outputLabel id="idSender" value="{!emailMsg.FromAddress}"
                        styleClass="longTextField"/>

                    <apex:outputLabel styleClass="labelText">Related To</apex:outputLabel>
                    <apex:outputField value="{!emailMsg.Subject}"/>

                    <apex:outputLabel styleClass="labelText">Additional To:</apex:outputLabel>
                    <apex:inputTextarea id="idAddlRecipients" styleClass="wideTextArea"                         value="{!addlRecipients}"/>

                    <apex:outputLabel styleClass="labelText">CC:</apex:outputLabel>
                    <apex:inputTextarea id="idCcRecipients" styleClass="wideTextArea"                       
                        value="{!emailMsg.CcAddress}"/>

                    <apex:outputLabel styleClass="labelText">BCC:</apex:outputLabel>
                    <apex:inputTextarea id="idBccRecipients" styleClass="wideTextArea"                      
                        value="{!emailMsg.BccAddress}"/>

                    <apex:outputLabel styleClass="labelText">Subject:</apex:outputLabel>
                    <apex:inputText id="idSubject" required="true" styleClass="longTextField" 
                        value="{!emailMsg.Subject}"/>

                    <apex:outputLabel styleClass="labelText">Attach File</apex:outputLabel>
                    <apex:inputFile value="{!attachment.body}" filename="{!attachment.name}"/>

                    <apex:outputLabel styleClass="labelText">Body:</apex:outputLabel>
                    <apex:inputTextarea id="idBody" styleClass="extraDeepTextArea" 
                        value="{!emailMsg.TextBody}"/>

                </apex:panelGrid>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>


Here is the Controller 
/*
** Class:  SendCaseEmailController
** Created by XYZ on 03/20/2015
** Description: Controller for the SendCaseEmail custom Visual Force page. 
*/
public with sharing class SendCaseEmailController {

    public String addlRecipients {get; set;}
    public Case   ourCase {get; set;}
    public EmailMessage emailMsg {get; private set;}

    private OrgWideEmailAddress sender = null;

    private static final String SUPPORT_EMAIL_ADDRESS = 'support@somewhere.com';
    private static final String SUPPORT_NAME = 'Support Email';

    public SendCaseEmailController(ApexPages.StandardController controller) {
        ourCase = (Case)controller.getRecord();

        // create our EmailMessage 
        emailMsg = new EmailMessage();

        // get our org-wide email address to set from/sender field
        sender = [select Id from OrgWideEmailAddress where DisplayName = :SUPPORT_NAME];
    }

    public Attachment attachment {
        get {
            if (attachment==null) {
                System.debug('==========> creating new empty Attachment.');
                attachment = new Attachment();
            }
            return attachment;
        }
        set;
    }

    // send email message per the attributes specified by user.
    public PageReference send() {
        try {
            // now create our SingleEmailMessage to send out.
            Messaging.SingleEmailMessage singleEmailMsg = new Messaging.SingleEmailMessage();

            // concatenate all Bcc Addresses
            if (emailMsg.BccAddress != null && emailMsg.BccAddress != '') {
                singleEmailMsg.setBccAddresses(emailMsg.BccAddress.split(';'));
            }

            // concatenate all CC Addresses
            if (emailMsg.CcAddress != null && emailMsg.CcAddress != '') {
                singleEmailMsg.setCcAddresses(emailMsg.CcAddress.split(';'));
            }
            singleEmailMsg.setOrgWideEmailAddressId(sender.Id); 

            singleEmailMsg.setSubject(emailMsg.Subject);
            singleEmailMsg.setPlainTextBody(emailMsg.TextBody);

            // now add additional recipients
            String[] addlToAddresses = null;
            if (addlRecipients != null && addlRecipients != '') {
                addlToAddresses = addlRecipients.split(';');
            }
            // now lets add any additional recipients to our list of recipients.
            List<String> lstToAddresses = null;
            if (addlToAddresses != null) {
                // now append these to our main recipient.
                lstToAddresses = new List<String>(addlToAddresses);
            } else {
                lstToAddresses = new List<String>();
            }
            lstToAddresses.add(emailMsg.ToAddress);
            singleEmailMsg.setToAddresses(lstToAddresses); 

            // now we need to reset the ToAddress for our EmailMessage.
            emailMsg.ToAddress += (addlRecipients != null ? ';' + addlRecipients : '');

            // now attach file to email if there is one. Have to check the Body as Attachment
            // itself will never be null as it is always created first time it is accessed.
            if (attachment.Body != null) {
                Messaging.EmailFileAttachment emailAttachment = new Messaging.EmailFileAttachment();
                emailAttachment.setBody(attachment.Body);
                emailAttachment.setFileName(attachment.Name);
                singleEmailMsg.setFileAttachments(new List<Messaging.EmailFileAttachment> {emailAttachment});
            }
            List<Messaging.SendEmailResult> results =  Messaging.sendEmail(
                new List<Messaging.SingleEmailMessage> {singleEmailMsg});

            // now parse  our results
            // on success, return to calling page - Case view.
            if (results[0].success) {
                // now insert EmailMessage into database so it is associated with Case.
                insert emailMsg;
                // and insert attachment into database as well, associating it with our emailMessage
                if (attachment.Body != null) {
                    attachment.parentId=emailMsg.Id;
                    insert attachment;
                }

                PageReference pgRef = new PageReference('/' + ourCase.Id);
                pgRef.setRedirect(true);
                return pgRef;
            } else {
                // on failure, display error message on existing page so return null to return there.
                String errorMsg = 'Error sending Email Message. Details = ' + results.get(0).getErrors()[0].getMessage();
                System.debug('==========> ' + errorMsg);
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, errorMsg));
                return null;
            }
        }
        catch (Exception e) {
            // on failure, display error message on existing page so return null to return there.
            String errorMsg = 'Exception thrown trying to send Email Message. Details = ' + e;
            System.debug('==========> ' + errorMsg);
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, errorMsg));
            return null;
        }

        return null;
    }

    // cancel creation of emailMessage. 
    public PageReference cancel() {
        // no need to do anything - just return to calling page.
        PageReference pgRef = new PageReference('/' + ourCase.Id);
        pgRef.setRedirect(true);
        return pgRef;
    }

    // populate our Email Message Template from the database, filling merge fields with
    // values from our Case object. Then store resulting template in EmailMessage for
    // display to end-user who is free to edit it before sending.
    public PageReference populateTemplate() {
        // we need to perform the merge for this email template before displaying to end-user.

        EmailTemplate emailTemplate = [select Body, HtmlValue, Subject, DeveloperName, BrandTemplateId 
            from EmailTemplate where DeveloperName='EMAIL_TEMPLATE_NAME' limit 1];

        // construct dummy email to have Salesforce merge BrandTemplate (HTML letterhead) with our email
        Messaging.SingleEmailMessage dummyEmailMsg = new Messaging.SingleEmailMessage();
        dummyEmailMsg.setTemplateId(emailTemplate.Id);
        // This ensures that sending this email is not saved as an activity for the targetObjectId. 
        dummyEmailMsg.setSaveAsActivity(false);

        // send dummy email to populate HTML letterhead in our EmailMessage object's html body.
        String[] toAddresses = new String[]{YOUR_RECIPIENT_EMAIL_ADDRESS};
        dummyEmailMsg.setToAddresses(toAddresses);
        dummyEmailMsg.setReplyTo(SUPPORT_EMAIL_ADDRESS); 
        
        // now send email and then roll it back but invocation of sendEmail() 
        // means merge of letterhead & body is done

        // TargetObject is User. This tells the emailMsg to use the email message
        // associated with our dummy User. This is necessary so we can populate our
        // email message body & subject with merge fields from template
        Savepoint sp = Database.setSavepoint();

        Account dummyAcct = new Account(Name='dummy account');
        insert dummyAcct;
        
        Contact dummyContact        = new Contact(AccountId=dummyAcct.Id);
        dummyContact.FirstName      = 'First';
        dummyContact.LastName       = 'Last';
        dummyContact.Email          = 'nobody@nowhere.com';
        insert dummyContact;

        dummyEmailMsg.setTargetObjectId(dummyContact.Id);
        dummyEmailMsg.setWhatId(ourCase.Id);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {dummyEmailMsg});
        // now rollback our changes.
        Database.rollback(sp);

        // now populate our fields with values from SingleEmailMessage.
        emailMsg.BccAddress  = UserInfo.getUserEmail();
        emailMsg.Subject     = dummyEmailMsg.getSubject();
        emailMsg.TextBody    = dummyEmailMsg.getPlainTextBody();
        emailMsg.ToAddress   = dummyEmailMsg.getToAddresses().get(0);
        emailMsg.FromAddress = SUPPORT_EMAIL_ADDRESS; 
        emailMsg.CcAddress   = '';
        emailMsg.ParentId    = ourCase.Id;
        return null;
    }
}


 
Carmen KraemerCarmen Kraemer
Thank you! Just found your code and it just saved me a lot of time!!!
John Croson 5John Croson 5
You wouldn't happen to have unit testing for this class, would you?

TIA!!
John Croson 5John Croson 5
This is as much as I've been able to come up with, and it only covers 70% of this code. I can only guess at this point I need to assert that there are fields populated with data in some way so that the checks for null values in the emailMsg variable in the class actually result in an email:
 
@isTest
public class TestSendSupportActivityEmailController {
    
    /*

Name: TestSendSupportActivityEmailController
Author/Date: John Croson 9/27/2016
Purpose: Unit test to cover SendSupportActivityEmailController
Change History Date: 

*/
    
    static testMethod void mySupportActivityEmail() {
        
        // Create the heirarchy of objects
        // starting with Account
        Account a = new Account(
            Name = 'Test Account', BillingCity = 'Hartland', BillingState = 'Wisconsin', BillingCountry = 'United States', 
            BillingPostalCode = '55009', BillingStreet = '1234 First St.', Has_Dashboards__c = true);
        insert a;
        
        // Then the contact
        Contact con = new Contact(
            FirstName = 'Unit', LastName = 'Test', Email = 'noN@non.com', AccountId = a.Id);
        insert con;
       
        // Then the case
        Case c = new Case(
            AccountId = a.Id, Subject = 'Unit Test', Description = 'Unit Test', Priority = 'Medium', Status = 'Logged', 
            Complaint_Type__c = 'No Allegation Made', Medical_Device__c = 'Yes', Origin = 'Portal', ContactId = con.Id);
        insert c;

        // Go to our page
        PageReference pageRef = Page.SendSupportActivityEmail;
        
        // Create the controller
        SendSupportActivityEmailController controller = new SendSupportActivityEmailController(new ApexPages.StandardController(c));
   
        
        // send the email
        pageRef = controller.send();
        
        // call the template
        pageRef = controller.populateTemplate(); 
        
        // cancel it
        pageRef = controller.cancel();

    }        
}

 
John Croson 5John Croson 5
Found by flipping the order of the method calls to this increased my code coverage by another 11%.
 
// call the template
        pageRef = controller.populateTemplate();
        
        // send the email
        pageRef = controller.send();

 
Jos Vervoorn 2Jos Vervoorn 2
Hi Brenda,

Currently i'm progressing thru the novice state of Apex & Visual force and I was looking for a more controlled way to compose email messages which brought me here. So this solution it really great as it would give us far more control but I would also like the ability to select a template from the list of email templates. and use these ..... In general this would allow me to control case status progression as when a support agent also has the ability to select a template communication would also be more consistant.
 
developer beginnerdeveloper beginner

Hi Brenda, Hi Reader

I implement this same code and trying to slightly modify it. I want to save the EmailMessage in the Activity History. But somehow I'm not able to do it. I got this following exception.

Parent Case: Case ID: id value of incorrect type: 0069000000LvghYAAR
Exception thrown trying to send Email Message. Details = System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, Case ID: id value of incorrect type: 0069000000LvghYAAR: [ParentId]

Apparently it shows I need to provide the 15 digit Id in place of 18 digit. The thing which is not making any sense to me is that apparently I'm not doing anything with the Case object then why it is looking for Case ID? I'm providing the Opportunity ID as the ParentId to this email message. How can I make it work? Any help will be appreciable. Thanks.