Ga naar de inhoud
CRMdata
  • Home
  • Nieuws
  • Events
  • Clouds
    • Marketing Cloud
    • Sales Cloud
    • Service Cloud
  • Skills
    • Administrator
    • Developer
  • Over CRMData
Zoeken

Mass E-mail sturen met SF Flow en APEX

  • No Comments
  • juni 28, 2024
  • 1:54 pm

Via de Salesforce Flow actie: Send Mail, kun je maar naar 5 contactpersonen tegelijkertijd mailen. Dit is vaak veel te weinig. Hier zijn een aantal oplossingen voor. Zo zou je de “Send mail” actie in een loop kunnen zetten, maar dit is niet best-practice. Wil je het op een goede manier oplossen, dan zul je APEX moeten raadplegen. In deze tutorial gaan we starten met een flow en daarna de Mass E-mail verzenden met APEX. Uiteraard wordt ook alles gelogd bij de activity!

Use Case

In mijn geval wil ik een herinneringsmail sturen naar iedereen die een evenement bij wil wonen. Om dit voor elkaar te krijgen heb ik eerst een Record Triggered Flow gemaakt op het desbetreffende object en vervolgens iedereen die zich nog niet geannuleerd heeft in een Collection Variabele gezet. Verder heb ik het juiste template Id opgehaald en deze 2 waarden worden vervolgens naar APEX gestuurd om de mail te sturen.

APEX Script voor Mass E-mail

Eigenlijk moeten we beginnen met het APEX-script, aangezien je in de Salesforce Flow naar de APEX moet verwijzen, maar voor deze tutorial is het handig om te zien welke 2 waarden er naar het APEX script gestuurd worden. Hieronder toon ik het volledige Salesforce Mass E-mail script en we lopen het daarna stap voor stap langs:
public class BatchEmailReminderSender implements Database.Batchable<SObject> {

    public List<Evenement_bezoeker__c> bezoekers;
    public Id emailTemplateId;

    public BatchEmailReminderSender(List<Evenement_bezoeker__c> bezoekers, Id templateId) {
        this.bezoekers = bezoekers;
        this.emailTemplateId = templateId;
    }

    public Database.QueryLocator start(Database.BatchableContext bc) {
        // Query om de gerelateerde contactrecords op te halen, inclusief het Name veld
        return Database.getQueryLocator([
            SELECT Id, E_mail__c, Contact__c, Contact__r.Email, Name
            FROM Evenement_bezoeker__c
            WHERE Id IN :bezoekers
        ]);
    }

    public void execute(Database.BatchableContext bc, List<SObject> scope) {
        List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

        for (Evenement_bezoeker__c bezoeker : (List<Evenement_bezoeker__c>) scope) {
            if (bezoeker.Contact__c != null && bezoeker.Contact__r.Email != null) {
                Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
                email.setToAddresses(new String[] { bezoeker.Contact__r.Email });
                email.setTemplateId(emailTemplateId);
                email.setTargetObjectId(bezoeker.Contact__c);
                email.setWhatId(bezoeker.Id); // Stel de WhatId in op het Evenement_bezoeker__c record
                email.setSaveAsActivity(true); // Zorg ervoor dat de e-mail zelf wordt gelogd als een activiteit
                emails.add(email);
            }
        }

        Messaging.sendEmail(emails);
    }

    public void finish(Database.BatchableContext bc) {
        // Eventuele opruimtaken
    }

    public class EmailBatchRequest {
        @InvocableVariable
        public List<Evenement_bezoeker__c> bezoekers;

        @InvocableVariable
        public Id emailTemplateId;
    }

    @InvocableMethod
    public static void startBatch(List<EmailBatchRequest> requests) {
        for (EmailBatchRequest req : requests) {
            BatchEmailReminderSender batch = new BatchEmailReminderSender(req.bezoekers, req.emailTemplateId);
            Database.executeBatch(batch, 200);
        }
    }
}

APEX Script maken met VS Code

Om op een makkelijke manier een APEX script te starten, kun je in Visual Studio Code in de terminal het volgende commando gebruiken:

sf apex generate class –name BatchEmailReminderSender –output-dir force-app/main/default/classes

Er wordt dan gelijk 2 bestanden aangemaakt:
-BatchEmailReminderSender.cls
-BatchEmailReminderSender.cls-meta.xml

De .xml houden we gewoon standaard en zullen ons nu focussen op de .cls. We beginnen bovenaan:

public class BatchEmailReminderSender implements Database.Batchable<SObject> {

public List<Evenement_bezoeker__c> bezoekers;
public Id emailTemplateId;

public BatchEmailReminderSender(List<Evenement_bezoeker__c> bezoekers, Id templateId) {
    this.bezoekers = bezoekers;
    this.emailTemplateId = templateId;
}

Door de interface tabase.Batchable te implementeren, maakt de klasse gebruik van het batch framework van Salesforce. Dit framework vereist dat de klasse drie methoden implementeert: start, execute en finish. Deze methoden komen later terug in de code. Vervolgens worden er twee klassenvariabelen gedefinieerd: een lijst van evenementbezoekers en een e-mailsjabloon ID. De constructor initialiseert de BatchEmailReminderSender klasse met de gegeven lijst van bezoekers en het e-mailsjabloon ID. Wanneer een object van deze klasse wordt gemaakt, worden de bezoekers en emailTemplateId ingesteld met de waarden die aan de constructor worden doorgegeven. Deze waarden zijn afkomstig van de Salesforce Flow.

public Database.QueryLocator start(Database.BatchableContext bc) {
    // Query om de gerelateerde contactrecords op te halen, inclusief het Name veld
    return Database.getQueryLocator([
        SELECT Id, E_mail__c, Contact__c, Contact__r.Email, Name
        FROM Evenement_bezoeker__c
        WHERE Id IN :bezoekers
    ]);
}

Batch Framework: Start

De start methode is een verplicht onderdeel van een klasse die de Database.Batchable<SObject> interface implementeert. Deze methode initialiseert het batchproces en specificeert welke records moeten worden verwerkt.

Database.QueryLocator: Dit is het type dat door de methode wordt geretourneerd. Een QueryLocator is een object dat een grote set van records in Salesforce vertegenwoordigt.

Het object Database.BatchableContext bc: is een contextobject dat door Salesforce wordt doorgegeven aan de batchmethode en kan worden gebruikt om contextinformatie te verkrijgen over het batchproces.

return Database.getQueryLocator([…]): Deze regel geeft een QueryLocator object terug dat door een SOQL-query wordt geproduceerd. Het stuk SOQL spreekt volgens mij voor zich en zal in ieder geval anders zijn.

public void execute(Database.BatchableContext bc, List<SObject> scope) {
    List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

    for (Evenement_bezoeker__c bezoeker : (List<Evenement_bezoeker__c>) scope) {
        if (bezoeker.Contact__c != null && bezoeker.Contact__r.Email != null) {
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
            email.setToAddresses(new String[] { bezoeker.Contact__r.Email });
            email.setTemplateId(emailTemplateId);
            email.setTargetObjectId(bezoeker.Contact__c);
            email.setWhatId(bezoeker.Id); // Stel de WhatId in op het Evenement_bezoeker__c record
            email.setSaveAsActivity(true); // Zorg ervoor dat de e-mail zelf wordt gelogd als een activiteit
            emails.add(email);
        }
    }

    Messaging.sendEmail(emails);
}

Batch Framework: Execute

De execute methode is de tweede methode die verplicht is voor de Database.Batchable<SObject> interface. Deze methode voert de hoofdlogica uit voor elke batch van records.
  • Database.BatchableContext bc: Net als hierboven beschreven is dit het contextobject dat door Salesforce wordt doorgegeven aan de batchmethode.
  • List<SObject> scope: Een lijst van Salesforce-objecten die in deze batch moeten worden verwerkt. In ons geval zijn dit de Evenement_bezoeker__c objecten.
  • List<Messaging.SingleEmailMessage> emails: Een lijst om de e-mailberichten op te slaan die verzonden moeten worden.
  • Vervolgens wordt er met een for-loop door alle Evenement_bezoeker__c objecten gegaan en wordt de scope lijst gecast naar een lijst van Evenement_bezoeker__c objecten. Met het if-statement wordt er nog een extra check gedaan dat het gerelateerde contact en het e-mailadres van het contact niet null zijn.
  • Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(): Maakt een nieuw e-mailbericht aan.
  • email.setToAddresses(new String[] { bezoeker.Contact__r.Email }): Stelt het “To” e-mailadres in op het e-mailadres van het gerelateerde contact.
  • email.setTemplateId(emailTemplateId): Stelt het e-mailsjabloon ID in op de emailTemplateId die aan de klasse is doorgegeven (via de gemaakte flow).
  • email.setTargetObjectId(bezoeker.Contact__c): Stelt het doelobject ID in op het gerelateerde contact.
  • email.setWhatId(bezoeker.Id): Stelt het WhatId in op het Evenement_bezoeker__c record. Dit koppelt de e-mailactiviteit aan het evenementbezoeker record en gebruiken we om de merge-tags van dit object te kunnen gebruiken in de e-mailtemplate.
  • email.setSaveAsActivity(true): Zorgt ervoor dat de e-mail wordt gelogd als een activiteit op het contact- en evenementbezoeker record.
  • emails.add(email): Voegt het e-mailbericht toe aan de lijst van e-mailberichten die verzonden moeten worden.
  • Messaging.sendEmail(emails): Verstuurt de e-mails die in de lijst emails zijn verzameld.
public void finish(Database.BatchableContext bc) {
        // Eventuele opruimtaken
    }

    public class EmailBatchRequest {
        @InvocableVariable
        public List<Evenement_bezoeker__c> bezoekers;

        @InvocableVariable
        public Id emailTemplateId;
    }

    @InvocableMethod
    public static void startBatch(List<EmailBatchRequest> requests) {
        for (EmailBatchRequest req : requests) {
            BatchEmailReminderSender batch = new BatchEmailReminderSender(req.bezoekers, req.emailTemplateId);
            Database.executeBatch(batch, 200);
        }
    }
}

Batch Framework: Finish

  • Dit is de finish methode, een van de verplichte methoden voor een klasse die de Database.Batchable<SObject> interface implementeert. De klasse is momenteel leeg omdat er geen specifieke opruimtaken of aanvullende logica nodig zijn na voltooiing van de batchverwerking.
  • public class EmailBatchRequest: Deze klasse is een container voor de parameters die nodig zijn om een batchverwerking te starten. De 2 variabelen die via de flow meegestuurd zijn, worden hier als @InvocableVariable weggeschreven, waardoor ze kunnen worden ingesteld via processen, zoals Flow in Salesforce.
  • @InvocableMethod: Deze annotatie maakt de methode toegankelijk voor invocable processen zoals Flow in Salesforce (vergelijkbaar met de variabele).
  • for (EmailBatchRequest req : requests): Itereert door elk EmailBatchRequest object in de requests lijst.
  • BatchEmailReminderSender batch = new BatchEmailReminderSender(req.bezoekers, req.emailTemplateId): Maakt een nieuwe instantie van de BatchEmailReminderSender klasse met de bezoekerslijst en het e-mailsjabloon ID uit het verzoek.
  • Database.executeBatch(batch, 200): Start de batchverwerking met de aangemaakte BatchEmailReminderSender instantie. De tweede parameter 200 geeft aan dat de batch in sets van 200 records moet worden verwerkt.
  • for (EmailBatchRequest req : requests): Itereert door elk EmailBatchRequest object in de requests lijst. Daarna wordt er een nieuwe instantie aangemaakt van de BatchEmailReminderSender klasse met de bezoekerslijst en het e-mailsjabloon ID uit het verzoek. Vervolgens start de batchverwerking in batches van 200 per keer.

Conclusie

Omdat Salesforce Flow een limiet van maximaal 5 e-mailberichten per keer hanteert, kun je geen Mass E-mail sturen via Salesforce Flow. Daarom heb ik de meeste stappen wel in Flow gebouwd, omdat dat sneller is, maar het daadwerkelijk verzenden van de E-mails wordt afgehandeld via APEX. Op deze manier combineer je een “Best of Breed” qua tooling.

Laat een reactie achter Reactie annuleren

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Laatste artikelen

AMPscript voor beginners: zo maak je je e-mails slimmer (en leuker)

Heb je ooit een e-mail gekregen die zo persoonlijk voelde dat het leek alsof iemand hem speciaal voor jou had geschreven? Grote kans dat daar

Lees Verder »
30 maart 2025 Geen reacties

E-mail Template in Marketing Cloud Maken

In Marketing Cloud wil je mails gaan versturen met een template die past bij het imago van jouw bedrijf of het bedrijf waar je voor

Lees Verder »
7 maart 2025 Geen reacties

Synchronized Data Extensions in Marketing Cloud

Nadat je de koppeling tussen Salesforce CRM en Marketing Cloud gelegd hebt, kun je gebruikmaken van synchronized data extensions. Op deze manier kun je data

Lees Verder »
4 maart 2025 Geen reacties

Komende Salesforce events

No events found
Instagram Twitter Linkedin-in Facebook-f
Salesforce Data

Op CRMData lees je het laatste nieuws, trends en updates over Salesforce van de Sales Cloud, Marketing Cloud en Service Cloud voor Administrators, Platform Builders, Developers en Markeers!

Quick Links
  • Know More About Us
  • Visit Store
  • Let's Connect
Algemeen
  • Privacy Policy
  • Over Mij
Copyright © 2025
CRMdata
Scroll naar boven