16

Steps to reproduce:

  1. Create Visualforce Email Template
  2. Create Visualforce component and add it into the email template
  3. Create Apex Controller for the component from pt.2
  4. Do some SOQL queries there, process them and result pass into component markup.
  5. Generate an email using Messaging.renderStoredEmailTemplate many times and get results from the email body. One email template generation takes 1 SOQL query limit, controller SOQL query limits are not counted.

LimitsHack.email

<messaging:emailTemplate subject="Limits Hack" recipientType="User" relatedToType="Contact">
    <messaging:plainTextEmailBody>
        <c:LimitsHackCmp/>
    </messaging:plainTextEmailBody>
</messaging:emailTemplate>

LimitsHackCmp.component

<apex:component id="LimitsHackCmp" controller="LimitsHackCmpController" access="global">
    {!results}
</apex:component>

LimitsHackCmpController.cls

    public String results {
        set;
        get {
            String result = '';
            for (Integer i = 0; i < 100; i++) {
                List<Account> accs = [SELECT Name FROM Account LIMIT 1 OFFSET :Math.mod(i, 3)];
                result += i + ') ' + accs[0].Name + ' ';
            }
            return result;
        }
    }
}

LimitsHackPlayground.cls

public with sharing class LimitsHackPlayground {
    public static void execute() {
        EmailTemplate emailTmpl = [
                SELECT Id
                FROM EmailTemplate
                WHERE DeveloperName = 'LimitsHack'
        ];

        System.debug(UserInfo.getUserId());

        for (Integer i = 0; i < 35; i++) {
            Long renderStart = System.now().getTime();
            String emailBody = Messaging.renderStoredEmailTemplate(emailTmpl.Id, UserInfo.getUserId(), '<any contact id>').plainTextBody;
            System.debug('LimitsHackPlayground: i=' + i + '. Took ' + (System.now().getTime() - renderStart) + ' ms. Email Body: ' + emailBody);
        }
    }
}

OFFSET :Math.mod(i, 3) I used to avoid any type of caching because of the deterministic repeatable query. Each email generation takes up to 500ms, so it is easy to get into the Apex CPU time limit. But still, I managed to make 35 email renders.

Question: Is it expected behavior or a bug? Did anybody meet similar behavior before?

6
  • What would be the non-buggy expected behavior, in your opinion?
    – identigral
    Commented Dec 15, 2019 at 23:33
  • @identigral I would say Salesforce limits should apply to every synchronous query in a context. Commented Dec 18, 2019 at 5:26
  • 4
    If each call to Messaging.renderStoredEmailTemplate is a separate transaction, the per-tx limit of 100 SOQL queries is still good. Does it complain if you go over 100 in the controller?
    – identigral
    Commented Dec 18, 2019 at 19:00
  • Result of calling renderStoredEmailTemplate is returned synchronously. It's not a separate transaction. Commented Dec 19, 2019 at 7:22
  • 4
    @YevhenKharchuk whether its synchronous or not has nothing to do with whether or not it is a transaction. The emails are acting a bit like Visualforce page renders in this context. so its a bit like rendering 35 visualforce pages, each with 100 SOQL queries on it. Nice experiment though! Eventually you will hit the email limit I guess!
    – codeulike
    Commented Feb 3, 2022 at 15:59

1 Answer 1

1

Visualforce is a separate runtime, and it historically did not honor governor limits. If you're able to still run this code, make sure you log a bug. I logged a similar bug where I was able to create over 100MB of heap data used to insert 300,000 records at once, consuming approximately 9,000,000ms CPU time, and consuming several thousand times my actual storage limit (in a Developer Edition), all in a single transaction. They've fixed a lot of this based on my feedback, but this is one I've not yet reported.

1
  • I'm impressed; of course VF strictly honors Viewstate limits
    – cropredy
    Commented Oct 25, 2022 at 18:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .