[SalesForce] Email Alert using VisualForce Email Template Produces Empty Email

I want to send an email on creation of a record. The email must contain information about the record plus certain related detail records. I chose a VisualForce email template with a VF component referenced by the template to meed this requirement.

My email template works when I press the test button and enter the ID of a certain record. The template renders the data and I receive a test email just as I want.

I setup a workflow action, an Email Alert, referencing this template and the custom object type. I receive an email however, there's no body, it's blank.

I checked the debug logs and there's nothing there saying the APEX code threw an exception. Something must have gone wrong though I don't know what. I'm guessing the id of the custom record is not being passed to the template.

is a VisualForce template containing a component. On the test page for the template, I can click the 'test' button and enter a record ID and tick the 'send a test email'. The template renders and I receive the test email as expected.

Is this even possible?
How do I troubleshoot the problem?

VisualForce Component Controller:

public with sharing class LicensePropertiesComponentController {

    public LicensePropertiesComponentController() {
    }

    public ID getId() {
        return m_licenseId;
    }

    public void setId(ID value) {
        m_licenseId = value;
    }

    public List<String> getLines() {
        List<String> lines = new List<String>();
        try {
            Initialize();
                for (LicenseProperty__c property :m_properties) {
                    label = isNull(property.LabelText__c, 'No Label');
                    value = isNull(property.Value__c, 'No Value');
                    lines.add(String.format('{0} ... {1}', new String[]{label, value}));
                }
            }
        }catch(Exception ex) {
            lines.add('An exception occurred: ' + ex);
            System.debug(ex);
        }
        return lines;
    }

    private ID m_licenseId;
    private List<LicenseProperty__c> m_properties;

    private void initialize() {
        try {
            m_properties = [SELECT Group1Order__c, Group2Order__c, Group3Order__c, DisplayOrder__c, Group1Name__c, Group2Name__c, Group3Name__c, LabelText__c, Value__c, License__c FROM LicenseProperty__c WHERE License__r.ID = :m_licenseId ORDER BY Group1Order__c, Group2Order__c, Group3Order__c, DisplayOrder__c];
        }catch(Exception ex) {
        }  
    }

    private string isNull(string input, string substitute) {
        if (input == null) return substitute;
        return input;
    }

    private decimal isNull(decimal input, decimal substitute) {
        if (input == null) return substitute;
        return input;
    }
}

The APEX component:

<apex:component access="global" controller="LicensePropertiesComponentController">
    <apex:attribute name="licenseId" description="Object ID of License__c instance whos properties will be rendered." type="ID" required="required" assignTo="{!id}" />
    <apex:repeat id="repCtrl" var="line" value="{!Lines}">
{!line}
    </apex:repeat>
</apex:component>

The next bit

<messaging:emailTemplate subject="License Request" recipientType="User" relatedToType="License__c">
<messaging:plainTextEmailBody >
<c:LicensePropertiesComponent licenseId="{!relatedTo.ID}" />
</messaging:plainTextEmailBody>
</messaging:emailTemplate>

That's all for now.

Best Answer

OK, this could be the issue (having recently faced this myself)

Your database structure appears to be:

  • License__c
  • Several License_Property__c each of which has a lookup relationship to License__c

You mentioned that you are using a workflow to fire the email alert that references the License__c. The target of the workflow, is represented in the VF email template by relatedTo.id

  • Per VF order of execution, relatedTo.id is passed as an attribute to the custom component and assigned to the custom controller's m_licenseId via the setId() method
  • The order of execution now has the component calling getLines() that calls Initialize() to fetch the list of License_property__c

So far, so good.

My hypothesis, and where I was bitten, is when you test the template in the VF Email Template editor, you already had built the License__c and related License_Property__cs. The template renders fine

But when you test via exercising the workflow, no License_property__cs appear

A likely cause of this is that the workflow is triggered too soon - before the License_Property__c are built by whatever process causes the workflow on License__c to fire. Check your workflow entry criteria versus the state of the database.

Related Topic