リストビューから取引先責任者へ一括メールを送るApex実装
リストビューで選択した取引先責任者へ、まとめてメールを送りたいときの実装です。ループの中でメールを送るとsendEmailの呼び出し回数の上限にすぐ当たります。まとめて1回で送る形に組み直します。
なぜ1回にまとめて送るのか
選択した取引先責任者へメールを送るとき、1件ずつループの中で Messaging.sendEmail() を呼び出すと、送信件数がすぐに頭打ちになります。Messaging.sendEmail() の呼び出し回数そのものが、1トランザクションあたり10回までに制限されているからです。選択件数ではなく「呼び出した回数」が数えられる点が、ここでのつまずき所です。
メールをまとめて1回の呼び出しで送れば、選択件数が増えても呼び出し回数は1回のままです。
Visualforceページ
一括メール送信の画面を、標準コントローラの拡張として作成します。
BulkSendEmailContact.page
<apex:page standardController="Contact" recordSetVar="records" lightningStyleSheets="true" extensions="BulkSendEmailContactController"> <apex:pageMessages id="pageMessages" /> <apex:form> <apex:pageBlock title="一括メールを送信する"> <apex:pageBlockButtons location="top" rendered="{!isNotEmpty}"> <apex:commandButton value="送信" action="{!sendEmail}" reRender="pageMessages" /> </apex:pageBlockButtons> <apex:pageBlockTable value="{!contacts}" var="contact" rendered="{!isNotEmpty}"> <apex:column headerValue="姓名" value="{!contact.Name}" /> <apex:column headerValue="TO" value="{!contact.Email}" /> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>
Contactのリストビューから複数選択したレコードを受け取る画面です
Apexクラス
メールはループの中では送りません。送るメッセージをいったんリストに集め、ループを抜けてから1回で送ります。
BulkSendEmailContactController.cls
public with sharing class BulkSendEmailContactController { private List<Contact> contacts; public BulkSendEmailContactController(ApexPages.StandardSetController controller) { Set<Id> contactIds = (new Map<Id, sObject>(controller.getSelected())).keySet(); if (contactIds.isEmpty()) { ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'メール送信対象を選択してください。')); return; } contacts = [ SELECT Name, Email FROM Contact WHERE Id IN :contactIds AND Email != null ]; if (contacts.isEmpty()) { ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'メールアドレスを持つ送信対象が存在しません。')); } } public List<Contact> getContacts() { return contacts; } public Boolean getIsNotEmpty() { return contacts != null && !contacts.isEmpty(); } public PageReference sendEmail() { List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>(); for (Contact contact : contacts) { String body = 'テストメールを送信しています。'; Messaging.SingleEmailMessage singleEmail = new Messaging.SingleEmailMessage(); singleEmail.setToAddresses(new String[]{contact.Email}); singleEmail.setSubject('テストメール送信'); singleEmail.setHtmlBody(body.replace('\n', '<br/>')); singleEmail.setPlainTextBody(body.stripHtmlTags()); singleEmail.setBccSender(true); emails.add(singleEmail); } if (!emails.isEmpty()) { Messaging.sendEmail(emails); } return null; } }
選択件数にかかわらずMessaging.sendEmail()の呼び出しは1回だけです
Messaging.sendEmail() を1件ずつループの中で呼び出す形だと、選択件数が10件を超えた時点で、11件目以降が Limits.getLimitEmailInvocations()(1トランザクションあたり10回)の上限に当たって失敗します。選択件数を数えて上限と比べても、実際に効いているのは「呼び出した回数」なので意味がありません。送るメッセージをリストにまとめ、ループの外で1回だけ Messaging.sendEmail(emails) を呼びます。リストビューからボタンで開く
リストビューで選択したレコードは、標準セットコントローラ(recordSetVar)を使うVisualforceページへそのまま渡ります。コントローラ拡張ではgetSelected()で受け取ります。
カスタムボタンを作成する
オブジェクトマネージャの「取引先責任者」で「ボタン、リンク、アクション」を開き、新規ボタンを作成します。表示の種類は「リストボタン」、コンテンツソースは「Visualforceページ」を選びます。
ボタンの内容を設定する
Visualforceページの一覧から
BulkSendEmailContactを選んで保存します。選択した取引先責任者が、まとめてページへ渡ります。リストビューの検索レイアウトに追加する
「検索レイアウト」の「取引先責任者リストビュー」を編集し、作成したボタンをリストビューのボタンとして追加します。
動作確認
取引先責任者を複数作成する
メールアドレスを入力した取引先責任者を、テスト用に複数作成します。
リストビューから選択する
作成した取引先責任者をリストビューで選択し、追加したボタンを押します。
送信対象を確認して送る
一覧に選択した取引先責任者が表示されることを確認し、「送信」ボタンを押します。
送信結果を確認する
送信対象の受信箱にテストメールが届いていることを確認します。
ここで間違えやすい
| 間違い | 何が起きるか |
|---|---|
ループの中でMessaging.sendEmail()を都度呼ぶ | 呼び出し回数が1トランザクションあたり10回を超えると失敗します |
選択件数をLimits.getLimitEmailInvocations()と比べる | この値は呼び出し回数の上限であって、選択件数の上限ではありません |
| メールアドレスが空の取引先責任者を対象に含める | 送信時にエラーになります。SOQLでEmail != nullを条件に含めます |
| 送信ユーザーのメールアドレスが未検証 | Apexからのメール送信にはドメインとユーザーのメール確認が必要です。送信できない場合はまずここを確認します |
確認した環境
- 2026年9月 / Salesforce Summer '26(API バージョン 67.0)時点の公式ドキュメントで、
Messaging.sendEmail()の呼び出し回数の上限と、組織の日次メール送信上限を確認しています - 組織の日次のメール送信上限は、標準では外部アドレス宛て5,000件/日です。この一括送信もこの上限を消費します
まとめ
Messaging.sendEmail()は1トランザクションあたり10回までしか呼び出せません。選択件数ではなく呼び出し回数が制限されます- 送信するメッセージはいったんリストに集め、ループの外で1回だけ
Messaging.sendEmail()を呼びます - リストビューのカスタムボタンは、コンテンツソースをVisualforceページにし、選択したレコードを
getSelected()で受け取ります - 一括送信も組織の日次メール送信上限(標準5,000件/日)を消費します
- Apexからのメール送信には、送信ユーザーのメールアドレス確認が必要です
参考:当時の画面
記事を最初に書いた当時の画面です。いまの手順と違うところは、各画像の説明に書いています。
Salesforceの導入・運用についてご相談ください
導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。