Passing custom string into a Salesforce email template.

I've done something similar in the past, but it requires that you manually do the template merge field lifting. Here is an example of how you could do it below.

Since you are manually doing the merging in the template, you can put any kind of merge field into your template that you'd like. In this example, I'm pretending there is a custom merge field {!myCustomString} in the email template for your custom string you want to insert.

I've also assumed below that you have a merge field for first name {!Contact.FirstName} in the subject and in the body of the template. If you have other fields, you would need to include the fields in the contact query and then to the string replace for each of those fields.

public static void sendSingleMail(Id contactId, Id templateId, String fromAddress, String myCustomString){

    // grab the email template
    EmailTemplate emailTemplate = [select Id, Subject, HtmlValue, Body from EmailTemplate where Id =: teamplateId];

    // grab the contact fields we need. This assumes we are emailing a contact.
    Contact c = [Select Id, FirstName FROM Contact WHERE Id=: contactId];

    // process the merge fields
    String subject = emailTemplate.Subject;
    subject = subject.replace('{!Contact.FirstName}', c.FirstName);

    String htmlBody = emailTemplate.HtmlValue;
    htmlBody = htmlBody.replace('{!Contact.FirstName}', c.FirstName);
    htmlBody = htmlBody.replace('{!myCustomString}', myCustomString);

    String plainBody = emailTemplate.Body;
    plainBody = plainBody.replace('{!Contact.FirstName}', c.FirstName);
    plainBody = plainBody.replace('{!myCustomString}', myCustomString);

        //build the email message
    Messaging.Singleemailmessage email = new Messaging.Singleemailmessage();

    email.setReplyTo(fromaddress);
    email.setSenderDisplayName(fromaddress);
    email.setTargetObjectId(objId);
    email.setSaveAsActivity(true);

    email.setSubject(subject);
    email.setHtmlBody(htmlBody);
    email.setPlainTextBody(plainBody);

    Messaging.sendEmail(new Messaging.SingleEmailmessage[] {email});
}

I would recommend you take a look at Visualforce Components.

<apex:component controller="DynamicContent">{!dynamicContent}</apex:component>

public with sharing class DynamicContent {
    public String getDynamicContent()
    {
        return 'Something dynamic ' + System.today();
    }
}

Then in your Visualforce Email Template reference the new component via...

<c:DynamicContent/>

You can also pass parameters to the component, if you need context from the target record.


I provided my process before on this answer: Using APEX to assemble HTML Letterhead Emails

using regular expressions and a Map <\String,String> you can build your own mail merge process that works pretty well.