Long time reader first question :)

I have a before insert trigger on EmailMessage, but I also need to update the Parent Case - which works fine. I believe I have to use before insert as I am updating the TextBody/HTMLBody of the EmailMessage and it cannot be updated once saved. However I have not been able to test the Parent Case update, the EmailMessage tests are fine.

Now I read in this situation it's best to use an after insert trigger for the Parent updates but I can't do this completely because of the EmailMessage limitation. So it is possible to cover the Parent Case update in the test methods (currently on 85%), or have I missed something in terms of my trigger/class structure?

Thanks in advance.

Further scenario info: We want to mask/replace certain details on an inbound email, then also mark the Parent Case so we can report on when this has happened and also make it obvious to the user on the Case record itself.

Class below (hope I've used the correct tag for readability). I've added comments for the lines I can't cover in my existing test. When querying the Case these updates are not showing (although they are applied in out of the test method).

public class MaskClass{   

    Public Static EmailMask (List<EmailMessage> newEm){

        Set<String> emPId = new Set<String>();
        String mask = System.Label.Mask;
        String regEx = System.Label.Pattern;
        String MaskedText;
        Boolean EmailIncoming;

        for(EmailMessage emx:newEm){
            If(emx.TextBody !=null){

            pattern p = Pattern.compile(regEx);
            matcher m = p.matcher(emx.TextBody);             

            //If pattern matched replace match with mask
                system.debug('**EmailMask**: Card Details Detected in Email');
                emx.TextBody = m.replaceAll(mask);
        emx.HtmlBody = m.replaceAll(mask);             
                System.debug('**EmailMask ParentId: '+emx.ParentId);
                MaskedText = emx.TextBody;
                EmIncoming = emx.Incoming;

                system.debug('**EmailMask**: No Detection');
        System.debug('**EmailMask** Masked Text: '+MaskedText);    
                system.debug('**EmailMask TextBody is Null** '+emx.Subject);
        //Flag Parent Case Record
        If(emPid != null && EmIncoming == True){
    List<Case> cx = [SELECT Id, CaseNumber FROM Case WHERE Id IN :emPId];    //Not covered   
        for(Case cxUpdate:cx){ //Not covered
            cxUpdate.Flag__c=True; //Not covered
            system.debug('**EmailMask Debug** CaseNumber: '+cxUpdate.CaseNumber);
            update cxUpdate; //Not covered
    public static void ParentCaseMask (List<Case> newCase){
        String mask = System.Label.Mask;
        String regEx = System.Label.Pattern;

        for(Case cxUpdate:newCase){
            If(cxUpdate.Description != null){
                pattern pc = pattern.compile(regEx);
                matcher mc = pc.matcher(cxUpdate.Description);
                    system.debug('**CaseMask**: Detected in Case Description');                            
                    cxUpdate.Description = mc.replaceAll(mask);
                    system.debug('**CaseMask: '+cxUpdate.Flag__c);
                    system.debug('**CaseMask*: No match in Case Description');
                    system.debug('**CaseMask**: Case Description is Null');
  • I've added the class to my original post. It's the Case loop where the updates don't get applied within the test method, but do in real use.
    – Girbot
    Commented Jun 13, 2014 at 11:18

1 Answer 1


If an EmailMessage is inserted, any before insert and after insert trigger on EmailMessage will execute. The after insert trigger can do a SOQL query on the parent Case and then update that Case.

//  after insert trigger snippet; assume variable theMask contains a unique mask string
Set<ID> csIdUpdSet = new Set<ID>();
for (EmailMessage em : Trigger.new) 
  if (em.htmlbody.contains(theMask) || em.textBody.contains(theMask))

List<Case> csUpdList = [select id, has_mask_event__c from Case where id IN :csIdUpdSet]
for (Case cs : csUpdList)
   cs.has_mask_event__c = true;
update csUpdList;

// end snippet
  • Hi, so are you suggesting changing the trigger to after insert? When I tried this the EmailMessage was read only and I couldn't update the TextBody or EmailBody.
    – Girbot
    Commented Jun 13, 2014 at 11:19
  • 2
    No - do the masking in the before insert and the Case update in the after insert
    – cropredy
    Commented Jun 13, 2014 at 18:23
  • Ah OK I think I understand. A new email message comes in (regardless if it creating a new case or associated to an existing case) an email message before insert trigger masks the email message and an email message after insert trigger performs the case update action. Didn't think of splitting it like that, I'll have a go when I'm next in the office.
    – Girbot
    Commented Jun 13, 2014 at 21:33
  • 1
    I generally follow two simple rules: Validations and updating records inside Trigger.new are always "before event", and any type of DML for related parent or child records, or any other records, in an "after event". There are, however, exceptions to the rule.
    – sfdcfox
    Commented Jul 13, 2014 at 19:06
  • 1
    N.B. The Force.com Enterprise Architecture domain layer (aka trigger pattern) does Validation in after triggers. The justification tends to be mostly for ISVs protecting data integrity against an environment where others also have triggers on the same object. @sfdcfox
    – cropredy
    Commented May 21, 2018 at 12:46

You must log in to answer this question.

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