[SalesForce] Dynamically displaying, adding, and deleting attachments from email template before sending email

-> A custom link on the contacts page invokes a VF page

-> This VF page simulates the Send an Email page while auto populating a predefined email template:

<apex:page standardController="contact" extensions="custom_button_controller" id="ThePage">
    <apex:form id="theForm">
        <apex:pageBlock id="theBlock" mode="inlineEdit">
                <apex:outputLabel value="To  "/>
                <apex:outputField value="{!Contact.name}"/>
                <br/>
                <br/>
                <apex:outputLabel value="Cc  "/>
                <apex:inputtext value="{!Cc}"/>
                <br/>
                <br/>
                <apex:outputLabel value="Subject  "/>
                <apex:outputField value="{!emailTemp.subject}"/>
                <br/>
                <br/>
                <p> Body </p>
                <apex:inputTextarea value="{!emailTemp.HtmlValue}" richText="true" rows="25" cols="100"/>
                <br/>
                <br/>
                <apex:commandButton action="{!sendEmail}" value="Send Email" id="theButton"/>
        </apex:pageBlock>
    </apex:form>
</apex:page>

-> The apex code:

public class custom_button_controller {

            string contact_id{get;set;}
            public EmailTemplate emailTemp{get;set;}
            public string cc{get;set;}
            contact c;
            public custom_button_controller(ApexPages.StandardController controller) {
                   contact_id = apexpages.currentpage().getparameters().get('id');
                   c = [Select FirstName from contact where id=: contact_id];
                   emailTemp  = [select Subject, Name, Id, HtmlValue From EmailTemplate where id='00X50000001XtXB'];
            }
            public pagereference sendEmail(){
                    Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
                    //message.setTemplateId('00X50000001XtXB');
                    message.setTargetObjectId(contact_id);
                    List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>();

                    for (Attachment a : [select Name, Body, BodyLength from Attachment])
                    {
                      Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();
                      efa.setFileName(a.Name);
                      efa.setBody(a.Body);
                      fileAttachments.add(efa);
                    }
                    //message.setCcAddresses();
                    emailTemp.HtmlValue = emailTemp.HtmlValue.replace('{!Contact.FirstName}',c.FirstName);
                    message.setHtmlBody(emailTemp.HtmlValue);
                    message.setFileAttachments(fileAttachments);
                    Messaging.sendEmail(new Messaging.SingleEmailMessage[]{message});
                    return null;
                }

            }  

What is working:

  1. Neat editable preview of the HTML body on the VF page (except for merge field, explained below)

  2. Sending email successfully with the right attachments

  3. Successful inline editing of the email body, which results in an updated body sent

What is NOT working:

  1. Email recipient sees merge field {!Contact.FirstName}, instead of the merge field value. Rather than reading Dear Diary, it's Dear {!Contact.FirstName},. This merge field (not its value) is also seen in the text area preview that the user can edit before sending out the email. Update: Got this working by using replace() to replace merge field with contact.firstname. See code

  2. Adding cc address to the email. Tried setCcAddress() in the code. Need help adding this cc address before sending out the email

  3. Displaying attachments as well as giving the user the option to add and delete attachments all on the same single 'Send an Email' VF page

  4. When the send button is clicked, the page (browser tab) is closed and the user views the concerned contact record

  5. Having the To field on the VF page as a lookup field to show emails of contacts and users

Appreciate your time.

Best Answer

Update one more time : The code below can send email, add attachements, delete attachments on the fly and reload the same page to send more emails. Page:

<apex:page standardController="contact" extensions="custom_button_controller" id="ThePage">
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.js"/>
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.js"/>
    <apex:form id="theForm">
        <apex:pageBlock id="theBlock" mode="inlineEdit">
                <apex:outputLabel value="To  "/>
                <apex:outputField value="{!Contact.name}"/>
                <br/>
                <br/>
                <apex:outputLabel value="Cc  "/>
                <apex:inputtext value="{!Cc}"/>
                <br/>
                <br/>
                <apex:outputLabel value="Subject  "/>
                <apex:outputField value="{!emailTemp.subject}"/>
                <br/>
                <br/>
                <p> Body </p>
                <apex:inputTextarea value="{!emailTemp.HtmlValue}" richText="true" rows="25" cols="100"/>
                <br/>
                <br/>
                <apex:commandButton action="{!sendEmail}" value="Send Email" id="theButton"/>
        </apex:pageBlock>




    <apex:pageblock title="Attachments">
    <apex:commandButton value="New Attachment" action="{!attach_new}"/>
    <apex:commandButton value="delete" action="{!getSelected}" />
        <apex:pageblocktable value="{!Selectedattachments}" var="a">
            <apex:column headerValue="Select to Delete ">
            <apex:inputCheckbox value="{!a.selected}" id="checkedone">
            
            </apex:inputCheckbox>
            </apex:column>
           <apex:column headerValue="Attachment Id"   value="{!a.acc.id}"/>
           <apex:column headervalue="Attachment Name" value="{!a.acc.name}"/>
        </apex:pageblocktable>
        
    </apex:pageblock>
    </apex:form>
  
</apex:page>

Controller :

 public class custom_button_controller {

            string contact_id{get;set;}
            public EmailTemplate emailTemp{get;set;}
            public string cc{get;set;}
            List<attachwrapper> attach= new List<attachwrapper>();
            list<attachment> selectedAttach = new list<attachment>();
            List<attachment> attach_criteria = new List<attachment>();

            public string Attach_to_delete_Id{get;set;}
            contact c;

            public List<string> cc_addresses{get;set;}
            public custom_button_controller(ApexPages.StandardController controller) {

                   contact_id = apexpages.currentpage().getparameters().get('id');
                   c = [Select FirstName from contact where id=: contact_id];
                   emailTemp  = [select Subject, Name, Id, HtmlValue From EmailTemplate limit 1];  
                   cc_addresses = new List<string>();  
            }

                public List<attachwrapper> getattach()
                {           
                     attach.clear();
                     if(selectedattach.size() > 0){
                        attach_criteria =  [select id,name from attachment where Id NOT IN: selectedattach and parentId =: '00X50000001XtXB'];
                     }
                     else{
                     attach_criteria = [select id,name from attachment where ParentId =: '00X50000001XtXB'];
                     }

                    for(Attachment a :  attach_criteria ){          
                    attach.add(new attachwrapper(a));}       
                    return attach ;
                }
                public PageReference getSelected()
                {

                    selectedattach.clear();
                    for(attachwrapper awrapper : attach){
                    if(awrapper.selected == true){                 
                    selectedattach.add(awrapper.acc);}   
                    }
                    return null;
                }
                public List<attachwrapper> GetSelectedattachments()
                {
                    if(selectedattach.size()>0){                     
                    return getattach();                    
                    }
                    return getattach();
                }   

                public pagereference sendEmail(){
                    if(cc.length() >0 && cc != null){
                        List<string> split_cc = new List<string>();
                        split_cc = cc.split(';');                        
                        for(string s: split_cc){
                            cc_addresses .add(s);
                        }

                    }
                    Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
                    //message.setTemplateId('00X50000001XtXB');
                    message.setTargetObjectId(contact_id);
                    List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>();

                    for (Attachment a : [select id,name,body from attachment where id IN: attach_criteria])
                    {
                      Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();
                      efa.setFileName(a.Name);
                      efa.setBody(a.Body);
                      fileAttachments.add(efa);
                    }
                    message.setCcAddresses(cc_addresses );
                    emailTemp.HtmlValue = emailTemp.HtmlValue.replace('{!Contact.FirstName}',c.FirstName);
                    message.setHtmlBody(emailTemp.HtmlValue);
                    message.setFileAttachments(fileAttachments);
                    Messaging.sendEmail(new Messaging.SingleEmailMessage[]{message});
                    return null;
                }

                public pagereference attach_new(){
                pagereference pag = new pagereference('/apex/addattachments');
                pag.getParameters().put('contact_id', contact_id);
                return pag;
                }

            public class attachwrapper{
                public attachment acc{get; set;}
                public Boolean selected {get; set;}
                public attachwrapper(attachment a){
                    acc = a;
                    selected = false;
                }
            } 
}

Page for adding new attachment

Page:

<apex:page controller="AttachmentUploadController">
  <apex:sectionHeader title="Visualforce Example" subtitle="Attachment Upload Example"/>

  <apex:form enctype="multipart/form-data">
    <apex:pageMessages />
    <apex:pageBlock title="Upload a Attachment">

      <apex:pageBlockButtons >
        <apex:commandButton action="{!upload}" value="Save"/>
      </apex:pageBlockButtons>

      <apex:pageBlockSection showHeader="false" columns="2" id="block1">

        <apex:pageBlockSectionItem >
          <apex:outputLabel value="File Name" for="fileName"/>
          <apex:inputText value="{!attachment.name}" id="fileName"/>
        </apex:pageBlockSectionItem>

        <apex:pageBlockSectionItem >
          <apex:outputLabel value="File" for="file"/>
          <apex:inputFile value="{!attachment.body}" filename="{!attachment.name}" id="file"/>
        </apex:pageBlockSectionItem>

        <apex:pageBlockSectionItem >
          <apex:outputLabel value="Description" for="description"/>
          <apex:inputTextarea value="{!attachment.description}" id="description"/>
        </apex:pageBlockSectionItem>

      </apex:pageBlockSection>

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

Controller:

public with sharing class AttachmentUploadController {
public string contact_Id{get;set;}
  public Attachment attachment {
  get {
      if (attachment == null)
        attachment = new Attachment();
      return attachment;
    }
  set;
  }

  public PageReference upload() {
    contact_Id = apexpages.currentpage().getparameters().get('contact_id');
    attachment.OwnerId = UserInfo.getUserId();
    attachment.ParentId = contact_Id; // the record the file is attached to
    attachment.IsPrivate = true;

    try {
      insert attachment;
    } catch (DMLException e) {
      ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error uploading attachment'));
      return null;
    } finally {
      attachment = new Attachment(); 
    }

    pagereference pag = new pagereference('apex/testing_emailK?id='+contact_id);
    pag.setredirect(true);
    return pag;
  }

}

enter image description here