ローコードアプリからメールを送るための機能群です。フィールドを置くだけで送信ボタンになり、 宛先・件名・本文はレコードの値から組み立てられます。スクリプトから動的に送ることもできます。
| やりたいこと | 使うもの |
|---|---|
| レコードの内容で 1 通送る (受付通知・依頼メールなど) | MailField |
| 名簿 (リスト) の全員に一斉送信する (キャンペーン・お知らせ) | BulkMailField |
| 送信した記録を残す | 送信履歴モジュール (メールのセットアップで生成) |
差出人は常に送信インフラ設定のシステム送信者 (SenderMailAddress / SenderDisplayName) です。
本人のアカウント (担当者個人の Gmail / Microsoft 365 / SMTP) から送る用途は、トークンを各自の PC にだけ置く Windows アプリ MailSender が担います (サーバーにはトークンを置かない)。
- モジュールの詳細レイアウトに MailField を置く
- プロパティに宛先と文面を設定する
- 宛先変数:
Email.Value(自レコードのフィールド。リンク先ならCustomer.Email.Value) - 件名:
注文確認: {OrderNo.Value} - 本文:
{Customer.Name.Value} 様\nご注文を受け付けました。
- 宛先変数:
- サーバーの
appsettings.jsonに送信インフラの設定を書く (後述)
これで詳細画面に送信アイコンのボタンが現れ、押すと確認ダイアログ (件名・宛先数) の後にそのレコードの値でメールが送られます。
文字付きのボタンにしたい場合は ButtonField を置いてスクリプトから フィールド名.Send() を呼びます。
{変数} は自レコードの値で置き換えられます (数値・日付はフィールドの書式で整形)。
「配信 (1 レコード)」と「配信対象の名簿 (リスト)」を持つモジュールに BulkMailField を置き、
宛先リストのフィールドを指定します。名簿の全行 (画面のページングとは無関係) に送信され、
文面の {変数} は宛先の行ごとに解決されます。宛先アドレスはサーバー側で解決されるため
クライアントには渡りません。
Tools > メールのセットアップ で、送信履歴モジュール (+送信明細) と
サーバー設定の案内をまとめて用意できます (使うものだけ選べます)。
コマンドラインからは <designer.exe> mail-setup "<projectDir>" で同じことができます。
レイアウトに置くと送信ボタン、置かなくてもスクリプトの Send() から使えます。
各項目は 値 と 変数 のペアで指定します。値が入っていれば値、空なら変数を自レコードで解決します。
| ペア | 説明 |
|---|---|
| 宛先 / 宛先変数 | 固定アドレス (カンマ・セミコロン区切りで複数可) か、Email.Value のような変数 (リンクパス可) |
| Cc / Cc変数、Bcc / Bcc変数 | 宛先と同じ規則 |
| 件名 / 件名変数 | 件名テンプレート。どちらの経路でも {変数} が自レコードで解決される |
| 本文 / 本文変数 | 本文テンプレート (件名と同じ規則) |
| 返信先 / 返信先変数 | 返信先アドレス |
| プロパティ | 説明 |
|---|---|
| HTML本文 | 本文を HTML として送る |
| メールインフラ名 | どの送信インフラで送るかの呼び名。通常は空にしてサーバー設定の既定を使う |
| プレビューボタンを表示 | 送信アイコンの横にプレビュー (HTML ダウンロード) を出す (既定 ON) |
- 宛先 (値か変数) と、件名・本文のどちらかは必須 (デザインチェックが検証)
- 変数はデザインチェックで存在検証され、フィールドのリネームに追従します
// デザインどおりに送る (ButtonField の OnClick 等から)
var result = ReceiptMail.Send(); // MailSendResult (IsSuccess / Failures)
if (!result.IsSuccess) Toaster.Error("送信失敗: " + result.Failures[0].Error);
// 動的に組み立てて送る (設定した値は変数より優先)
ReceiptMail.To = "sato@example.com;suzuki@example.com";
ReceiptMail.Subject = "月次レポート {Month.Value}"; // 値も {変数} が解決される
ReceiptMail.Body = "今月のレポートを添付します。";
ReceiptMail.AddAttachment("report.xlsx", excel); // Excel オブジェクトを添付
ReceiptMail.AddTextAttachment("memo.txt", "テキスト添付");
ReceiptMail.Send(); // 添付は送信後にクリアされる| プロパティ | 説明 |
|---|---|
| 宛先リスト | 同一モジュール上の List / DetailList / TileList のフィールド名。その先のモジュールに一斉送信の宛先契約が必要 |
| 件名 / 件名変数、本文 / 本文変数 | MailField と同じ規則。{変数} は宛先行で解決される ({Contact.Name.Value} のようなリンクパス可) |
| HTML本文 / 返信先 / メールインフラ名 / プレビューボタンを表示 | MailField と同じ |
動作:
- ボタン押下 → 対象件数の確認ダイアログ
- サーバーが宛先リストの検索条件から宛先を解決して送信 (読み取り権限・行条件が効く)
- 宛先契約の 配信停止 (OptOut) が true の行と、アドレスが空の行はスキップ
- 未保存の変更があるレコード・新規レコードからは送れない (保存済みの状態が送信対象)
典型構成 (キャンペーン + 名簿):
メール配信 (MailCampaign) … 1 レコード = 1 配信
├── Title (Text) … 件名テンプレート
├── Body (Text 複数行) … 本文テンプレート
├── Members (DetailList → 配信対象) … 送る相手そのもの
└── BulkMail (BulkMailField) 宛先リスト = Members、件名変数 = Title.Value、本文変数 = Body.Value
配信対象 (CampaignMember) … 一斉送信の宛先契約を置く (Email = Contact.Email.Value / OptOut = Contact.メール拒否.Value)
├── Campaign (Link → メール配信)
└── Contact (Link → 担当者)
担当者 (Contact)
├── Email (Text)
└── メール拒否 (Boolean) … 配信停止。どの配信でも常に尊重される
スクリプトからは Send() (確認ダイアログなし・戻り値 MailSendResult) が使えます。
MailField / BulkMailField の送信ボタンの横に プレビュー ボタンがあり (プロパティ「プレビューボタンを表示」で非表示にできます)、 押すと自己完結の HTML ファイルがダウンロードされます。ブラウザで開くだけで、外部への通信はしません。 文面と宛先の解決は送信と同じサーバー経路なので、プレビューと実際の送信内容は一致します。
- 単発 (MailField): To / Cc / Bcc / 返信先 / 添付 / 件名 / 本文を 1 枚で表示
- 一斉 (BulkMailField): 左に宛先一覧、右に選んだ宛先で解決した件名・本文。除外された行も理由付き (配信停止 / アドレスなし) で一覧に残り、
「除外のみ」の絞り込み・検索・キーボード移動 (↑↓、
n= 次の除外) ができます。1 万件でも軽く動きます - 変数ハイライト: テンプレートの
{変数}が入った箇所に色が付き、原文の変数名がツールチップで見えます (空になった変数は「(空)」と表示) - HTML 本文は sandbox 内で描画。「ソースを表示」で切替
- 一覧に人の名前を出すには、宛先契約の任意役割 DisplayName (例:
Contact.Name.Value) を設定します - 一斉送信のプレビューは保存済みの内容 (テンプレート・名簿) で作られます。未保存の変更は反映されません
- スクリプトからは
フィールド名.Preview()で同じ HTML をダウンロードできます
UI もデータも持たない「宣言用」のフィールドです。役割 → フィールド (変数) の対応を宣言します。 必須の役割は表示名に「(必須)」が付き、それ以外は空にすれば「使わない」宣言になります。
| 契約 | 置く先 | 役割 | 使う機能 |
|---|---|---|---|
| 一斉送信の宛先契約 (BulkMailRecipientContractField) | 一斉送信の宛先リストが指すモジュール | Email (必須) / OptOut / DisplayName | BulkMailField の宛先解決・プレビューの一覧表示 |
| メール履歴契約 (MailHistoryContractField) | 送信履歴モジュール | SentAt (必須) / MailInfraName / Subject / TotalCount / SuccessCount / FailureDetails / SourceModule / SourceId / Details | 送信履歴の記録 |
| メール送信明細契約 (MailHistoryDetailContractField) | 送信明細モジュール (履歴の Details 一覧の参照先) | History (必須) / To (必須) / Subject / Body / IsSuccess / Error | 宛先ごとの明細 (任意) |
役割の値はフィールドのリネームに追従し、不在ならデザインチェックがエラーにします。
サーバー設定 Mail.HistoryModuleName に履歴モジュール名を書くと、単発・一斉すべての送信が
そのモジュールに 1 送信 1 レコードで記録されます (失敗明細は JSON)。
書き込みは操作ユーザーの権限に依存しないサーバー内部経路で行われ、履歴の失敗が送信を止めることはありません。
履歴モジュールはメールのセットアップで生成できます (一覧画面・ページリンク付き)。
送信明細 (任意): 履歴モジュールに明細モジュールへの一覧を置き、履歴契約の「送信明細の一覧」に設定すると、 1 宛先 1 行で「宛先・その宛先で解決した後の件名と本文・成否・失敗理由」が残ります。 テンプレートの変数が正しく展開されたか、誰に何を送ったかを後から確認できます。 セットアップの「送信明細モジュールも生成」(既定 ON) で明細モジュールごと揃います。 宛先アドレスと本文が残るので、履歴・明細モジュールの閲覧権限は管理者などに絞ってください。
- 差出人は常に送信インフラ設定のアドレス・表示名 (システム送信者)。部署共通アドレスなどはインフラ (呼び名) を分けて表現する
- 差出人アドレスを指定する手段はありません (なりすましの構造的排除)。クライアントが載せた From はサーバーで常に破棄される
- 本人のアカウント (担当者個人の Gmail / Microsoft 365 / SMTP) から送る用途は、トークンを各自の PC にだけ置く Windows アプリ MailSender が担います (サーバーにはトークンを置かない)
本人名義の送信は Windows アプリ MailSender (Tools/MailSender) で行います。
- Web で MailField / BulkMailField の プレビュー をダウンロードする (宛先・変数は解決済み。添付の内容も同梱される)
- そのプレビュー HTML を MailSender で開く (ダブルクリック / ドラッグ & ドロップ)
- 内容を確認して「送信」→ 本人の PC に DPAPI で保存したトークン (Gmail / Microsoft 365) または SMTP アカウントで送る。サーバーは関与しない
トークンの発行・破棄、Web アプリのシステム送信者用トークンの発行もこのアプリで行います。 使い方・ビルド方法は MailSender を参照してください。
"Mail": {
"DefaultInfraName": "Gmail", // 単発送信の既定インフラ (呼び名)
"DefaultBulkInfraName": "Gmail", // 一斉送信の既定インフラ (省略時は単発と同じ)
"HistoryModuleName": "MailHistory", // 送信履歴モジュール (空 = 記録しない)
"DebugRedirectAllTo": "" // 開発時: 全メールをこのアドレスへ転送 (空 = 無効)
},
"Smtp": {
"SenderMailAddress": "notify@your-domain.example",
"SenderDisplayName": "業務システム",
"Host": "smtp.your-domain.example",
"Port": "587",
"SSL": "true", // true: 465 は SSL 接続、他は STARTTLS / false: サーバーが対応していれば STARTTLS
"UserName": "", // 空 = SenderMailAddress で認証
"Password": "",
"MaxBulkCount": 10000
},
"GraphApi": {
"SenderMailAddress": "notify@your-domain.example",
"SenderDisplayName": "業務システム",
"TenantId": "", // クライアントシークレット認証では必須
"ClientId": "", // クライアントシークレット認証では必須
"ClientSecret": "", // 空 = DefaultAzureCredential (Managed Identity 等) で認証
"MaxBulkCount": 10000
},
"SendGrid": {
"SenderMailAddress": "notify@your-domain.example", // SendGrid で検証済みのアドレス
"SenderDisplayName": "業務システム",
"ApiKey": "", // 環境変数 SendGrid__ApiKey 推奨
"MaxBulkCount": 10000
},
"Gmail": {
"SenderMailAddress": "notify@your-domain.example",
"SenderDisplayName": "業務システム",
"ClientSecret": "client_secret.json のパス、または JSON そのもの",
"TokenSecret": "システム送信者のトークン (JSON のパス、または JSON / トークン文字列そのもの)",
"MaxBulkCount": 500
}Mailは共通設定、送信インフラごとの設定 (Smtp/GraphApi/SendGrid/Gmailなど) は独立したセクションです。使うものだけ書きますClientSecret/TokenSecretは値が.jsonで終わればファイルパス、それ以外は中身そのものとして扱います。 秘密をファイルで置きたくない場合は環境変数 (Gmail__ClientSecret/Gmail__TokenSecret) に JSON やトークン文字列を直接入れてください- 提供している送信インフラは SMTP、GraphApi (Microsoft Graph)、SendGrid、Gmail (Gmail API) です
- SMTP は社内メールサーバーや各種メールサービスの SMTP エンドポイントに送ります (MailKit)。一斉送信は 1 接続で逐次送信します。
Passwordは環境変数 (Smtp__Password) やユーザーシークレットに置いてください。 開発時は smtp4dev (dotnet tool install -g Rnwood.Smtp4dev) をローカルに立て、Host: localhost/Port: 25/SSL: falseで送ると 実際のメールを出さずにブラウザ (http://localhost:5000) で受信内容を確認できます - GraphApi は Microsoft 365 (Exchange Online) のメールボックスから Microsoft Graph の
sendMailで送ります。 Entra ID にアプリを登録し、Microsoft Graph のアプリケーションの許可Mail.Sendに管理者の同意を与えてください (差出人を特定のメールボックスに限定するには Exchange Online の Application Access Policy を使います)。 送ったメールは差出人の「送信済みアイテム」に残ります。認証は 2 通り:ClientSecretを設定 → クライアントシークレット認証 (TenantId/ClientId/ClientSecret)。シークレットは環境変数 (GraphApi__ClientSecret) やユーザーシークレットに置いてくださいClientSecretが空 →DefaultAzureCredential。App Service 等では Managed Identity で動くので設定にシークレットを持ちません (MI のサービスプリンシパルにMail.Sendのアプリロールを付与します。ポータルの UI は無く PowerShell のNew-MgServicePrincipalAppRoleAssignmentで行います)。 ローカル開発では Azure CLI / Visual Studio のログインが使われます (別テナント既定ならTenantIdを指定) Exchange Online のレート制限があるため大量の一斉送信には向きません (逐次送信、429 は Retry-After に従って再試行)
- SendGrid は Twilio SendGrid の v3 mail/send API で送ります (SDK 不使用の素の REST)。
差出人は SendGrid 側で検証済みであることが必要です (少量なら Single Sender Verification、本格運用は Settings > Sender Authentication のドメイン認証。未検証は 403 で拒否されます)。
一斉送信はネイティブの personalizations (1 リクエスト最大 1,000 宛先) を使い、
{変数}の差し込みは SendGrid 側で行われるため、 大量配信にはこのインフラを推奨します。ApiKeyは環境変数 (SendGrid__ApiKey) やユーザーシークレットに置いてください - Gmail は Gmail の上限 (Workspace: 1 ユーザー 1 日 2,000 通 / 無料: 500 通、約 2.5 通/秒) に合わせて、
一斉送信は 400ms 間隔で逐次送信し、レート制限 (429 / 503) は指数バックオフ (2s→32s・最大 5 回) で再試行、日次上限に達したら残りを打ち切って失敗として返します。
MaxBulkCountの既定は 500。数千通規模の配信は配信サービス系のインフラ (IMailSender実装) を使ってください - 独自の送信手段 (社内メールゲートウェイなど) は
IMailSenderを実装し、アプリのMailSenderTable(呼び名 → 実装の対応表) に 1 行足すだけで使えます
0.5.0 のテンプレートにあった MailService (スクリプトオブジェクト) / MailMessage / サーバーの SmtpMailService / MailSettings (appsettings の MailSettings セクション) は互換のために残してあり、
そのままビルド・動作します (SmtpMailService の中身は SmtpMailSender になりました)。新しく作る画面では MailField / BulkMailField を使ってください。
新しいアプリテンプレートには最初から入っています。既存アプリに足す場合の要点:
MailController—MailTransport.SendMailEndPoint(/api/mail) /BulkSearchMailEndPoint(/api/mail/bulk_search) /PreviewMailEndPoint(/api/mail/preview) /BulkPreviewMailEndPoint(/api/mail/bulk_preview) の受け口 (プレビューはMailPreviewBuilderが HTML を作る)MailSenderTable— 呼び名 →IMailSenderの対応表- クライアント起動時:
MailTransport.SendMailEndPoint/BulkSearchMailEndPoint/PreviewMailEndPoint/BulkPreviewMailEndPointに URL を設定
- MailField / BulkMailField: 宛先未設定、件名・本文とも空、変数の不在
- BulkMailField の宛先リストの先に宛先契約が無い
- 契約の必須役割が空、名指ししたフィールドの不在
- 承認フローの「順番が回ってきた人への通知」は、承認メンバーモジュールに置いた MailField を テンプレートとして使います → 承認フロー