How can I capture a system.limitexception stopping my emails being sent

Update 26th Oct: See below for a second version following comments below

I have just promoted this idea as well, I would never have imagined it to be a good design for this method to have it throw an unhandled exception, IMHO that is!

Anyway, since we are being inventive here, the following also seems to do the trick. But be aware much like the custom setting counting trick, it does not actually reserve anything for the subsequent sending of emails, as the method call is made in another VF context.

<apex:page controller="TestMessagingLimitController" action="{!check}"/>

public with sharing class TestMessagingLimitController 
{
    public PageReference check()
    {
        Integer amount = Integer.valueOf(ApexPages.currentPage().getParameters().get('amount'));
        Messaging.reserveSingleEmailCapacity(amount);       
        return null;
    }
}

You can then do this...

try
{
    PageReference checkMessages = Page.testmessaginglimit;
    checkMessages.getParameters().put('amount', '1000');
    checkMessages.getContent();
    // Success (note messages will not be reserved however)
}
catch (Exception e)
{
    // Failure
    System.debug(e.getMessage());
}

Implementation Note: If you wrap the above in your own helper method, e.g.

public static boolean checkSingleEmailCapacity(Integer amount)

You can then easily switch out this implementation with a try/catch once Salesforce allows us to catch these exceptions or provides an alternative as per the idea exchange posting.

Hope this helps!

Update: Apex REST Approach

Here is a further approach that is using a Http callout. I've left the above approach in my answer, as it has the benefit of not needing a remote site enabled, global class etc. So please make your choice! In the end if you follow the abstraction I recommended above and only call the helper method you can change your mind swiftly in the future.

@RestResource(urlMapping='/MessageLimit')
global with sharing class MessageLimit 
{
    @HttpGet
    global static void doGet() 
    {
        RestRequest req = RestContext.request;
        Integer amount = Integer.valueOf(req.params.get('amount'));
        Messaging.reserveSingleEmailCapacity(amount);               
    }

    public static boolean checkSingleEmailCapacity(Integer amount)
    {   
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/apexrest/MessageLimit?amount=' + amount);
        req.setMethod('GET');
        req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());
        HttpResponse res = h.send(req);
        if(res.getStatusCode() == 500) // May want to actually check the body message to be 100% sure
            return false;
        return true;
    }
}    

Thus you can now do this!

if(MessageLimit.checkSingleEmailCapacity(1001))
    System.debug('Good to go!');
else 
    System.debug('No go for launch!');              

Enjoy!


I agree, it's a huge inconvenience.

My colleague has decided to use custom setting with count of emails sent so far from Apex (there's a scheduled job to reset it overnight). Definitely not an elegant solution, you need to hunt all Messaging-related code and wrap it in your own class or add a line that would increment the counter...

Feel free to upvote his idea ;) https://sites.secure.force.com/success/ideaView?id=08730000000aSLLAA2