I have custom metadata type with api name program_mdt in which I have created two fields called Email_Keyword__c and Body__c. In the below trigger I am trying to get rid of hard coded values in the if(filename.contains('report')) and the defining body of the email in step4.

I am not sure how to proceed from here to replace hard coded values with custom metadata. In this case i am trying to send out an email when file name contains the values that exist in Email_Keyword__c field of program__mdt.

    trigger FilesAccountUpload_Tr on ContentDocumentLink (before insert) {
  set<Id>setAccIds = new set<Id>();
    set<Id>setCntDocIds = new set<Id>();
    List<Program__mdt> lstMetaData = [SELECT Email_c FROM Program__mdt];

    Map<Id, String> filestitlemaps  = new Map<Id, String>();
    Map<Id, String> accnamemaps   = new Map<Id, String>();

    for(ContentDocument c : [select id, title from ContentDocument]){

    for(Appointment__c app: [select id,Name from Appointment__c]){

    List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
    Set<String> KeywordSet = new Set<String>();  

    for(ContentDocumentLink clIterator : trigger.new) {
        string strObjPrefix = String.valueOf(clIterator.LinkedEntityId).substring(0, 3);
        if(strObjPrefix == Appointment__c.sObjectType.getDescribe().getKeyPrefix()) {
              string filename =filestitlemaps.get(clIterator.ContentDocumentId); 
        string accountname = accnamemaps.get(clIterator.LinkedEntityId);
        Set<String> KeywordSet = new Set<String>();

            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

            // Step 2: Set list of people who should get the email
      List<String> sendTo = new List<String>();

            // Step 3: Set who the email is sent from
      mail.setSenderDisplayName('File gets uploaded');

            // (Optional) Set list of people who should be CC'ed
      List<String> ccTo = new List<String>();

            // Step 4. Set email contents - you can use variables!
      mail.setSubject(accountname+'File uploaded');
      String body = 'Dear Team , '; 
      //body += +filename+'files was uploaded';
      body += +Program_Setting__mdt.Email_Body__c;


      // Step 5. Add your email to the master list

            // Step 6: Send all emails in the master list


You can simply query the Custom metadata types like below:

program__mdt[] programs = [SELECT MasterLabel, QualifiedApiName, Email_Keyword__c, Body__c FROM Threat_Tier_Mapping__mdt];

Then, you use these values like below:


This is, if you are sure there will be only 1 record. However, you can add WHERE condition to get exactly the record metadata-type needed in query like below:

program__mdt[] programs = [SELECT MasterLabel, QualifiedApiName, Email_Keyword__c, Body__c FROM Threat_Tier_Mapping__mdt WHERE Email_Keyword__c='report'];


I would recommend you to use Email templates and use setTemplateId. The content can be dynamically generated through merge fields in template and depends on Account/Contact/other object.

For further info, You can check How to send an Email Template via Apex?

Note: setting the body through custom metadata type and concatenating OR replacing dynamic data in apex class is not scalable and will become very complex to implement.

  • Thanks very much mate. It worked out for the Email_Keyword__c but I am still not sure about making email Body__c dynamic. I understand that we have queried body from the custom data but I am not how to place it in my step4 of the trigger. please suggest // Step 4. Set email contents - you can use variables! mail.setSubject(accountname+'File uploaded'); String body = 'Dear Team , '; //body += +filename+'files was uploaded'; body += +Program_Setting__mdt.Email_Body__c; mail.setHtmlBody(body);
    – user54028
    Aug 13 '19 at 15:43
  • I think this will become very complex. added in answer Aug 13 '19 at 15:57

I am going to assume you already know how to create and populate a Custom Metadata type.

With that, your code can have a snippet like this one

Boolean containsKeyword = false;

for (Program__mdt prog : [Select Email_Keyword__c from Program__mdt]) {
  if (filename.contains(prog.Email_Keyword__c)) {
    containsKeyword = true;

if (containsKeyword) {
   //Do your thing

That way, if at least one keyword is found, you'll execute your logic.

PS: I see that in your code you already have lstMetaData, you can (should) use that instead of the SoQL I added in my snippet if that list is pointing to the same Custom Metadata Type.

Update from OP's comments

Salesforce offers templates built-in in the platform. You can do them in Classic or Lightning.

Templates are going to allow you to merge fields, set subjects and even change the text without having to write code (which is why, I assume, you tried to do it with Custom Metadata).

The main takeaway of using sending emails via Apex is that some limits will apply. (see here and here).

I do not recommend you try your own merging via Custom Metadata. Re-inventing standard functionality is not the way to go.

  • Thank you Sebastian! I understand the keyword scenario however I am still confused how to call and define the body content in trigger from the metadata.
    – user54028
    Aug 13 '19 at 15:48
  • 1
    Hi there, you're really asking two very different things here. As @salesforce-sas outlined above, the second question is very different. I'll update my answer as well, but I agree with him in that you probably want a template and not a CMDT for it. Aug 13 '19 at 16:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy