Test MAS addresses against real Postfix; close MAS-WP-0002, add MAS-WP-0003

- experiments/postfix-probe: Postfix 3.7 -> pipe -> mas-gateway -> ticket
  service in Docker; 14 address forms x 5 configurations. 13/14 arrive
  byte-identical everywhere; quoted "ticket=PR42" is unquoted in transit.
  Legacy bang/percent rewrites never fire for MAS addresses.
- docs/experiment-review.md: Email infrastructure section with results
- MAS-WP-0003: provider-side live test on a real subdomain (needs DNS/MX)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 623586@bnt-lap001
Assistant-Session: 10b30928-5b3b-4c11-9934-5ecca07367d8
This commit is contained in:
tegwick 2026-10-08 00:51:27 +02:00
parent 8d3878d9c8
commit e19d557a4c
13 changed files with 1179 additions and 20 deletions

View file

@ -0,0 +1,8 @@
# Real Postfix -> pipe transport -> mas-gateway -> reference ticket service.
FROM debian:bookworm-slim
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
postfix python3 python3-jsonschema ca-certificates && rm -rf /var/lib/apt/lists/*
RUN useradd -r -s /usr/sbin/nologin mas
COPY entrypoint.sh /entrypoint.sh
EXPOSE 25 8024 8025
ENTRYPOINT ["/bin/sh", "/entrypoint.sh"]

View file

@ -0,0 +1,29 @@
# Postfix probe
A real Postfix delivers MAS addresses through the `pipe` transport to
`mas-gateway` and on to the reference ticket service. A capture proxy
(`capture.py`) records the envelope recipient each event carried, so the
probe can tell whether Postfix rewrote anything.
```bash
docker build -t mas-postfix-probe experiments/postfix-probe
python3 experiments/postfix-probe/probe.py --profile defaults # relay domain
python3 experiments/postfix-probe/probe.py --profile local-domain # domain in mydestination
python3 experiments/postfix-probe/probe.py --profile local-domain-safe # + swap_bangpath/percent_hack off
```
The other profiles are `defaults-local` and `mas-safe-local`. The repo is
mounted read-only. In `results/` a `=` mark means the address arrived
unchanged and `!` means it was rewritten. Findings are in
`docs/experiment-review.md` under *Email infrastructure*.
The Postfix side is the `master.cf` entry in `entrypoint.sh`:
```
mas unix - n n - - pipe
flags=Rq user=mas argv=/usr/local/bin/mas-gateway --statute <statute>
pipe --app-url http://127.0.0.1:8024/mas-events --recipient ${recipient}
```
Set `mas_destination_recipient_limit = 1` so each pipe invocation handles
one recipient.

View file

@ -0,0 +1,40 @@
"""Probe-only proxy: records each MAS event as delivered by Postfix, then
forwards it to the ticket service and records the app's answer."""
import json
import sys
import urllib.error
import urllib.request
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
UPSTREAM = sys.argv[1]
EVENTS = []
class H(BaseHTTPRequestHandler):
def do_POST(self):
body = self.rfile.read(int(self.headers.get("Content-Length", "0")))
req = urllib.request.Request(UPSTREAM, body, {"Content-Type": "application/json"})
try:
with urllib.request.urlopen(req) as r:
status, resp = r.status, r.read()
except urllib.error.HTTPError as e:
status, resp = e.code, e.read()
EVENTS.append({"event": json.loads(body), "app_status": status, "app": json.loads(resp or b"null")})
self._send(status, resp)
def do_GET(self):
self._send(200, json.dumps(EVENTS).encode())
def _send(self, status, body):
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, *a):
pass
ThreadingHTTPServer(("0.0.0.0", 8024), H).serve_forever()

View file

@ -0,0 +1,42 @@
#!/bin/sh
# Repo is mounted read-only at /mas. PROFILE=defaults|mas-safe selects Postfix settings.
set -e
cat > /usr/local/bin/mas-gateway <<'SH'
#!/bin/sh
exec env PYTHONPATH=/mas python3 -m mas_gateway.main "$@"
SH
chmod +x /usr/local/bin/mas-gateway
postconf -e "maillog_file=/dev/stdout" "myhostname=mx.probe.test" "mydestination=" \
"relay_domains=great-service.example" "transport_maps=inline:{great-service.example=mas:}" \
"mynetworks=0.0.0.0/0" "smtpd_relay_restrictions=permit_mynetworks,reject" \
"mas_destination_recipient_limit=1" "recipient_delimiter=+" "compatibility_level=3.6"
# PROFILE: defaults - Postfix defaults; probe client is "remote" (no address rewriting)
# defaults-local - defaults, but every client gets the local rewrite context
# mas-safe-local - local rewrite context with swap_bangpath/allow_percent_hack off
# local-domain - domain served via mydestination (local delivery class), defaults
# local-domain-safe - local-domain with swap_bangpath/allow_percent_hack off
case "$PROFILE" in
local-domain*) postconf -e "relay_domains=" "transport_maps=" "mydestination=great-service.example" \
"local_transport=mas" "local_recipient_maps=" ;;
esac
case "$PROFILE" in
*-local) postconf -e "local_header_rewrite_clients=static:all" ;;
esac
case "$PROFILE" in
mas-safe*|*-safe) postconf -e "swap_bangpath=no" "allow_percent_hack=no" ;;
esac
cat >> /etc/postfix/master.cf <<'CF'
mas unix - n n - - pipe
flags=Rq user=mas argv=/usr/local/bin/mas-gateway
--statute /mas/examples/statute/great-service.example/.well-known/mas
pipe --app-url http://127.0.0.1:8024/mas-events --recipient ${recipient}
CF
# Postfix runs `mas-gateway` as user mas; the service needs a writable DB.
mkdir -p /var/lib/tickets && chown mas /var/lib/tickets
su -s /bin/sh mas -c "PYTHONPATH=/mas python3 /mas/examples/ticket_service/ticket_service.py \
--db /var/lib/tickets/t.sqlite3 --listen 0.0.0.0:8025" &
python3 /mas/experiments/postfix-probe/capture.py http://127.0.0.1:8025/mas-events &
echo "PROFILE=${PROFILE:-defaults}"
postconf swap_bangpath allow_percent_hack recipient_delimiter local_header_rewrite_clients
exec postfix start-fg

View file

@ -0,0 +1,118 @@
#!/usr/bin/env python3
"""Send MAS test addresses through a real Postfix and report what arrived.
python experiments/postfix-probe/probe.py --profile defaults
python experiments/postfix-probe/probe.py --profile defaults-local
python experiments/postfix-probe/probe.py --profile mas-safe-local
Starts the mas-postfix-probe container, sends one message per address via
SMTP, then compares the envelope recipient Postfix handed to mas-gateway
with the one that was sent.
"""
import argparse
import json
import smtplib
import subprocess
import sys
import time
import urllib.request
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
D = "great-service.example"
# (label, local-part as sent in RCPT TO). "{ID}" is filled with the created ticket id.
CASES = [
("P2 intake", "ticket!callback"),
("resource", "ticket={ID}"),
("resource + facet", "ticket={ID}+comments"),
("extra '=' in id", "ticket==X1"),
("registry function", "support"),
("person-style", "bernd.worsch"),
("upper-case local-part", "Ticket={ID}"),
("percent data", "ticket=PR%2B42"),
("percent hack form", "ticket%other.example"),
("bang in resource", "ticket={ID}!web"),
("facet + interaction", "ticket={ID}+comments!callback"),
("reserved $", "ticket=PR42$4.99"),
("quoted local-part", '"ticket=PR42"'),
("unknown resource", "ticket=DOES-NOT-EXIST"),
]
def run(profile, port):
name = f"mas-probe-{profile}"
subprocess.run(["docker", "rm", "-f", name], capture_output=True)
subprocess.run(["docker", "run", "-d", "--name", name, "-e", f"PROFILE={profile}",
"-v", f"{ROOT}:/mas:ro", "-p", f"127.0.0.1:{port}:25",
"-p", f"127.0.0.1:{port + 1}:8024", "mas-postfix-probe"], check=True,
capture_output=True)
try:
for _ in range(60):
try:
smtplib.SMTP("127.0.0.1", port, timeout=2).quit()
break
except OSError:
time.sleep(0.5)
results, tid = [], None
for label, lp in CASES:
rcpt_lp = lp.replace("{ID}", tid or "MISSING")
rcpt = f"{rcpt_lp}@{D}"
msg = (f"From: probe@example.net\r\nTo: {rcpt}\r\nSubject: {label}\r\n"
f"Message-ID: <{abs(hash(rcpt))}@example.net>\r\n\r\nprobe\r\n")
before = len(events(port))
try:
with smtplib.SMTP("127.0.0.1", port, timeout=10) as s:
refused = s.sendmail("probe@example.net", [rcpt], msg)
smtp = "accepted" if not refused else f"refused {refused}"
except smtplib.SMTPException as e:
smtp = f"rejected: {e}"
got = wait_event(port, before) if smtp == "accepted" else None
arrived = got["event"]["recipient"] if got else None
mas = got["event"]["mas"] if got else {}
app = got["app"] if got else None
if label == "P2 intake" and app:
tid = app.get("ticket_id")
results.append({"label": label, "sent": rcpt, "smtp": smtp, "arrived_as": arrived,
"unchanged": arrived == rcpt,
"mas_valid": mas.get("valid"), "kind": mas.get("kind"),
"app_status": got["app_status"] if got else None,
"app": (app or {}).get("status") if isinstance(app, dict) else app})
logs = subprocess.run(["docker", "logs", name], capture_output=True, text=True)
return results, logs.stdout + logs.stderr
finally:
subprocess.run(["docker", "rm", "-f", name], capture_output=True)
def events(port):
with urllib.request.urlopen(f"http://127.0.0.1:{port + 1}/") as r:
return json.loads(r.read())
def wait_event(port, before, timeout=15):
end = time.time() + timeout
while time.time() < end:
ev = events(port)
if len(ev) > before:
return ev[-1]
time.sleep(0.3)
return None
if __name__ == "__main__":
ap = argparse.ArgumentParser()
ap.add_argument("--profile", choices=["defaults", "defaults-local", "mas-safe-local", "local-domain", "local-domain-safe"], default="defaults")
ap.add_argument("--port", type=int, default=2525)
ap.add_argument("--json", metavar="FILE")
ap.add_argument("--log", metavar="FILE")
a = ap.parse_args()
results, log = run(a.profile, a.port)
for r in results:
mark = "=" if r["unchanged"] else "!"
print(f"{mark} {r['label']:<22} {r['sent']:<52} -> {r['arrived_as'] or r['smtp']}"
f" [{r['kind']}/{r['app']}]")
if a.json:
Path(a.json).write_text(json.dumps({"profile": a.profile, "results": results}, indent=2) + "\n")
if a.log:
Path(a.log).write_text(log)
sys.exit(0)

View file

@ -0,0 +1,159 @@
{
"profile": "defaults-local",
"results": [
{
"label": "P2 intake",
"sent": "ticket!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 201,
"app": "created"
},
{
"label": "resource",
"sent": "ticket=GS-9G9WEYSMDH@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-9G9WEYSMDH@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "resource + facet",
"sent": "ticket=GS-9G9WEYSMDH+comments@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-9G9WEYSMDH+comments@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "extra '=' in id",
"sent": "ticket==X1@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket==X1@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "registry function",
"sent": "support@great-service.example",
"smtp": "accepted",
"arrived_as": "support@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 404,
"app": "not-handled"
},
{
"label": "person-style",
"sent": "bernd.worsch@great-service.example",
"smtp": "accepted",
"arrived_as": "bernd.worsch@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "upper-case local-part",
"sent": "Ticket=GS-9G9WEYSMDH@great-service.example",
"smtp": "accepted",
"arrived_as": "Ticket=GS-9G9WEYSMDH@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "percent data",
"sent": "ticket=PR%2B42@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR%2B42@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "percent hack form",
"sent": "ticket%other.example@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket%other.example@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "bang in resource",
"sent": "ticket=GS-9G9WEYSMDH!web@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-9G9WEYSMDH!web@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "facet + interaction",
"sent": "ticket=GS-9G9WEYSMDH+comments!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-9G9WEYSMDH+comments!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "reserved $",
"sent": "ticket=PR42$4.99@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42$4.99@great-service.example",
"unchanged": true,
"mas_valid": false,
"kind": null,
"app_status": 422,
"app": "not-mas"
},
{
"label": "quoted local-part",
"sent": "\"ticket=PR42\"@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42@great-service.example",
"unchanged": false,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "unknown resource",
"sent": "ticket=DOES-NOT-EXIST@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=DOES-NOT-EXIST@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
}
]
}

View file

@ -0,0 +1,159 @@
{
"profile": "defaults",
"results": [
{
"label": "P2 intake",
"sent": "ticket!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 201,
"app": "created"
},
{
"label": "resource",
"sent": "ticket=GS-2H6T5NBH6K@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-2H6T5NBH6K@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "resource + facet",
"sent": "ticket=GS-2H6T5NBH6K+comments@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-2H6T5NBH6K+comments@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "extra '=' in id",
"sent": "ticket==X1@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket==X1@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "registry function",
"sent": "support@great-service.example",
"smtp": "accepted",
"arrived_as": "support@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 404,
"app": "not-handled"
},
{
"label": "person-style",
"sent": "bernd.worsch@great-service.example",
"smtp": "accepted",
"arrived_as": "bernd.worsch@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "upper-case local-part",
"sent": "Ticket=GS-2H6T5NBH6K@great-service.example",
"smtp": "accepted",
"arrived_as": "Ticket=GS-2H6T5NBH6K@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "percent data",
"sent": "ticket=PR%2B42@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR%2B42@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "percent hack form",
"sent": "ticket%other.example@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket%other.example@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "bang in resource",
"sent": "ticket=GS-2H6T5NBH6K!web@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-2H6T5NBH6K!web@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "facet + interaction",
"sent": "ticket=GS-2H6T5NBH6K+comments!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-2H6T5NBH6K+comments!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "reserved $",
"sent": "ticket=PR42$4.99@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42$4.99@great-service.example",
"unchanged": true,
"mas_valid": false,
"kind": null,
"app_status": 422,
"app": "not-mas"
},
{
"label": "quoted local-part",
"sent": "\"ticket=PR42\"@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42@great-service.example",
"unchanged": false,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "unknown resource",
"sent": "ticket=DOES-NOT-EXIST@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=DOES-NOT-EXIST@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
}
]
}

View file

@ -0,0 +1,159 @@
{
"profile": "local-domain-safe",
"results": [
{
"label": "P2 intake",
"sent": "ticket!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 201,
"app": "created"
},
{
"label": "resource",
"sent": "ticket=GS-VZZRSGXV12@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-VZZRSGXV12@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "resource + facet",
"sent": "ticket=GS-VZZRSGXV12+comments@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-VZZRSGXV12+comments@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "extra '=' in id",
"sent": "ticket==X1@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket==X1@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "registry function",
"sent": "support@great-service.example",
"smtp": "accepted",
"arrived_as": "support@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 404,
"app": "not-handled"
},
{
"label": "person-style",
"sent": "bernd.worsch@great-service.example",
"smtp": "accepted",
"arrived_as": "bernd.worsch@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "upper-case local-part",
"sent": "Ticket=GS-VZZRSGXV12@great-service.example",
"smtp": "accepted",
"arrived_as": "Ticket=GS-VZZRSGXV12@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "percent data",
"sent": "ticket=PR%2B42@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR%2B42@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "percent hack form",
"sent": "ticket%other.example@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket%other.example@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "bang in resource",
"sent": "ticket=GS-VZZRSGXV12!web@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-VZZRSGXV12!web@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "facet + interaction",
"sent": "ticket=GS-VZZRSGXV12+comments!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-VZZRSGXV12+comments!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "reserved $",
"sent": "ticket=PR42$4.99@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42$4.99@great-service.example",
"unchanged": true,
"mas_valid": false,
"kind": null,
"app_status": 422,
"app": "not-mas"
},
{
"label": "quoted local-part",
"sent": "\"ticket=PR42\"@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42@great-service.example",
"unchanged": false,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "unknown resource",
"sent": "ticket=DOES-NOT-EXIST@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=DOES-NOT-EXIST@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
}
]
}

View file

@ -0,0 +1,159 @@
{
"profile": "local-domain",
"results": [
{
"label": "P2 intake",
"sent": "ticket!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 201,
"app": "created"
},
{
"label": "resource",
"sent": "ticket=GS-D4QGSR85P2@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-D4QGSR85P2@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "resource + facet",
"sent": "ticket=GS-D4QGSR85P2+comments@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-D4QGSR85P2+comments@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "extra '=' in id",
"sent": "ticket==X1@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket==X1@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "registry function",
"sent": "support@great-service.example",
"smtp": "accepted",
"arrived_as": "support@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 404,
"app": "not-handled"
},
{
"label": "person-style",
"sent": "bernd.worsch@great-service.example",
"smtp": "accepted",
"arrived_as": "bernd.worsch@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "upper-case local-part",
"sent": "Ticket=GS-D4QGSR85P2@great-service.example",
"smtp": "accepted",
"arrived_as": "Ticket=GS-D4QGSR85P2@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "percent data",
"sent": "ticket=PR%2B42@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR%2B42@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "percent hack form",
"sent": "ticket%other.example@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket%other.example@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "bang in resource",
"sent": "ticket=GS-D4QGSR85P2!web@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-D4QGSR85P2!web@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "facet + interaction",
"sent": "ticket=GS-D4QGSR85P2+comments!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-D4QGSR85P2+comments!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "reserved $",
"sent": "ticket=PR42$4.99@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42$4.99@great-service.example",
"unchanged": true,
"mas_valid": false,
"kind": null,
"app_status": 422,
"app": "not-mas"
},
{
"label": "quoted local-part",
"sent": "\"ticket=PR42\"@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42@great-service.example",
"unchanged": false,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "unknown resource",
"sent": "ticket=DOES-NOT-EXIST@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=DOES-NOT-EXIST@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
}
]
}

View file

@ -0,0 +1,159 @@
{
"profile": "mas-safe-local",
"results": [
{
"label": "P2 intake",
"sent": "ticket!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 201,
"app": "created"
},
{
"label": "resource",
"sent": "ticket=GS-V5KFZ1PGY5@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-V5KFZ1PGY5@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "resource + facet",
"sent": "ticket=GS-V5KFZ1PGY5+comments@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-V5KFZ1PGY5+comments@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "extra '=' in id",
"sent": "ticket==X1@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket==X1@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "registry function",
"sent": "support@great-service.example",
"smtp": "accepted",
"arrived_as": "support@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "function",
"app_status": 404,
"app": "not-handled"
},
{
"label": "person-style",
"sent": "bernd.worsch@great-service.example",
"smtp": "accepted",
"arrived_as": "bernd.worsch@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "upper-case local-part",
"sent": "Ticket=GS-V5KFZ1PGY5@great-service.example",
"smtp": "accepted",
"arrived_as": "Ticket=GS-V5KFZ1PGY5@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "percent data",
"sent": "ticket=PR%2B42@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR%2B42@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "percent hack form",
"sent": "ticket%other.example@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket%other.example@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "opaque",
"app_status": 404,
"app": "not-handled"
},
{
"label": "bang in resource",
"sent": "ticket=GS-V5KFZ1PGY5!web@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-V5KFZ1PGY5!web@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "facet + interaction",
"sent": "ticket=GS-V5KFZ1PGY5+comments!callback@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=GS-V5KFZ1PGY5+comments!callback@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 200,
"app": "correlated"
},
{
"label": "reserved $",
"sent": "ticket=PR42$4.99@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42$4.99@great-service.example",
"unchanged": true,
"mas_valid": false,
"kind": null,
"app_status": 422,
"app": "not-mas"
},
{
"label": "quoted local-part",
"sent": "\"ticket=PR42\"@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=PR42@great-service.example",
"unchanged": false,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
},
{
"label": "unknown resource",
"sent": "ticket=DOES-NOT-EXIST@great-service.example",
"smtp": "accepted",
"arrived_as": "ticket=DOES-NOT-EXIST@great-service.example",
"unchanged": true,
"mas_valid": true,
"kind": "resource",
"app_status": 202,
"app": "unknown-resource"
}
]
}