+ Start a Discussion
ElcalvoMikeElcalvoMike 

Dynamic email template and controller

We maintain about 50 brands within our company and I would like to have a standard email template where the brand logo would swap out AND the body of the email (not the header and footer) would be inserted at send. The problem I have had is that I CANNOT get the body to work with the controller. I want to be able to create a template and reference any field  like {!opp.companyname__c}_logo,jpg for example. Right now I am using objects to retrieve the parts but this doesnt connect it with the controller. How can I approch this in a better way?

 

Code:

public class oppSendMail{
    public string subject { get; set; }
    public string body { get ; set; }
    private final Opportunity oppo { get ; set; }
    private final Account acc;
    private final OpportunityEmailHtml__c objHTML;
    private final Emails_Subject_And_Body__c objESB;
    private string webPartner {get; set; }
    
    public oppSendMail(){
           oppo=[select ID,Name,etc];

        objHTML = [select EmailHtml__c from OpportunityEmailHtml__c where Name = : 'GlobalET'];
        
        objESB = [select Body__c, Subject__c from Emails_Subject_And_Body__c where Name =: 'Hold' Limit 1];
        
        subject = String.valueOf(objESB.get('Subject__c'));
        body = String.valueOf(objHTML.get('EmailHtml__c'));
        webPartner = String.valueOf(oppo.get('WebPartner__c'));
        body = body.Replace('{!OppBasic.WebPartner__c}', webPartner);
        body = body.Replace('@Message', String.valueOf(objESB.get('Body__c')));
    }
    
    public Opportunity getOppBasic(){
        return oppo;
    }
    
    public OpportunityEmailHtml__c getETBasic(){
        return objHTML;
    }
    
    public PageReference send() {
        // Define the email
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        String addresses;
        addresses = String.valueOf(oppo.get('email__c'));
        String[] toAddresses = addresses.split(':', 0);
        // Sets the paramaters of the email
        email.setSubject( subject );
        email.setToAddresses( toAddresses );
        email.setHtmlBody(body);
        // Sends the email
        Messaging.SendEmailResult [] r =
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
        
        PageReference objPage = new PageReference(Apexpages.currentPage().getParameters().get('retURL'));
        objPage.setRedirect(true);
        return objPage;
    }
}

 

 

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

I'm pretty confused now.  What is testmailbody?  Is it the name of a custom visualforce component?  

 

The apex:insert is part of the templating system will pull in the element from the page that is bounded by apex:define tags.  

All Answers

bob_buzzardbob_buzzard

This sounds like you should be using visualforce templates to me.  You can pull information from two objects as standard, plus you can use custom components where the controller can have any business logic that you like.

ElcalvoMikeElcalvoMike

I actually have it working now via a page template, and then pushing the page to the sendmail() htmlbody.

The only issue I have remaining is that I am trying to reference the body of my template via the  URL like so

apex/display_email?id=006Q0000007pzGA&body=testmailbody

 

There is a component called testmailbody, but when I try to insert it into the page it will now allow me to use the variable reference. It only allows a literal. Is there another way to call the component by reference?

public class opportunityCustomController{ 
private final Opportunity o;
private final string component;
public opportunityCustomController(){
              
        o=[select ID,Name,address1__c,address2__c,shipAddrType__c,Amount_Net__c,Cancelled__c,chkAmount__c,chkNumber__c,chkRecd__c,chkDate__c,city__c,Company__c,country__c,cPONum__c,cShippingInfo__c,custID__c,CustomerArt__c,email__c,shippingemail__c,EstDelEndDate__c,EstDelStartDate__c,EstShipMethod__c,ExpectedShipDate__c,fax__c,shippingfax__c,fname__c,handling__c,InvoiceSent__c,iocd_text__c,iOrderCustDetailPk__c,IS_CC__c,Is_CreditCard_declines__c,isFromUnviersalQuote__c,isOnCreditHold__c,Lead_Time__c,lname__c,LogoUploaded__c,OrderDate__c,OrderInstructions__c,phone__c,shippingphone__c,POSent__c,PromoCode__c,rebate__c,rebate_desc__c,Redo__c,Remarks__c,ReOrder__c,shipping__c,shippingaddress__c,shippingaddress2__c,shippingcity__c,shippingcompany__c,NetShippingCost__c,shippingcountry__c,shippingfname__c,shippinglname__c,shippingstate__c,shippingtitle__c,shippingzip__c,state__c,tax__c,Title__c,VisitorId__c,WebPartner__c,webpartnerOID__c,XMQuoteNo__c,zip__c,(Select Id, IsPrimary, Contact.Name, Contact.Email From OpportunityContactRoles Where IsPrimary=TRUE)
          from Opportunity where id = : Apexpages.currentPage().getParameters().get('id')];
        component = Apexpages.currentPage().getParameters().get('body');

}

public Opportunity getOpportunity(){
return o;
}

public string getEmailBody() {
return component;

}

 

 

<apex:insert name="{!Emailbody}" /> 

 

bob_buzzardbob_buzzard

I'm pretty confused now.  What is testmailbody?  Is it the name of a custom visualforce component?  

 

The apex:insert is part of the templating system will pull in the element from the page that is bounded by apex:define tags.  

This was selected as the best answer
ElcalvoMikeElcalvoMike

Exactly, i want to be able to pass the name of a component (testemailbody in this example) to the page and insert it into the page.

Just to clairify I am not using VF tempalte but rather a standard page.

bob_buzzardbob_buzzard

The problem is that you are trying to dynamically generate the Visualforce markup, and then have a second pass at the generation that generates HTML from the VF markup.  Unfortunately you only have one pass at generation so you can't do this.

 

What I think you should be able to do is include all possible components in the apex:define section that defines the email body and then conditionally render them based on the URL parameter.

ElcalvoMikeElcalvoMike

Sure that makes sense. thanks for the help.

Ill make a single page and include all of the templates with define and display conditionally with JavaScript. That way they will all render but only one will show.

 

Ideally I would like to have created a component and insert it into the dynamically and have it controlled by that template page or even better have the component contain an extension of the template's controller for additional logic.