Skip to content
このページは AI の支援により作成・翻訳されました。誤りがあれば、改善にご協力ください。 GitHub で編集

SMTP設定

PRX-Emailはrustls TLSを持つlettreクレートを通じてSMTP経由でメールを送信します。アウトボックスパイプラインは重複送信を防ぐアトミックなクレーム・送信・ファイナライズワークフローを使用し、指数バックオフリトライと決定論的なMessage-IDべき等性キーを提供します。

基本的なSMTP設定

rust
use prx_email::plugin::{SmtpConfig, AuthConfig};

let smtp = SmtpConfig {
    host: "smtp.example.com".to_string(),
    port: 465,
    user: "[email protected]".to_string(),
    auth: AuthConfig {
        password: Some("your-app-password".to_string()),
        oauth_token: None,
    },
};

設定フィールド

フィールドタイプ必須説明
hostStringはいSMTPサーバーホスト名(空であってはならない)
portu16はいSMTPサーバーポート(暗黙的TLSは465、STARTTLSは587)
userStringはいSMTPユーザー名(通常はメールアドレス)
auth.passwordOption<String>いずれかSMTP AUTH PLAIN/LOGINのパスワード
auth.oauth_tokenOption<String>いずれかXOAUTH2のOAuthアクセストークン

一般的なプロバイダ設定

プロバイダホストポート認証方式
Gmailsmtp.gmail.com465アプリパスワードまたはXOAUTH2
Outlook / Office 365smtp.office365.com587XOAUTH2
Yahoosmtp.mail.yahoo.com465アプリパスワード
Fastmailsmtp.fastmail.com465アプリパスワード

メールの送信

基本的な送信

rust
use prx_email::plugin::SendEmailRequest;

let response = plugin.send(SendEmailRequest {
    account_id: 1,
    to: "[email protected]".to_string(),
    subject: "Hello".to_string(),
    body_text: "Message body here.".to_string(),
    now_ts: now,
    attachment: None,
    failure_mode: None,
});

メッセージへの返信

rust
use prx_email::plugin::ReplyEmailRequest;

let response = plugin.reply(ReplyEmailRequest {
    account_id: 1,
    in_reply_to_message_id: "<[email protected]>".to_string(),
    body_text: "Thanks for your message!".to_string(),
    now_ts: now,
    attachment: None,
    failure_mode: None,
});

返信は自動的に:

  • In-Reply-Toヘッダーを設定する
  • 親メッセージからReferencesチェーンをビルドする
  • 受信者を親メッセージの送信者から派生させる
  • 件名にRe:のプレフィックスを付ける

アウトボックスパイプライン

アウトボックスパイプラインはアトミックな状態マシンを通じて信頼性の高いメール配信を保証します:

mermaid
stateDiagram-v2
    [*] --> pending: send() / reply()
    pending --> sending: claim (atomic)
    sending --> sent: finalize (success)
    sending --> failed: finalize (error)
    failed --> sending: retry (claim)
    failed --> sending: retry_outbox()
    pending --> sending: retry_outbox()

状態マシンのルール

遷移条件ガード
pending -> sendingclaim_outbox_for_send()status IN ('pending','failed') AND next_attempt_at <= now
sending -> sentプロバイダが受け入れたupdate_outbox_status_if_current(status='sending')
sending -> failedプロバイダが拒否またはネットワークエラーupdate_outbox_status_if_current(status='sending')
failed -> sendingretry_outbox()status IN ('pending','failed') AND next_attempt_at <= now

べき等性

各アウトボックスメッセージは決定論的なMessage-IDを取得します:

<outbox-{id}-{retries}@prx-email.local>

これによりリトライが元の送信と区別でき、Message-IDで重複排除するプロバイダが各リトライを受け入れます。

リトライバックオフ

失敗した送信は指数バックオフを使用します:

next_attempt_at = now + base_backoff * 2^retries

ベースバックオフ5秒の場合:

リトライバックオフ
110秒
220秒
340秒
480秒
5160秒
6320秒
7640秒
105,120秒(約85分)

手動リトライ

rust
use prx_email::plugin::RetryOutboxRequest;

let response = plugin.retry_outbox(RetryOutboxRequest {
    outbox_id: 42,
    now_ts: now,
    failure_mode: None,
});

以下の場合にリトライは拒否されます:

  • アウトボックスのステータスがsentまたはsending(リトライ不可)
  • next_attempt_atにまだ達していない場合(retry_not_due

添付ファイル

添付ファイルで送信する

rust
use prx_email::plugin::{SendEmailRequest, AttachmentInput};

let response = plugin.send(SendEmailRequest {
    account_id: 1,
    to: "[email protected]".to_string(),
    subject: "Report attached".to_string(),
    body_text: "Please find the report attached.".to_string(),
    now_ts: now,
    attachment: Some(AttachmentInput {
        filename: "report.pdf".to_string(),
        content_type: "application/pdf".to_string(),
        base64: Some(base64_encoded_content),
        path: None,
    }),
    failure_mode: None,
});

添付ファイルポリシー

AttachmentPolicyはサイズとMIMEタイプの制限を適用します:

rust
use prx_email::plugin::AttachmentPolicy;

let policy = AttachmentPolicy {
    max_size_bytes: 25 * 1024 * 1024,  // 25 MiB
    allowed_content_types: [
        "application/pdf",
        "image/jpeg",
        "image/png",
        "text/plain",
        "application/zip",
    ].into_iter().map(String::from).collect(),
};
ルール動作
サイズがmax_size_bytesを超えるattachment exceeds size limitで拒否
MIMEタイプがallowed_content_typesにないattachment content type is not allowedで拒否
attachment_storeなしのパスベース添付attachment store not configuredで拒否
パスがストレージルートを逸脱する(../トラバーサル)attachment path escapes storage rootで拒否

パスベース添付ファイル

ディスクに保存された添付ファイルには、添付ファイルストアを設定します:

rust
use prx_email::plugin::AttachmentStoreConfig;

let store = AttachmentStoreConfig {
    enabled: true,
    dir: "/var/lib/prx-email/attachments".to_string(),
};

パス解決にはディレクトリトラバーサルガードが含まれています。設定されたストレージルート外で解決されるパス(シンボリックリンクベースのエスケープを含む)はすべて拒否されます。

APIレスポンス形式

すべての送信操作はApiResponse<SendResult>を返します:

rust
pub struct SendResult {
    pub outbox_id: i64,
    pub status: String,          // "sent" or "failed"
    pub retries: i64,
    pub provider_message_id: Option<String>,
    pub next_attempt_at: i64,
}

次のステップ

Released under the Apache-2.0 License.