Problem Statement
In Salesforce Service Cloud, when using Email-to-Case, there may be a need to prevent users from replying to or CC’ing certain email addresses — for example, internal loopbacks, external systems, or deprecated inboxes.
Hardcoding such addresses in validation rules or Apex logic is not scalable or maintainable. Instead, we can leverage Custom Metadata Types (CMDT) to manage this list dynamically and enforce restrictions via a trigger.
The Solution
We define a Custom Metadata Type named Blocked_Email_Address__mdt
with a field Email_Address__c
. Then, using an Apex trigger and helper logic, we check outgoing emails and block any that contain a restricted address in the To or CC fields.
This provides:
Easy updates without deploying code
Centralized governance of blocked addresses
Enforcement at the platform level using Apex triggers
Apex Trigger Snippet
Below is a focused code block demonstrating how the enforcement is done:
// >>> BLOCKED EMAIL LOGIC START
Set blockedEmails = new Set();
for (Blocked_Email_Address__mdt meta :
[SELECT Email_Address__c FROM Blocked_Email_Address__mdt]) {
if (meta.Email_Address__c != null) {
blockedEmails.add(meta.Email_Address__c.toLowerCase());
}
}
for (EmailMessage email : emailMessageList) {
// Check that email is outgoing and related to a Case
if (!email.Incoming && email.ParentId != null &&
String.valueOf(email.ParentId).startsWith('500')) {
String toAddr =
email.ToAddress != null ? email.ToAddress.toLowerCase() : '';
String ccAddr =
email.CcAddress != null ? email.CcAddress.toLowerCase() : '';
for (String blocked : blockedEmails) {
if ((toAddr.contains(blocked)) || (ccAddr.contains(blocked))) {
email.addError(
'Email not allowed to be sent to or CC\'d to restricted address: ' +
blocked);
continue;
}
}
}
}
// <<< BLOCKED EMAIL LOGIC END
How to Set It Up
Create the Custom Metadata Type
- Label:
Blocked Email Address
- Developer Name:
Blocked_Email_Address__mdt
- Field:
Email_Address__c
(Text, Required)
Add Metadata Records
Go to Setup → Custom Metadata Types → Manage Records, and create entries like:
Add the Logic to a Helper Class or Trigger
Keep the main logic modular. You can invoke this from EmailMessageTriggerHandler
or similar classes.
Trigger
trigger EmailMessageTrigger on EmailMessage(before insert) {
if (Trigger.isBefore && Trigger.isInsert) {
EmailMessageTriggerHandler.handleBeforeInsert(Trigger.new);
}
}
TriggerHandlerClass
public
class EmailMessageTriggerHandler {
public static void handleBeforeInsert(
List emailMessageList) {
// Load blocked email addresses from Custom Metadata
Set blockedEmails = new Set();
for (Blocked_Email_Address__mdt meta :
[SELECT Email_Address__c FROM Blocked_Email_Address__mdt]) {
if (meta.Email_Address__c != null) {
blockedEmails.add(meta.Email_Address__c.toLowerCase());
}
}
for (EmailMessage email : emailMessageList) {
// Only apply to outbound emails associated with Cases (Prefix: 500)
if (!email.Incoming && email.ParentId != null &&
String.valueOf(email.ParentId).startsWith('500')) {
String toAddr =
email.ToAddress != null ? email.ToAddress.toLowerCase() : '';
String ccAddr =
email.CcAddress != null ? email.CcAddress.toLowerCase() : '';
for (String blocked : blockedEmails) {
if ((toAddr.contains(blocked)) ||
(ccAddr.contains(blocked))) {
email.addError(
'Email not allowed to be sent to or CC\'d to restricted address: ' +
blocked);
break;
}
}
}
}
}
}
Benefits
Dynamic: Admins can update the blocked list without developer involvement.
Secure: Prevents accidental or unauthorized emails from being sent.
Scalable: Easily integrates with existing trigger frameworks or email policies.
Conclusion
This pattern highlights the power of Custom Metadata and Apex triggers in enforcing flexible business logic. Whether it’s blocking addresses, applying branding, or routing logic — metadata-driven designs provide long-term maintainability and agility for growing orgs.