KaiMail の HTTP 送信 API を使うと、アプリケーションから HTTPS 経由で独自ドメインのメールを送信できます。SMTP ライブラリは不要です。この API は、ポート 587 の SMTP 認証送信と同じ送信パイプラインへの入り口であり、DKIM 署名・送信者検証・クォータ制御・配信ログはどちらの経路でも同一に動作します。プラットフォームがポート 587 をブロックしている場合、サーバーレス環境から呼び出す場合、あるいは単純に JSON over HTTPS の方が扱いやすい場合にご利用ください。
https://kaimail.net/api/v1202 Accepted を返しますすべてのリクエストに HTTP Basic 認証の資格情報が必要です。
これはポート 587 での SMTP 送信に使う資格情報と同一です。Web ダッシュボードへのログインに使うアカウントパスワードでは認証できません。
curl -u "[email protected]:YOUR_SMTP_PASSWORD" https://kaimail.net/api/v1/usage
資格情報が欠落・無効の場合は 401(エラーコード invalid_credentials)を返します。資格情報は正しいがプランに送信機能が含まれていない場合は 403(sending_not_allowed)を返します。この区別により、パスワード誤りとプラン制限をインテグレーション側で切り分けられます。
送信には、SMTP 送信が有効なプランが必要です。
成功・エラーを問わず、すべてのレスポンスはリクエストごとに生成される一意の識別子 request_id を含む JSON オブジェクトです。特定の API 呼び出しについてサポートに問い合わせる際は、この値を添えてください。
成功レスポンスはペイロードを data に格納します。
{
"request_id": "0f6d2c9be5a34f7f9f0c1d2e3a4b5c6d",
"data": { "...": "..." }
}
エラーレスポンスは、機械可読な code と人間向けの message を持つ error オブジェクトを返します。
{
"request_id": "0f6d2c9be5a34f7f9f0c1d2e3a4b5c6d",
"error": {
"code": "quota_exceeded",
"message": "Monthly sending quota reached."
}
}
エラー処理は error.code で分岐してください。message の文言は変更される可能性があります。
送信できるのは、ご自身が所有するアドレスからのみです。すべての送信リクエストにおいて、送信者アドレスは次の両方を満たす必要があります。
domain_not_owned)。mailbox_not_registered)。メッセージは送信処理の中でドメインごとの鍵(セレクタ kaimail)により DKIM 署名されます。ダッシュボードに表示される DKIM の DNS レコードを必ず公開しておいてください。
標準的な送信方法です。プレーンなフィールドを渡すだけで、サーバー側が MIME メッセージを構築します(Date ヘッダと Message-ID ヘッダも付与されます)。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
from |
string | はい | 送信者アドレス。表示名も指定可能です: "Support <[email protected]>"。アドレス部分は上記「送信者の要件」を満たす必要があります。 |
to |
string または string の配列 | はい | 宛先アドレス。1 通あたり最大 100 件。すべての宛先がメッセージの To: ヘッダに記載されます。Bcc 相当の動作が必要な場合は send-raw を使用してください。 |
subject |
string | いいえ | 件名。998 文字で切り詰められます。 |
text |
string | 下記参照 | プレーンテキスト本文。 |
html |
string | 下記参照 | HTML 本文。 |
text と html の少なくとも一方が必須です。両方を指定した場合、multipart/alternative(テキスト + HTML)として送信されます。
curl -X POST https://kaimail.net/api/v1/email/send \
-u "[email protected]:YOUR_SMTP_PASSWORD" \
-H "Content-Type: application/json" \
-d '{
"from": "Support <[email protected]>",
"to": ["[email protected]"],
"subject": "ご登録ありがとうございます",
"text": "こんにちは。ご登録ありがとうございます。",
"html": "<p>こんにちは。<strong>ご登録</strong>ありがとうございます。</p>"
}'
202 Accepted{
"request_id": "0f6d2c9be5a34f7f9f0c1d2e3a4b5c6d",
"data": {
"tracking_id": "k2vq81xw3n7p5d09smc4",
"status": "queued",
"recipients": ["[email protected]"]
}
}
202 は、メッセージが検証を通過しキューに登録されたことを意味します。配信完了を意味するものではありません。後述のステータスエンドポイントをポーリングするため、tracking_id を保存してください。
import requests
resp = requests.post(
"https://kaimail.net/api/v1/email/send",
auth=("[email protected]", "YOUR_SMTP_PASSWORD"),
json={
"from": "Support <[email protected]>",
"to": ["[email protected]"],
"subject": "ご登録ありがとうございます",
"text": "こんにちは。ご登録ありがとうございます。",
},
timeout=30,
)
resp.raise_for_status()
tracking_id = resp.json()["data"]["tracking_id"]
<?php
$payload = [
"from" => "Support <[email protected]>",
"to" => ["[email protected]"],
"subject" => "ご登録ありがとうございます",
"text" => "こんにちは。ご登録ありがとうございます。",
];
$ch = curl_init("https://kaimail.net/api/v1/email/send");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_USERPWD => "[email protected]:YOUR_SMTP_PASSWORD",
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$body = json_decode($response, true);
if ($status !== 202) {
throw new RuntimeException(
"send failed: {$body['error']['code']}: {$body['error']['message']}"
);
}
$trackingId = $body["data"]["tracking_id"];
MIME メッセージを完全に制御したい場合に使用します — 添付ファイル、カスタムヘッダ、Bcc、メールライブラリで構築済みのメッセージなど。RFC 822 メッセージ全体を base64 エンコードし、SMTP エンベロープとともに送信します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
raw_message |
string | はい | RFC 822 メッセージ全体を base64 エンコードしたもの(標準エンコーディング、パディングあり)。 |
to |
string の配列 | はい | エンベロープ宛先(SMTP RCPT TO)。最大 100 件。配信はこの配列のアドレスに対してのみ行われます。メッセージ内の To:/Cc:/Bcc: ヘッダは配送先の決定には使用されません。Bcc はこの仕組みで実現します: アドレスをこの配列に含め、ヘッダには書かないでください。 |
envelope_from |
string | いいえ | エンベロープ送信者(SMTP MAIL FROM)。省略時はメッセージの From: ヘッダのアドレスが使われます。「送信者の要件」を満たす必要があります。 |
注意: base64 エンコードによりペイロードは約 33% 増加します。プランのメッセージサイズ上限は、デコード後のメッセージバイト数に適用されます。
import base64
import requests
from email.message import EmailMessage
msg = EmailMessage()
msg["From"] = "Billing <[email protected]>"
msg["To"] = "[email protected]"
msg["Subject"] = "請求書のご送付"
msg.set_content("請求書を添付いたします。")
msg.add_attachment(
open("invoice.pdf", "rb").read(),
maintype="application", subtype="pdf", filename="invoice.pdf",
)
resp = requests.post(
"https://kaimail.net/api/v1/email/send-raw",
auth=("[email protected]", "YOUR_SMTP_PASSWORD"),
json={
"raw_message": base64.b64encode(msg.as_bytes()).decode("ascii"),
"to": ["[email protected]", "[email protected]"],
"envelope_from": "[email protected]"
},
timeout=30,
)
PHP には MIME メッセージを構築する標準機能がないため、この例では PHPMailer(composer require phpmailer/phpmailer)でメッセージを構築し、SMTP の代わりに API 経由で送信します。
<?php
require "vendor/autoload.php";
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->CharSet = "UTF-8";
$mail->setFrom("[email protected]", "Billing");
$mail->addAddress("[email protected]");
$mail->Subject = "請求書のご送付";
$mail->Body = "請求書を添付いたします。";
$mail->addAttachment("invoice.pdf");
$mail->preSend(); // 送信せずに MIME メッセージのみ構築
$raw = $mail->getSentMIMEMessage();
$payload = [
"raw_message" => base64_encode($raw),
"to" => ["[email protected]", "[email protected]"],
"envelope_from" => "[email protected]",
];
$ch = curl_init("https://kaimail.net/api/v1/email/send-raw");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_USERPWD => "[email protected]:YOUR_SMTP_PASSWORD",
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
レスポンスの形式は /email/send と同一です(202 とともに tracking_id、status、recipients を返します)。
キューに登録したメッセージの送信ステータスを返します。照会できるのは自分のアカウントから送信したメッセージのみです。
curl -u "[email protected]:YOUR_SMTP_PASSWORD" \
https://kaimail.net/api/v1/email/k2vq81xw3n7p5d09smc4
200 OK{
"request_id": "6b1a2c3d4e5f60718293a4b5c6d7e8f9",
"data": {
"tracking_id": "k2vq81xw3n7p5d09smc4",
"status": "sent",
"envelope_from": "[email protected]",
"recipients": ["[email protected]"],
"subject": "ご登録ありがとうございます",
"created_time": "2026-07-20T04:12:33Z",
"processed_time": "2026-07-20T04:12:41Z",
"error": null
}
}
タイムスタンプは ISO 8601(UTC)です。存在しない tracking_id は 404(コード not_found)を返します。
queued ──▶ sending ──▶ sent
└──▶ failed
| ステータス | 意味 |
|---|---|
queued |
受理され、送信待ちの状態。 |
sending |
ワーカーが送信処理中。 |
sent |
KaiMail のメールサーバーが配信のために受理した状態。 宛先ごとの配信結果とバウンスはログダッシュボードで確認できます。 |
failed |
送信を断念。理由は error に記録されます。 |
セマンティクスに関する注意:
failed になります。sent となり、拒否された宛先が error に記録されます。failed にします。再送する前にログダッシュボードをご確認ください。送信機能の有効状態と残りクォータを返します。送信前のチェックや監視に利用できます。
curl -u "[email protected]:YOUR_SMTP_PASSWORD" https://kaimail.net/api/v1/usage
200 OK{
"request_id": "9c8b7a6d5e4f30211203f4e5d6c7b8a9",
"data": {
"smtp_sending": true,
"sent_this_period": 42,
"quota": 1000,
"remaining": 958,
"period_days": 30
}
}
| フィールド | 説明 |
|---|---|
smtp_sending |
プランで送信機能が有効かどうか。 |
sent_this_period |
集計期間内に送信したメール数(宛先ごとにカウント)。 |
quota |
期間あたりの送信クォータ。-1 は無制限を意味します。 |
remaining |
残りクォータ。無制限の場合は null。 |
period_days |
ローリング集計期間の長さ(現在は 30 日)。 |
クォータは宛先ごとにカウントされます: 10 宛先への 1 通は 10 とカウントされます。キュー登録済みでまだ送信されていないメッセージも、リクエスト時点のクォータ判定に含まれるため、大量のキュー投入によって上限を超過することはできません。
| HTTP | error.code |
意味 / 対処 |
|---|---|---|
| 400 | invalid_json |
ボディが JSON オブジェクトではない。 |
| 400 | invalid_request |
フィールドの欠落または不正(宛先アドレスの誤り、from の欠落、宛先数超過、text/html の両方が未指定、など)。詳細は message に記載されます。 |
| 400 | invalid_message |
send-raw のみ: raw_message が有効な base64 でない、またはデコード結果が空。 |
| 401 | invalid_credentials |
Basic 認証の資格情報が誤っているか未指定。アカウントのメールアドレスと SMTP パスワードを使用してください。 |
| 403 | sending_not_allowed |
資格情報は正しいが、プランに送信機能が含まれていない。 |
| 403 | domain_not_owned |
送信者のドメインが、有効なカスタムドメインとして登録されていない。 |
| 403 | mailbox_not_registered |
送信者アドレスが、登録済みの有効なメールボックスではない。 |
| 404 | not_found |
指定の tracking_id を持つメッセージがアカウントに存在しない。 |
| 413 | message_too_large |
メッセージがプランのサイズ上限を超過。両方のサイズが message に記載されます。 |
| 429 | quota_exceeded |
月間送信クォータに到達(キュー済みメッセージを含む)。/usage を確認してください。 |
| 制限 | 値 |
|---|---|
| 1 通あたりの宛先数 | 100 |
| 件名の長さ | 998 文字 |
| メッセージサイズ | プランによる(プラン詳細を参照。send-raw ではデコード後のバイト数に適用) |
| 送信クォータ | プランによる。ローリング 30 日間で宛先ごとにカウント |
| 送信リトライ | バックオフ付きで 3 回試行後、failed |
POST /api/v1/email/send を呼び出し、返された tracking_id を保存する。GET /api/v1/email/<tracking_id> を sent または failed になるまでポーリングする。sent は「メールサーバーへの受け渡し完了」と解釈し、バウンスはログダッシュボードで確認する。429 を受け取ったらバックオフし、GET /api/v1/usage で状況を確認する。