Newer Version Available
Moderate Chatter Private Messages with Triggers
| Available in: Salesforce Classic |
| Available in: Enterprise, Performance, Unlimited, and Developer Editions |
| User Permissions Needed | |
| To save Apex triggers for ChatterMessage: | Author Apex AND Manage Chatter Messages and Direct Messages |
Write an Apex before insert trigger to review the private message body and information about the sender. You can add validation messages to the record or the Body field, which causes the message to fail and an error to be returned to the user.
Although you can create an after insert trigger, ChatterMessage is not updatable, and consequently any after insert trigger that modifies ChatterMessage will fail at run time with an appropriate error message.
To create a trigger for private messages from Setup, enter ChatterMessage Triggers in the Quick Find box, then select ChatterMessage Triggers. Alternatively, you can create a trigger from the Developer Console by clicking and selecting ChatterMessage from the sObject drop-down list.
This table lists the fields that are exposed on ChatterMessage.
| Field | Apex Data Type | Description |
|---|---|---|
| Id | ID | Unique identifier for the Chatter message |
| Body | String | Body of the Chatter message as posted by the sender |
| SenderId | ID | User ID of the sender |
| SentDate | DateTime | Date and time that the message was sent |
| SendingNetworkId | ID | Network (site) in which the message was sent. This field is visible only if digital experiences is enabled and Private Messages is enabled in at least one site. |
This example shows a before insert trigger on ChatterMessage that is used to review each new message. This trigger calls a class method, moderator.review(), to review each new message before it is inserted.
1trigger PrivateMessageModerationTrigger on ChatterMessage (before insert) {
2 ChatterMessage[] messages = Trigger.new;
3
4 // Instantiate the Message Moderator using the factory method
5 MessageModerator moderator = MessageModerator.getInstance();
6
7 for (ChatterMessage currentMessage : messages) {
8 moderator.review(currentMessage);
9 }
10}If a message violates your policy, for example when the message body contains blocklisted words, you can prevent the message from being sent by calling the Apex addError method. You can call addError to add a custom error message on a field or on the entire message. The following snippet shows a portion of the reviewContent method that adds an error to the message Body field.
1if (proposedMsg.contains(nextBlockListedWord)) {
2 theMessage.Body.addError(
3 'This message does not conform to the acceptable use policy');
4 System.debug('moderation flagged message with word: '
5 + nextBlockListedWord);
6 problemsFound=true;
7 break;
8 }The following is the full MessageModerator class, which contains methods for reviewing the sender and the content of messages. Part of the code in this class has been deleted for brevity.
1public class MessageModerator {
2 private Static List<String> blocklistedWords=null;
3 private Static MessageModerator instance=null;
4
5 /**
6 Overall review includes checking the content of the message,
7 and validating that the sender is allowed to send messages.
8 **/
9 public void review(ChatterMessage theMessage) {
10 reviewContent(theMessage);
11 reviewSender(theMessage);
12 }
13
14 /**
15 This method is used to review the content of the message. If the content
16 is unacceptable, field level error(s) are added.
17 **/
18 public void reviewContent(ChatterMessage theMessage) {
19 // Forcing to lower case for matching
20 String proposedMsg=theMessage.Body.toLowerCase();
21 boolean problemsFound=false; // Assume it's acceptable
22 // Iterate through the blocklist looking for matches
23 for (String nextBlockListedWord : blocklistedWords) {
24 if (proposedMsg.contains(nextBlockListedWord)) {
25 theMessage.Body.addError(
26 'This message does not conform to the acceptable use policy');
27 System.debug('moderation flagged message with word: '
28 + nextBlockListedWord);
29 problemsFound=true;
30 break;
31 }
32 }
33
34 // For demo purposes, we're going to add a "seal of approval" to the
35 // message body which is visible.
36 if (!problemsFound) {
37 theMessage.Body = theMessage.Body +
38 ' *** approved, meets conduct guidelines';
39 }
40
41 }
42
43 /**
44 Is the sender allowed to send messages in this context?
45 -- Moderators -- always allowed to send
46 -- Internal Members -- always allowed to send
47 -- Site Members -- in general only allowed to send if they have
48 a sufficient Reputation
49 -- Site Members -- with insufficient reputation may message the
50 moderator(s)
51 **/
52 public void reviewSender(ChatterMessage theMessage) {
53 // Are we in a Site Context?
54 boolean isSiteContext = (theMessage.SendingNetworkId != null);
55
56 // Get the User
57 User sendingUser = [SELECT Id, Name, UserType, IsPortalEnabled
58 FROM User where Id = :theMessage.SenderId ];
59 // ...
60 }
61
62 /**
63 Enforce a singleton pattern to improve performance
64 **/
65 public static MessageModerator getInstance() {
66 if (instance==null) {
67 instance = new MessageModerator();
68 }
69 return instance;
70 }
71
72
73 /**
74 Default contructor is private to prevent others from instantiating this class
75 without using the factory.
76 Initializes the static members.
77 **/
78 private MessageModerator() {
79 initializeBlockList();
80 }
81 /**
82 Helper method that does the "heavy lifting" to load up the dictionaries
83 from the database.
84 Should only run once to initialize the static member which is used for
85 subsequent validations.
86 **/
87 private void initializeBlockList() {
88 if (blocklistedWords==null) {
89 // Fill list of blocklisted words
90 // ...
91 }
92 }
93}