Let's attempt to approach this systematically, one step at a time.
Step 1: Create an Apex controller for email transmission.
For the sake of simplicity, we'll focus on sending emails to the primary contact associated with an opportunity.
public class EmailController {
@AuraEnabled
public static void sendEmail(String opportunityId, String templateName) {
Opportunity opportunityRecord = [
SELECT (
SELECT ContactId, Contact.Email
FROM OpportunityContactRoles
WHERE IsPrimary = TRUE
)
FROM Opportunity
WHERE Id = :opportunityId
];
if (!opportunityRecord.OpportunityContactRoles.isEmpty()) {
OpportunityContactRole primaryContact = opportunityRecord.OpportunityContactRoles[0];
EmailTemplate template = [SELECT Id FROM EmailTemplate WHERE Name = :templateName];
List<String> toAddresses = new List<String>{ primaryContact.Contact.Email };
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
email.setTemplateId(template.Id);
email.setTargetObjectId(primaryContact.ContactId);
email.setWhatId(opportunityId);
email.setToAddresses(toAddresses);
email.setSaveAsActivity(false);
emails.add(email);
Messaging.sendEmail(emails);
} else {
throw new AuraHandledException('No primary contact found');
}
}
}
The given code receives two parameters, opportunityId
and templateName
. It proceeds to fetch the Opportunity record along with its primary contact role. Next, it checks if the contact role is not empty; otherwise, an exception is thrown. Finally, an email message is prepared and sent to the primary contact using the specified template.
Step 2: Develop an LWC (Lightning Web Component) with the Action type, allowing placement on the Opportunity record page.
HTML (no refactoring needed as this is an Action):
<template>
</template>
JS
import {LightningElement, api} from 'lwc';
import {ShowToastEvent} from "lightning/platformShowToastEvent";
import sendEmail from '@salesforce/apex/EmailController.sendEmail';
const TOAST_TITLE = 'Send Email';
export default class SendEmailAction extends LightningElement {
@api recordId;
@api invoke() {
sendEmail({
opportunityId: this.recordId,
templateName: 'TestEmailTemplate'
})
.then(() => {
this.dispatchEvent(new ShowToastEvent({
title: TOAST_TITLE,
message: 'Email sent successfully',
variant: 'success'
}))
})
.catch(error => {
this.dispatchEvent(new ShowToastEvent({
title: TOAST_TITLE,
message: error.body?.message || 'Unexpected error',
variant: 'error'
}))
});
}
}
Metadata
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>58.0</apiVersion>
<description>Send Email Action</description>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordAction</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordAction">
<actionType>Action</actionType>
</targetConfig>
</targetConfigs>
<masterLabel>Send Email Action</masterLabel>
</LightningComponentBundle>
In this step, we will utilize the Apex method created in Step 1 to send emails when our action is invoked. Additionally, we will handle exceptions and display them in a popup toast.
Step 3: Generate an action on the Opportunity object.
- Click on the Setup Gear button in your organization.
- Go to the Object Manager tab and locate Opportunity.
- Select Buttons, Links, and Actions.
- Click on the "New Action" button in the top right corner.
- Configure as follows:

- Click Save button.
Step 4: Add your new Action button to the Opportunity Layout.
- Go to the Object Manager tab and locate Opportunity.
- Select Page Layouts
- Select the desired layout.
- Find you Action in "Mobile & Lightning Actions" section.
- Perform a drag-and-drop operation to add this action to the layout.
- Click Save button.
Step 5: Congratulations, everything is set up. Now you can navigate to the Opportunity record page and test the functionality of your new action button.

I hope this information proves helpful. Happy coding! :)
P.S If you have any questions, feel free to ask me in the comments section. I'll be glad to assist.