Mail Proxy API

คู่มือผู้ดูแลระบบและผู้ใช้งาน: ส่งอีเมลผ่าน HTTPS API ด้วย API key

Endpoint: https://mailproxy.ipv9.meVersion 2.1.0 ปรับปรุง 27 ก.ย. 2569 (mpkey --mail)

1. ภาพรวม

Mail Proxy คือ HTTP API ภายในองค์กรสำหรับส่งอีเมลแจ้งเตือนจากระบบต่าง ๆ เช่น Wazuh, LibreNMS, script และ n8n โดยระบบต้นทางไม่ต้องมีรหัสผ่าน SMTP ใช้แค่ API key ของตัวเอง ซึ่งเพิกถอนหรือจำกัดอัตราการส่งแยกรายระบบได้

Clientcurl / Python / n8n
→ HTTPS →
CloudflareTLS edge + tunnel
→
mailapiFastAPI :8000
→
mailrelayPostfix
→ STARTTLS →
Gmail SMTPบัญชี relay ขององค์กร
ส่วนประกอบหน้าที่
APIตรวจ API key, rate limit, template แล้วส่งต่อไป SMTP relay
SMTP relayPostfix ส่งต่อไป Gmail ผ่าน STARTTLS
Key storeRedis เก็บ API key แบบ SHA-256, ตัวนับ rate limit, สถิติ 30 วัน
EdgeCloudflare Tunnel (ไม่มีพอร์ตเปิดสู่อินเทอร์เน็ตโดยตรง)

2. Features ที่รองรับ

API key ต่อระบบเก็บเฉพาะค่า SHA-256 ใน Redis ตั้งเปิด/ปิดและวันหมดอายุได้
Rate limit ต่อ keyจำนวนครั้งต่อนาทีต่อ key (0 = ไม่จำกัด) พร้อม header X-RateLimit-*
ผู้รับหลายคนto เป็น string หรือ array และมี cc, bcc
HTML bodyตั้ง "html": true (เฉพาะ /send)
ชื่อผู้ส่งใช้ sender_name แสดงชื่อ เช่น "ระบบงานตรวจสอบ" (รองรับ UTF-8)
Templateswazuh, zimbra, system, custom และจำกัด template ต่อ key ได้
Health checkGET /health รายงานสถานะ Redis และ SMTP
OpenAPI / Swagger/docs, /redoc, /openapi.json
สถิติรายวันนับสำเร็จ/ล้มเหลวต่อ key เก็บ 30 วัน และสรุปเข้า Slack

3. ผู้ดูแลระบบ: จัดการ API key

หัวข้อนี้สำหรับผู้ดูแลระบบเท่านั้น ใช้เครื่องมือ mpkey บนเครื่องที่รัน key store ของระบบ (ต้องมีสิทธิ์ผู้ดูแล)
ผู้ใช้งานทั่วไป: ขอ API key จากผู้ดูแลระบบ โดยแจ้งชื่อระบบ, rate ที่ต้องการ, อายุ key, template ที่ใช้ และอีเมลผู้รับผิดชอบ (ใช้รับ key และรับแจ้งเมื่อ key ถูกปิด เปิด หรือลบ)

3.1 สร้าง key

# mpkey create <name> [rate_per_min=60] [expire_days=0] [templates=*] [--mail <email>]
mpkey create wazuh-prod 100                 # 100 ครั้ง/นาที, ไม่หมดอายุ
mpkey create n8n-sit 30 90                  # 30 ครั้ง/นาที, หมดอายุใน 90 วัน
mpkey create zimbra-mon 20 0 zimbra,system  # ใช้ได้เฉพาะ template zimbra และ system
mpkey create batch-job 0                    # ไม่จำกัด rate (ใช้เท่าที่จำเป็น)
mpkey create app-x 60 0 --mail owner@example.com   # ผูกอีเมลเจ้าของ + ส่ง key ทางอีเมล
Parameterค่าเริ่มต้นความหมาย
name(ต้องใส่)ชื่อระบบที่ใช้ key ห้ามมีอักขระ < > & "
rate_per_min60จำนวน request ต่อนาที · 0 = ไม่จำกัด
expire_days0อายุ key เป็นวัน · 0 = ไม่หมดอายุ
templates*template ที่อนุญาต คั่นด้วย comma
--mail <email>—อีเมลเจ้าของ key (วางตำแหน่งไหนก็ได้ รองรับ --mail=addr) ระบบตรวจรูปแบบอีเมลก่อนสร้าง

ผลลัพธ์:

name=app-x rate=60/min expires=never templates=* email=owner@example.com hash=3f9c0a1b7e2d
API KEY (shown once): mp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mail sent to owner@example.com
ค่า key จะแสดงเพียงครั้งเดียว ระบบเก็บไว้แค่ค่า hash ถ้าทำหายต้องสร้างใหม่ (ไม่มีคำสั่งกู้คืน)

3.2 การส่ง key ให้ผู้ใช้: เลือกวิธีตามความเสี่ยง

วิธีเหมาะกับข้อควรระวัง
A. --mail ส่งอีเมลอัตโนมัติผู้ใช้เป็นคน เช่น ทีมพัฒนาหรือผู้รับเหมา ที่ต้องการคู่มือไปด้วยkey อยู่ในกล่องจดหมายของผู้รับเป็นข้อความธรรมดา ใช้ได้เฉพาะอีเมลองค์กรหรือที่เชื่อถือได้ · แนะนำให้ผู้รับย้าย key ไป vault แล้วลบเมล
B. Pipe ตรงเข้าไฟล์ บนเครื่องปลายทางระบบอัตโนมัติ เช่น cron, watchdog หรือ agentปลอดภัยที่สุด key ไม่แสดงบนจอเลย
mpkey create app-x 60 | sed -n 's/^API KEY (shown once): /X-API-Key: /p' | ssh host 'umask 077; cat > /etc/app-x.key'
C. คัดลอกเข้า vault ด้วยมือระบบที่อ่าน secret จาก vault หรือ secret managerห้ามวาง key ในแชท, ticket หรือ Git

วิธี B/C ใช้ร่วมกับ --mail ได้ ถ้าต้องการผูกอีเมลเจ้าของไว้รับแจ้งเตือน แต่ไม่อยากให้ key ไปอยู่ในอีเมล ให้สร้างแบบไม่ใส่ --mail (ตอนนี้ยังไม่มีคำสั่งผูกอีเมลภายหลัง ดู 3.6)

3.3 อีเมลที่ระบบส่งอัตโนมัติ

เหตุการณ์Subjectเนื้อหา
create --mail[Mail Proxy] API key สำหรับ <name>API key, hash อ้างอิง, rate limit, วันหมดอายุ, template, endpoint, ตัวอย่าง curl, ลิงก์คู่มือ และคำเตือนเรื่องการเก็บรักษา
disable[Mail Proxy] API key "<name>" disabledเวลาที่ปิด และบอกว่าจะได้ HTTP 401 API_KEY_DISABLED
enable[Mail Proxy] API key "<name>" enabledเวลาที่เปิด และบอกว่าใช้งานได้ตามปกติ
delete[Mail Proxy] API key "<name>" deletedเวลาที่ลบ และแนะนำให้ขอ key ใหม่ (HTTP 401 INVALID_API_KEY)

ผู้ส่งแสดงเป็น Mail Proxy Admin · อีเมลแจ้ง disable/enable/delete ไม่มีค่า key · key ที่ไม่ได้ผูกอีเมลจะไม่มีการส่งเมลใด ๆ
ถ้าส่งเมลไม่สำเร็จ คำสั่งยังมีผลตามปกติ แต่จะขึ้น WARN: mail to … FAILED ให้ผู้ดูแลแจ้งเจ้าของเองทางช่องทางอื่น

3.4 ดูรายการ, ปิด/เปิด, ลบ

mpkey list
HASH           NAME                     ENABLED RATE   EXPIRES             LAST_USED           EMAIL
3f9c0a1b7e2d   app-x                    true    60     never               2026-09-27T16:55:24 owner@example.com
7b21d0c94a5e   backup-cron              true    10     never                                   -

mpkey disable 3f9c    # ปิดชั่วคราว มีผลทันที + แจ้งเจ้าของ (ใส่แค่ต้นของ hash ที่ไม่ซ้ำกับตัวอื่นก็พอ)
mpkey enable  3f9c    # เปิดคืน + แจ้งเจ้าของ
mpkey delete  3f9c    # ลบถาวร + แจ้งเจ้าของ

ถ้า hash prefix ตรงกับ key 0 ตัวหรือมากกว่า 1 ตัว คำสั่งจะหยุดโดยไม่แก้ไขอะไร

3.5 Mapping อีเมล และ audit log

ที่เก็บเนื้อหาอายุข้อมูล
Redis mailproxy:apikey:<hash> field emailอีเมลเจ้าของของ key ที่ยังอยู่ (ดูได้จาก mpkey list)ลบไปพร้อม key · Redis เปิด AOF ไว้แล้ว
Audit log บนเครื่องผู้ดูแล1 บรรทัดต่อ action: เวลา, action, ผู้สั่ง, hash, ชื่อ, อีเมล · ไม่มีค่า keyเก็บถาวร ยังอยู่แม้ key ถูกลบ
# ประวัติของ key ใด key หนึ่ง / ของเจ้าของคนหนึ่ง
grep 'hash=3f9c' <audit log>
grep 'email=owner@example.com' <audit log>
2026-09-27T17:56:50+0700 create by=admin hash=3f9c0a1b7e2d name=app-x email=owner@example.com rate=60 expires=never templates=*
2026-09-27T17:56:53+0700 disable by=admin hash=3f9c0a1b7e2d name=app-x email=owner@example.com

3.6 ข้อจำกัดของ mpkey

3.7 แนวทางตั้งชื่อและค่า

หัวข้อแนวทาง
ชื่อ key<ระบบ>-<env> เช่น wazuh-prod หรือ n8n-sit 1 ระบบใช้ 1 key เพื่อให้เพิกถอนแยกกันได้
rate limitalert ทั่วไปใช้ 10–60/นาที ระบบที่อาจยิงถี่ (SIEM) ใช้ 100 ไม่ควรตั้ง 0 ถ้าไม่จำเป็น
วันหมดอายุkey ทดสอบหรือของผู้รับเหมาให้ตั้งเสมอ เช่น 1–90 วัน
ขอบเขต templateระบบที่ใช้ template เดียวให้จำกัดไว้ เช่น wazuh

4. API Reference

Base URL: https://mailproxy.ipv9.me · ยืนยันตัวตนด้วย header X-API-Key: mp_... · ส่งข้อมูลเป็น Content-Type: application/json

MethodPathAuthคำอธิบาย
GET/health—สถานะระบบ: healthy หรือ degraded
POST/api/v1/send✔ส่งอีเมลโดยกำหนด subject และ body เอง
POST/api/v1/send/template✔ส่งอีเมลด้วย template
GET/api/v1/templates✔รายการ template และ field ที่ต้องใช้ (ใช้ทดสอบ key ได้โดยไม่ส่งเมล)
GET/docs, /redoc, /openapi.json—เอกสาร API แบบโต้ตอบ

POST /api/v1/send: request body

FieldTypeต้องใส่คำอธิบาย
tostring | string[]✔ผู้รับ 1 คนหรือหลายคน (ระบบตรวจรูปแบบอีเมลให้)
subjectstring✔ห้ามว่าง ระบบตัดช่องว่างหัวท้ายให้
bodystring✔เนื้อหา plain text หรือ HTML
htmlbooltrue = ส่งเป็น text/html (ค่าเริ่มต้น false)
sender_namestringชื่อที่แสดงในช่อง From
from_addremailค่าเริ่มต้นคือบัญชี relay ขององค์กร (ดูข้อจำกัดในหัวข้อ 8)
cc, bccstring[]สำเนา / สำเนาลับ

Response (HTTP 200)

{
  "success": true,
  "message_id": "ef8ce787-3faa-46c2-961e-daf7a64001c1",
  "timestamp": "2026-09-27T09:58:08.681369",
  "recipient": "user@example.com",
  "template": null,
  "error": null
}

Response headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (unix time ที่ตัวนับจะเริ่มใหม่) · header Message-ID ของอีเมลคือ <message_id@mailproxy.ipv9.me> ใช้ค้นย้อนหลังได้

5. ตัวอย่างการใช้งาน

ทุกตัวอย่างอ่าน key จาก environment variable MAILPROXY_KEY หรือจากไฟล์ ห้ามเขียน key ลงในโค้ดโดยตรง

ส่งแบบพื้นฐาน

curl -sS -X POST https://mailproxy.ipv9.me/api/v1/send \
  -H "X-API-Key: $MAILPROXY_KEY" -H 'Content-Type: application/json' \
  -d '{"to":"user@example.com","subject":"Test","body":"Hello from Mail Proxy"}'

หลายผู้รับ + CC/BCC + ชื่อผู้ส่ง

curl -sS -X POST https://mailproxy.ipv9.me/api/v1/send \
  -H "X-API-Key: $MAILPROXY_KEY" -H 'Content-Type: application/json' \
  -d '{
    "to": ["ops1@example.com","ops2@example.com"],
    "cc": ["lead@example.com"],
    "bcc": ["audit@example.com"],
    "sender_name": "ระบบงานตรวจสอบ",
    "subject": "สรุปผลตรวจประจำวัน",
    "body": "ผ่าน 42 รายการ / ไม่ผ่าน 0 รายการ"
  }'

HTML body

curl -sS -X POST https://mailproxy.ipv9.me/api/v1/send \
  -H "X-API-Key: $MAILPROXY_KEY" -H 'Content-Type: application/json' \
  -d '{"to":"user@example.com","subject":"Report","html":true,
       "body":"<h2>Daily report</h2><p style=\"color:#1a7f37\">All systems OK</p>"}'

อ่าน key จากไฟล์ (key ไม่อยู่ใน argv และไม่โผล่ใน ps)

# /etc/myapp.key (0600) มี 1 บรรทัด: X-API-Key: mp_...
curl -sS -X POST https://mailproxy.ipv9.me/api/v1/send -H @/etc/myapp.key \
  -H 'Content-Type: application/json' -d @payload.json

Script แจ้งเตือนเมื่อคำสั่งล้มเหลว (ใช้กับ cron ได้)

#!/bin/sh
# usage: notify-on-fail.sh <command...>   — ส่งเมลเมื่อ command จบด้วย exit ≠ 0
out=$("$@" 2>&1); rc=$?
[ $rc -eq 0 ] && exit 0
payload=$(python3 -c 'import json,sys,socket
print(json.dumps({"to":"ops@example.com","sender_name":"Cron Monitor",
 "subject":f"[FAIL] {socket.gethostname()}: {sys.argv[1]} (rc={sys.argv[2]})",
 "body":sys.argv[3][-4000:]}))' "$*" "$rc" "$out")
curl -sS --max-time 30 -X POST https://mailproxy.ipv9.me/api/v1/send \
  -H @/etc/notify.key -H 'Content-Type: application/json' -d "$payload" \
  | grep -q '"success":true' || logger -t notify "mailproxy send failed"
exit $rc

ใช้ใน crontab: 0 2 * * * /usr/local/bin/notify-on-fail.sh /opt/backup/run.sh

Python (requests) พร้อม retry เมื่อโดน 429 หรือ 503

import os, time, requests

URL = "https://mailproxy.ipv9.me/api/v1/send"
HDR = {"X-API-Key": os.environ["MAILPROXY_KEY"]}

def send_mail(to, subject, body, html=False, retries=3, **extra):
    payload = {"to": to, "subject": subject, "body": body, "html": html, **extra}
    for attempt in range(retries):
        r = requests.post(URL, json=payload, headers=HDR, timeout=30)
        if r.status_code == 200:
            return r.json()["message_id"]
        if r.status_code == 429:                       # rate limited
            time.sleep(int(r.headers.get("Retry-After", 60)))
        elif r.status_code == 503:                     # SMTP relay error
            time.sleep(2 ** attempt * 5)
        else:                                          # 401/403/422: ไม่ต้อง retry
            raise RuntimeError(f"{r.status_code}: {r.text}")
    raise RuntimeError("mailproxy: retries exhausted")

send_mail(["a@example.com", "b@example.com"], "Backup done", "OK",
          sender_name="Backup Bot", cc=["lead@example.com"])

Python stdlib (ไม่ต้องติดตั้ง package)

import json, os, urllib.request

req = urllib.request.Request(
    "https://mailproxy.ipv9.me/api/v1/send/template",
    data=json.dumps({
        "to": "ops@example.com",
        "template": "system",
        "sender_name": "Disk Monitor",
        "data": {"hostname": os.uname().nodename, "alert_type": "Disk usage",
                 "severity": "WARNING", "message": "/var at 91%"}
    }).encode(),
    headers={"X-API-Key": os.environ["MAILPROXY_KEY"], "Content-Type": "application/json"},
)
print(json.load(urllib.request.urlopen(req, timeout=30)))

Node.js 18+ (ใช้ fetch ที่มีในตัว)

const res = await fetch("https://mailproxy.ipv9.me/api/v1/send", {
  method: "POST",
  headers: { "X-API-Key": process.env.MAILPROXY_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    to: ["dev@example.com"],
    subject: `Deploy ${process.env.APP_VERSION} finished`,
    body: "Deploy succeeded",
    html: true,
    sender_name: "CI/CD",
  }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json(), "remaining:", res.headers.get("x-ratelimit-remaining"));

PHP (cURL)

<?php
$ch = curl_init('https://mailproxy.ipv9.me/api/v1/send');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('MAILPROXY_KEY'), 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode([
    'to' => 'user@example.com',
    'subject' => 'แจ้งเตือนจากระบบ',
    'body' => 'ข้อความภาษาไทยรองรับ UTF-8',
    'sender_name' => 'ระบบสารสนเทศ',
  ], JSON_UNESCAPED_UNICODE),
]);
$resp = json_decode(curl_exec($ch), true);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($code !== 200) { error_log("mailproxy $code: " . json_encode($resp)); }

PowerShell (Windows)

$body = @{
  to          = @("helpdesk@example.com")
  subject     = "[Windows] $env:COMPUTERNAME service stopped"
  body        = (Get-Service Spooler | Out-String)
  sender_name = "Windows Monitor"
} | ConvertTo-Json

Invoke-RestMethod -Method Post -Uri "https://mailproxy.ipv9.me/api/v1/send" `
  -Headers @{ "X-API-Key" = $env:MAILPROXY_KEY } `
  -ContentType "application/json; charset=utf-8" `
  -Body ([System.Text.Encoding]::UTF8.GetBytes($body))

n8n: HTTP Request node

ค่าตั้งเป็น
Method / URLPOST · https://mailproxy.ipv9.me/api/v1/send
AuthenticationGeneric Credential → Header Auth · Name X-API-Key · Value = key (เก็บเป็น credential ของ n8n ไม่ใส่ใน node)
BodyJSON:
{
  "to": "{{ $json.email }}",
  "subject": "Ticket #{{ $json.id }} updated",
  "body": "{{ $json.summary }}",
  "sender_name": "Service Desk"
}

ตั้ง Options → Retry On Fail = 3 และ Wait Between Tries = 60000 ms เพื่อรองรับกรณีโดน 429

6. Templates

templateSubject ที่ได้Field ที่ต้องใส่Field เสริม
wazuh[Wazuh Alert] {level}: {rule_description}level, rule_id, rule_description, agent_name, agent_ipfull_log, timestamp
zimbra[Zimbra Alert] {alert_type}: {summary}alert_type, summarydetails, timestamp
system[System Alert] {hostname}: {alert_type}hostname, alert_type, severity, messagetimestamp
custom{subject}subject, body—

ถ้าไม่ส่ง timestamp ระบบจะใส่เวลาปัจจุบัน (Asia/Bangkok) ให้

curl -sS -X POST https://mailproxy.ipv9.me/api/v1/send/template \
  -H "X-API-Key: $MAILPROXY_KEY" -H 'Content-Type: application/json' \
  -d '{
    "to": "soc@example.com",
    "template": "wazuh",
    "sender_name": "Wazuh SIEM",
    "data": {
      "level": 12, "rule_id": "100409", "rule_description": "MISP threat IP on web",
      "agent_name": "web-01", "agent_ip": "192.0.2.10",
      "full_log": "GET /wp-login.php from 203.0.113.9"
    }
  }'

7. Error codes

HTTPcodeสาเหตุสิ่งที่ client ควรทำ
401INVALID_API_KEYไม่ส่ง header หรือ key ไม่ถูกต้องตรวจ key ห้าม retry
401API_KEY_DISABLEDผู้ดูแลปิด key นี้ไว้ติดต่อผู้ดูแล
401API_KEY_EXPIREDkey หมดอายุแล้วขอ key ใหม่
403TEMPLATE_NOT_ALLOWEDkey นี้ไม่ได้รับสิทธิ์ใช้ template นี้ใช้ template ที่ได้รับอนุญาต
400MISSING_TEMPLATE_DATAfield ที่ template ต้องใช้ขาดหรือว่างเติม field ตามข้อความ error
422(validation)JSON ผิดรูปแบบ, อีเมลไม่ถูกต้อง, subject/body ว่างแก้ payload
429RATE_LIMIT_EXCEEDEDเกินโควตาของนาทีนี้รอตาม header Retry-After แล้วค่อยส่งใหม่
503SMTP_ERRORส่งต่อไป Postfix ไม่สำเร็จretry แบบ backoff และตรวจ /health
530 / 1033(Cloudflare)tunnel ไม่มี connector ทำงานอยู่แจ้งผู้ดูแล

รูปแบบ error: {"detail":{"code":"RATE_LIMIT_EXCEEDED","message":"...","retry_after":42}}

8. ข้อจำกัดของระบบ

หัวข้อข้อจำกัด
ไฟล์แนบไม่รองรับ ส่งได้แค่ text หรือ HTML ถ้าจำเป็นให้ใส่เป็นลิงก์ดาวน์โหลดแทน
multipart/alternativeส่งได้ทีละแบบ คือ plain หรือ HTML ไม่มี text สำรองในฉบับ HTML · /send/template เป็น plain text เสมอ
ความหมายของ "success"success:true แปลว่า Postfix รับเมลเข้าคิวแล้ว ยังไม่ได้แปลว่าถึงกล่องผู้รับ ถ้าปลายทางตีกลับหรือ Gmail ปฏิเสธ client จะไม่รู้ ต้องดู log ของ mailrelay
ผู้ส่ง (From)ส่งผ่านบัญชี Gmail ขององค์กร ถ้ากำหนด from_addr เป็นอีเมลอื่น Gmail อาจเขียน From ทับเป็นบัญชีที่ใช้ login เว้นแต่ address นั้นตั้งเป็น "Send mail as" ไว้ในบัญชี · sender_name ใช้ได้เสมอ
โควตาการส่งอยู่ภายใต้โควตาของ Google Workspace ของบัญชี relay (ประมาณ 2,000 ฉบับ/วัน และนับผู้รับแต่ละคน) ถ้าเกิน Gmail จะหยุดส่งชั่วคราว ไม่ควรใช้ส่งจดหมายข่าวหรือ bulk mail
Rate limitนับแบบ fixed window ต่อนาทีปฏิทิน ต่อ key ตอนขึ้นนาทีใหม่อาจส่งได้เกินชั่วคราวสูงสุด 2 เท่า · request ที่ผ่านการตรวจ key แล้วถูกนับทุกครั้ง รวมถึงที่จบด้วย 400/403/503 (ส่วน 401 และ 422 ไม่นับ) · GET /templates ไม่นับ
Idempotencyไม่มี ถ้า client retry หลัง timeout ทั้งที่รอบแรกส่งสำเร็จแล้ว ผู้รับจะได้เมลซ้ำ
High availabilitySMTP relay และ key store รันแบบ instance เดียว ถ้าเครื่องที่รันล่ม ระบบจะส่งเมลไม่ได้และ auth ไม่ได้จนกว่าเครื่องจะกลับมา · API มี 1 instance
ขนาดPostfix จำกัดขนาดเมล 50 MB แต่แนะนำให้ body ไม่เกินหลักร้อย KB
การจัดการ keyไม่มี admin API หรือ UI ผู้ดูแลจัดการผ่าน mpkey · สถิติเก็บ 30 วัน · การแจ้งเตือนทางอีเมลขึ้นกับ Mail Proxy เอง ถ้าระบบล่มจะไม่มีเมลแจ้ง
Endpoint สาธารณะ/health และ /docs เปิดให้ทุกคนเข้าได้ · CORS อนุญาตทุก origin ดังนั้นห้ามเรียก API จาก JavaScript ฝั่ง browser เพราะ key จะหลุด

9. Operations (ผู้ดูแลระบบ)

ขั้นตอนดูแลระบบ เช่น log, คิวเมล, deploy, secret และการปิดทางเข้าฉุกเฉิน อยู่ในคู่มือฉบับภายในซึ่งไม่เผยแพร่สาธารณะ
ผู้ใช้งานตรวจสถานะได้เองที่ GET https://mailproxy.ipv9.me/health (healthy = พร้อมใช้งาน)

10. แนวปฏิบัติด้านความปลอดภัย

ควรทำ
  • 1 ระบบใช้ 1 key · เก็บใน secret manager, vault หรือไฟล์ 0600 · ส่ง key ด้วย curl -H @file เพื่อไม่ให้โผล่ใน ps
  • ตั้งวันหมดอายุให้ key ชั่วคราว · จำกัด template ให้แคบที่สุดเท่าที่ใช้
  • ตรวจ mpkey list เป็นระยะ ปิด key ที่ไม่มี LAST_USED นานเกิน 90 วัน
  • ผูกอีเมลเจ้าของ (--mail) ให้ทุก key เพื่อให้ติดต่อได้เมื่อต้องปิด key · ถ้าได้รับ key ทางอีเมล ให้ย้ายเข้า vault แล้วลบเมลทันที
ห้ามทำ
  • ใส่ key ใน source code, Git, ข้อความแชท, ticket หรือ JavaScript ฝั่ง browser
  • ใช้ key เดียวร่วมกันหลายระบบ เพราะจะเพิกถอนแยกไม่ได้
  • ส่ง key ด้วย --mail ไปยังอีเมลส่วนตัว, forwarder หรือกล่องที่หลายคนเข้าถึงได้
  • ใส่ข้อมูลลับหรือข้อมูลส่วนบุคคลใน body โดยไม่จำเป็น เพราะเมลผ่าน Gmail และ log ของ relay

ถ้าสงสัยว่า key หลุด: mpkey disable <hash> ทันที (เจ้าของได้รับเมลแจ้ง) → mpkey create … --mail <เจ้าของ> สร้าง key ใหม่ → mpkey delete key เดิม