What Method Signature and Parameters the Messaging.sendEmail() Method Accepts
According to the Salesforce Outbound Email Developer Guide, the method signature is:
static Messaging.SendEmailResult[] sendEmail(
Messaging.Email[] emails,
Boolean allOrNone
)
emails: Array of SingleEmailMessage or MassEmailMessage objects to send. allOrNone: If true, all emails fail if any one fails. If false (default), partial success is allowed. Returns: Array of SendEmailResult objects with success/failure status for each email.
How to Send a Basic Email Using the Messaging.sendEmail() Method
Simple implementation:
// Create email message
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
email.setToAddresses(new String[] {'recipient@example.com'});
email.setSubject('Your Order Confirmation');
email.setHtmlBody('<h1>Thank You!</h1><p>Your order has been confirmed.</p>');
// Send email
Messaging.SendEmailResult[] results = Messaging.sendEmail(
new Messaging.SingleEmailMessage[] { email }
);
What the SendEmailResult Object Returns After Each Send Operation
As documented in the SendEmailResult Class Reference, the result object provides send status: isSuccess() returns a Boolean indicating if the email was sent successfully. getErrors() returns a List of SendEmailError objects if the send failed. SendEmailError properties include: getMessage() for a human-readable error description, getStatusCode() for the error code (e.g., INVALID_EMAIL_ADDRESS, LIMIT_EXCEEDED), getFields() for the list of fields that caused the error, and getTargetObjectId() for the ID of the target record if applicable.
How to Implement Proper Error Handling for sendEmail() Results
Proper error handling implementation:
List emails = new List();
// ... build email messages ...
Messaging.SendEmailResult[] results = Messaging.sendEmail(emails, false);
Integer successCount = 0;
Integer failCount = 0;
List errorMessages = new List();
for (Integer i = 0; i < results.size(); i++) {
if (results[i].isSuccess()) {
successCount++;
} else {
failCount++;
for (Messaging.SendEmailError error : results[i].getErrors()) {
errorMessages.add('Email ' + i + ': ' + error.getMessage());
}
}
}
System.debug('Sent: ' + successCount + ', Failed: ' + failCount);
What Governor Limits the Send Email API Imposes on Each Transaction
Key Salesforce email limits for sendEmail(): Invocations Per Transaction: Maximum 10 sendEmail() calls per Apex transaction. Emails Per Call: 100 SingleEmailMessage or 10 MassEmailMessage objects per call. Daily Single Email: 5,000 emails per day, organization-wide. Daily Mass Email: 5,000 external recipients per day. Recipients Per Email: 100 for SingleEmailMessage, 250 for MassEmailMessage.
How to Bulkify sendEmail() Calls for Efficient High-Volume Delivery
Efficient bulk sending:
public class EmailSender {
public static void sendBulkEmails(List contacts, Id templateId) {
List emails = new List();
for (Contact c : contacts) {
if (c.Email != null && !c.HasOptedOutOfEmail) {
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
email.setTargetObjectId(c.Id);
email.setTemplateId(templateId);
email.setSaveAsActivity(true);
emails.add(email);
}
}
if (!emails.isEmpty()) {
Messaging.sendEmail(emails, false);
}
}
}
How to Send Triggered Emails from Record Events Using sendEmail()
Send triggered emails from record events:
trigger OrderConfirmation on Order__c (after insert) {
List emails = new List();
Id templateId = [SELECT Id FROM EmailTemplate
WHERE DeveloperName = 'Order_Confirmation'].Id;
for (Order__c order : Trigger.new) {
if (order.Contact__c != null) {
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
email.setTargetObjectId(order.Contact__c);
email.setWhatId(order.Id);
email.setTemplateId(templateId);
email.setSaveAsActivity(true);
emails.add(email);
}
}
if (!emails.isEmpty()) {
Messaging.sendEmail(emails);
}
}
How to Send Template-Based Emails with Merge Fields via sendEmail()
Send with email templates:
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
email.setTemplateId(templateId); // Required for template
email.setTargetObjectId(contactId); // Contact/Lead/User for merge
email.setWhatId(opportunityId); // Related record for merge
email.setSaveAsActivity(true);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });
How the allOrNone Parameter Controls Partial Success Behavior
Control partial success behavior: allOrNone = true: If any email fails, all emails in the batch fail. Use when emails are logically connected. allOrNone = false (default): Emails succeed or fail independently. Use for batch sends where partial success is acceptable.
// All-or-none: entire batch fails if any email fails
Messaging.sendEmail(emails, true);
// Partial success allowed (recommended for batch)
Messaging.sendEmail(emails, false);
Which Common Error Codes the sendEmail() Method Returns on Failure
Handle these common SendEmailError status codes: INVALID_EMAIL_ADDRESS: Malformed email address in recipients. LIMIT_EXCEEDED: Daily sending limit or per-transaction limit reached. NO_MASS_MAIL_PERMISSION: User lacks permission to send mass email. REQUIRED_FIELD_MISSING: Missing required field, like a template or a recipient. TEMPLATE_NOT_ACTIVE: Referenced email template is not active.
Send Email API Best Practices for Maximizing Delivery and Reliability
Batch Emails: Collect emails in a list and make a single sendEmail() call to conserve invocation limits. Check Limits First: Use Limits.getEmailInvocations() and Limits.getLimitEmailInvocations() before sending. Handle All Results: Always iterate through the SendEmailResult array to catch failures. Use allOrNone=false: Allow partial success for batch sends to maximize delivery. Respect Opt-Out: Filter for opt-out preferences before building email list. Log for Tracking: Enable saveAsActivity for email tracking.
What Limitations Make Native sendEmail() Insufficient for Large-Scale Operations
Daily Ceiling: 5,000/day limit constrains email campaigns. No Tracking: API doesn’t provide open rates or click tracking natively. Shared Infrastructure: Email deliverability depends on Salesforce’s shared IPs. No Scheduling: sendEmail() executes immediately—scheduling requires Scheduled Apex. Synchronous: Method is synchronous—large sends impact transaction performance.
How Send Email API Connects with Marketing Workflows and Campaign Attribution
Campaign Tracking: Link sent emails to email campaigns for attribution. Automation Flows: Trigger sendEmail() from email automation workflows. Sequences: Build email sequences and drip campaigns with scheduled Apex. Follow-Ups: Create follow-up sequences based on engagement. List Management: Build contact lists for targeted sends.
Enhanced Send Capabilities That Scale Beyond Native API Limits
For organizations needing enhanced send capabilities beyond API limits, MassMailer operates 100% native to Salesforce. Unlimited mass email without governor constraints. Complete email capabilities with email analytics and email metrics. Use the email builder for professional templates.
Key Takeaways
- Messaging.sendEmail() executes email delivery with an array of email objects and returns results
- Governor limits include 10 invocations per transaction and 5,000 daily emails
- Use allOrNone=false for batch sends to allow partial success
- Native solutions extend capabilities beyond API limitations
Stop writing custom Apex email code and fighting governor limits. Install MassMailer free to replace sendEmail() workarounds with unlimited native Salesforce sending, automatic engagement tracking, and built-in drip sequences—no Apex required. Discover best-in-class email capabilities with dedicated IPs today →