デモでメールを1通送るのは簡単です。しかし本番環境で月に10万通を送るなら、問題が起きる瞬間に備えておく必要があります。失効したキー、期限切れのカード、思ったより早く訪れる月末、調子の悪いメールサーバーなどです。
このガイドでは、Inbixioの送信エンドポイントが返すすべてのレスポンスと、それぞれに対してコードがすべきこと、そして運用開始後に配信状況を監視する方法を解説します。
2つの段階:受け付け、そして配信
POST /api/send-email/の呼び出しは、2つの段階で処理されます。
- APIリクエスト:Inbixioはキー、その権限、サブスクリプション、月間の利用量、リクエスト本文をチェックします。すべて問題なければ
200を返し、メッセージをキューに追加します。 - 配信:その直後、Inbixioはお使いのSMTPサーバーに接続してメッセージを引き渡します。各メッセージは「送信済み」か「失敗」として記録され、その結果がダッシュボードの数値に反映されます。
つまり200は「配信のために受け付けた」という意味であり、「受信トレイに届いた」という意味ではありません。段階1の問題は、コードで処理できるHTTPエラーとして返ってきます。SMTPパスワードの誤りなど段階2の問題は、ダッシュボードの配信失敗率に表れます。Inbixioはメッセージごとに1回だけ配信を試み、失敗した配信をリトライすることはありません。
すべてのレスポンスと対応方法
| ステータス | 本文 | 意味 | コードでの対応 |
|---|---|---|---|
200 |
{"message": "Email queued successfully."} |
受け付け完了 | 完了 |
400 |
{"error": "to_email, subject, and message are required."} |
フィールドが欠けているか空 | リクエストを修正。リトライしない |
400 |
{"error": "to_email must be a single valid email address."} |
有効なアドレスがちょうど1つではない | リクエストを修正。リトライしない |
400 |
{"error": "subject must be a single line of at most 500 characters."} |
件名が長すぎるか改行を含む | リクエストを修正。リトライしない |
400 |
{"error": "message must be text of at most 1,000,000 characters."} |
本文が大きすぎる | リクエストを修正。リトライしない |
400 |
{"error": "No SMTP configuration found. Please add an email server first."} |
サーバーが接続されていない | ダッシュボードでサーバーを追加 |
401 |
{"detail": "API key missing"} |
X-API-Keyヘッダーがない |
設定を修正。リトライしない |
401 |
{"detail": "Invalid API key"} |
キーの誤り、更新済み、または削除済み | キーを更新し、チームに通知 |
401 |
{"detail": "API key access not allowed"} |
キーが無効化されている | 別のキーを使い、チームに通知 |
402 |
{"error": "An active subscription is required to send emails."} |
サブスクリプションが無効 | 請求情報を修正し、チームに通知 |
403 |
{"error": "This API key does not have send permission."} |
キーにSend権限がない | Sendを有効にするか、別のキーを使う |
429 |
{"error": "Monthly email limit reached for your plan.", "limit": 25000, "sent": 25000} |
プランの上限に到達 | アップグレードするか、翌月まで送信を保留。リトライしない |
429 |
{"detail": "Request was throttled. Expected available in 12 seconds."} |
短時間にこのキーでのリクエストが多すぎる(レート制限) | Retry-Afterヘッダーの時間だけ待ってからリトライ |
503 |
{"error": "Too many emails are waiting to be sent. Please retry in a few seconds."} |
一時的に混雑 | Retry-Afterヘッダーの時間だけ待ってからリトライ |
5xx / タイムアウト |
— | 一時的な問題 | バックオフしながらリトライ |
エラーメッセージは、ほとんどのレスポンスではerrorに、認証エラーではdetailに入っているので、両方を読み取りましょう。
const body = await res.json().catch(() => ({}));
const reason = body.error ?? body.detail ?? res.statusText;
後で成功しうるものだけをリトライする
401を100回リトライしてもキーが有効になることはなく、ログが埋まるだけです。エラーは2つのグループに分けましょう。
- リトライする:ネットワークエラー、タイムアウト、
5xxレスポンス、そしてレート制限による429(detailメッセージを含むもの)。Retry-Afterヘッダーで指定された時間だけ待ち、ヘッダーがなければジッター付きの指数バックオフを使い、数回試して諦めます。 - リトライしない:
400、401、402、403、そして月間上限による429(limitとsentを含むもの)。これらは人の対応か、別のリクエストが必要です。目立つようにログに残し、401、402、月間上限の429についてはアラートを出しましょう。これらはすべてのメール送信を止めてしまうからです。
// 5xx and the short-term rate limit can succeed later; the monthly limit (body has `limit`) can't.
const retryable = (status, body) => status >= 500 || (status === 429 && body.limit === undefined);
export async function sendWithRetry(payload, attempts = 4) {
for (let i = 0; i < attempts; i++) {
let res;
try {
res = await fetch('https://backend.inbixio.com/api/send-email/', {
method: 'POST',
headers: { 'X-API-Key': process.env.INBIXIO_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
signal: AbortSignal.timeout(15_000),
});
} catch (err) {
if (i === attempts - 1) throw err; // network error or timeout: retry
}
if (res?.ok) return res.json();
if (res) {
const body = await res.json().catch(() => ({}));
if (!retryable(res.status, body)) {
throw new Error(`Inbixio ${res.status}: ${body.error ?? body.detail ?? res.statusText}`);
}
}
const retryAfter = Number(res?.headers.get('Retry-After')) * 1000;
const delay = retryAfter || Math.min(30_000, 1000 * 2 ** i) * (0.5 + Math.random()); // 0.5s–30s with jitter
await new Promise((r) => setTimeout(r, delay));
}
throw new Error('Inbixio: gave up after retries');
}
重複について:リクエストがタイムアウトしても、実際には受け付けられている場合があります。その場合、リトライすると同じメールが2通送られる可能性があります。領収書や通知であれば通常は許容範囲ですが、重複がユーザーを混乱させるものについては、送信した内容を自社のデータベースに記録し、リトライ前に確認しましょう。
月間上限
各プランには月あたりの送信数が含まれています。Starterは25,000通、Growthは150,000通です。Inbixioは当月(暦月)に送信に成功したメールをカウントします。上限に達すると、翌月が始まるかアップグレードするまで、送信にはlimitと現在のsent数を含む429が返されます。
429が返ってくるまで待つ必要はありません。
- API Keys(APIキー)ページにはUsage Limit(使用量の上限)カードがあり、今月の送信数とプランの上限が表示されます。
- 上限の約80%に達したら確認するようリマインダーを設定し、大規模なローンチやインポートの前にはアップグレードを計画しましょう。
- 送信数を段階的に見積もる方法は、メールAPIのプランの選び方をご覧ください。
配信の失敗(段階2)
APIがメッセージを受け付けたものの、お使いのSMTPサーバーが拒否した場合は、配信失敗としてカウントされます。ダッシュボードには個々のメッセージの一覧ではなく、過去7日間のFailed Deliveries(配信失敗)率が表示されるので、この割合を見守り、上昇したらサーバー設定を確認しましょう。主な原因は次のとおりです。
- 認証の失敗:メールボックスのパスワードが変更された、またはプロバイダーがアプリパスワードを要求するようになった。
- 接続の問題:サーバー設定のホストまたはポートが間違っている。
- プロバイダーの制限:メールプロバイダーがメールボックスの1日あたりの送信数を制限した。
- 受信者の拒否:送信中にサーバーがアドレスを拒否した。後からメールとして届くバウンスはInbixioではなく送信元のメールボックスに届くので、その受信トレイも確認しましょう。
修正箇所はほぼ必ず、Email Servers(メールサーバー)またはメールプロバイダー側にあります。よくあるケースはSMTP設定の解説で取り上げています。
本番環境で監視すべきこと
Inbixioのダッシュボードでは、必要な情報をひととおり確認できます。
- 過去7日間のEmail Sent(送信済みメール)とFailed Deliveries率。それぞれ、その前の7日間との比較も表示されます。
- Avg Latency(平均レイテンシ):SMTPサーバーがメールを受け付けるまでにかかる時間。急な上昇は、失敗の前兆であることがよくあります。
- 1年間のAPIとメールの送信量グラフ:傾向や季節的なピークを把握できます。
- すべてのAPI呼び出しのLogs(ログ):イベントID、エンドポイント、メソッド、ステータスコード、レスポンス時間、タイムスタンプ。
自社側では、200以外のレスポンスの件数をステータスコード別に記録し、401、402、月間上限の429が発生したらアラートを出しましょう。これらはすべてのメールが止まったことを意味し、ログより先にユーザーが気づいてしまいます。
チェックリスト
-
200は「キューに追加済み」として扱い、配信結果はダッシュボードで確認する - エラーレスポンスから
errorとdetailの両方を読み取る - リトライするのはネットワークエラー、タイムアウト、
5xx、503、レート制限の429だけにし、Retry-Afterに従う -
401、402、月間上限の429でアラートを出す - ローンチやインポートの前にUsage Limitカードを確認する
- Failed Deliveries率を見守り、SMTP設定をすぐに修正する