Files
recipe-maintainer/scripts/mailgun_test.py
autonomic-bot f283a371bb recipe-maintainer: public snapshot (secrets + deployment plans removed, single commit)
Sanitized single-commit public mirror of recipe-maintainer.
- Removed test-ssh/.testenv (live creds); added test-ssh/.testenv.example placeholders.
- Removed plans/ and planned-updates/ (deployment-planning docs) so no client/
  deployment domains appear in the public repo.
- All other secret stores were already gitignored.
- docs.coopcloud.tech retained as a submodule (public upstream).
2026-06-16 20:18:24 +00:00

82 lines
2.7 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Test outgoing Mailgun credentials by sending a single email via the HTTP API.
Usage:
MAILGUN_API_KEY='...' MAILGUN_FROM='noreply@example.com' \\
./mailgun_test.py recipient@example.com
Env vars:
MAILGUN_API_KEY (required) — Mailgun API key
MAILGUN_FROM (required) — sender address (must be on a verified domain)
MAILGUN_DOMAIN (optional) — defaults to the domain part of MAILGUN_FROM
MAILGUN_BASE_URI (optional) — defaults to https://api.mailgun.net/v3
use https://api.eu.mailgun.net/v3 for EU region
Prints HTTP status + Mailgun response body. Mailgun returns JSON with an
"id" + "message" on success, or an error string on failure (e.g. bad domain,
unverified sender, invalid key).
"""
import base64
import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request
from email.utils import parseaddr
def main() -> int:
if len(sys.argv) != 2:
print(f"usage: {sys.argv[0]} recipient@example.com", file=sys.stderr)
return 2
recipient = sys.argv[1]
api_key = os.environ.get("MAILGUN_API_KEY")
sender = os.environ.get("MAILGUN_FROM")
if not api_key or not sender:
print("error: MAILGUN_API_KEY and MAILGUN_FROM env vars are required",
file=sys.stderr)
return 2
_, sender_addr = parseaddr(sender)
domain = os.environ.get("MAILGUN_DOMAIN") or sender_addr.split("@", 1)[-1]
base_uri = os.environ.get("MAILGUN_BASE_URI", "https://api.mailgun.net/v3")
url = f"{base_uri.rstrip('/')}/{domain}/messages"
data = urllib.parse.urlencode({
"from": sender,
"to": recipient,
"subject": "Mailgun test from mailgun_test.py",
"text": f"This is a test message sent via {url} as {sender}.\n",
}).encode()
auth = base64.b64encode(f"api:{api_key}".encode()).decode()
req = urllib.request.Request(url, data=data, method="POST")
req.add_header("Authorization", f"Basic {auth}")
req.add_header("Content-Type", "application/x-www-form-urlencoded")
print(f"POST {url}")
print(f" from={sender} to={recipient}")
try:
with urllib.request.urlopen(req, timeout=30) as resp:
body = resp.read().decode()
print(f"\nHTTP {resp.status}")
try:
print(json.dumps(json.loads(body), indent=2))
except json.JSONDecodeError:
print(body)
print(f"\nOK: Mailgun accepted the message")
return 0
except urllib.error.HTTPError as e:
body = e.read().decode(errors="replace")
print(f"\nHTTP {e.code} {e.reason}")
print(body)
return 1
if __name__ == "__main__":
sys.exit(main())