GetEmailMessageIds

Overview

Step 3 of the pipeline (email path). Given a scope from BuildScopeForRecord, queries Salesforce EmailMessage records linked to the in-scope records via ActivityRelation. Returns a page of EmailMessage IDs; the caller is responsible for querying EmailMessage directly for whatever fields are needed.

Emails are record-scoped — the query is driven by the scope records' IDs, not by phone numbers. This is why this step is reached directly from step 1 rather than from step 2. The SharingRule passed at construction controls whether Salesforce row-level sharing is enforced; use WithSharing to honour the running user's CRM visibility.

Request

Obtain the Request via BuildScopeForRecord.Response.toGetEmailMessageIdsRequest().

GetEmailMessageIds.IHandler handler =
    GetEmailMessageIds.construct(SharingRule.WithSharing);
GetEmailMessageIds.Response emailResult =
    handler.execute(
        scopeResult.toGetEmailMessageIdsRequest()
            .sentAfter(cutoff)
            .take(50)
    );
Method Description
sentAfter(Datetime cutoff) Filter to emails sent after this timestamp.
sentBefore(Datetime cutoff) Filter to emails sent before this timestamp.
take(Integer n) Page size. Maximum 50, default 20.
forNextPage(GetEmailMessageIds.Response prev) Continue from the previous response's cursor.

Use SharingRule.WithSharing at construction to honour the running user's CRM visibility — EmailMessage records are standard Salesforce CRM objects and should follow Salesforce sharing rules.

Response

Member Type Description
emailMessageIds Set<Id> IDs of matching EmailMessage records for this page.
moreAvailable Boolean true if earlier pages exist. Pass this response to forNextPage() on the next request.

The service returns IDs only — query EmailMessage directly for subject, body, sender, recipients, or any other fields you need:

List<EmailMessage> emails = [
    SELECT Id, Subject, TextBody, FromAddress, MessageDate
    FROM EmailMessage
    WHERE Id IN :emailResult.emailMessageIds
    WITH USER_MODE
];

Testing

MockGetEmailMessageIds is a package-provided test double. Call use() to install it for the current test transaction, then returning() with the email message IDs it should return. Use withMoreAvailable(true) when testing paging. If your code calls forNextPage() on the response, also call withOldestMessageDate() to populate the paging cursor.

@isTest
static void myTest() {
    Id emailId = [SELECT Id FROM EmailMessage LIMIT 1].Id;

    MockGetEmailMessageIds.use()
        .returning(new Set<Id>{ emailId });

    MyService.run(someRecordId);
}

When testing paging behaviour:

MockGetEmailMessageIds.use()
    .returning(firstPageIds)
    .withMoreAvailable(true)
    .withOldestMessageDate(Datetime.now().addDays(-7));
Method Description
use() Installs this instance as the handler for the current test transaction. Returns the instance for chaining.
returning(Set<Id> emailMessageIds) Configures the IDs returned by execute(). Passing null is equivalent to an empty set.
withMoreAvailable(Boolean value) Sets the moreAvailable flag on the response. Defaults to false.
withOldestMessageDate(Datetime value) Populates the paging cursor used by forNextPage(). Only needed when testing code that pages through results.