A standalone Swift Package that runs SwiftEmailValidator's 243-case DemoApp corpus against a set of other Swift email validation libraries and prints a Markdown-formatted accuracy table.
Kept separate from the main Package.swift so consumers of
SwiftEmailValidator don't transitively pull competitor dependencies.
| Key | Library |
|---|---|
OursAscii |
SwiftEmailValidator — .ascii mode |
OursAsciiUnicode |
SwiftEmailValidator — .asciiWithUnicodeExtension mode |
OursUnicode |
SwiftEmailValidator — .unicode mode |
EvanRobertsonAscii |
evanrobertson/EmailValidator — allowInternational: false |
EvanRobertsonInternational |
evanrobertson/EmailValidator — allowInternational: true |
MimeParser |
igorrendulic/MimeEmailParser |
Bdolewski |
bdolewski/SwiftEmailValidator — regex vendored (their symbol is internal and can't be imported) |
JweltonEquivalent |
jwelton/EmailValidator — emulated via NSDataDetector to avoid a package-identity collision with evanrobertson's EmailValidator |
Deliberately excluded:
- swift-standards/swift-emailaddress-standard — its manifest uses
.package(path: "../../swift-ietf/…")and requires macOS 26; it isn't consumable as a Git SPM dependency. - SwiftValidator / SwiftValidators / adamwaite/Validator — general-purpose form validators, not RFC-focused email parsers.
cd Benchmarks
swift run -c release EmailBench # print the full report
swift run -c release EmailBench --verbose # also list every failing case
swift run -c release EmailBench --scope # within-declared-scope table only
swift run -c release EmailBench --reverse # run competitor corpora through ours
swift run -c release EmailBench --list # idx → email mapping (for crash discovery)Some competitors call fatalError on adversarial inputs (out-of-bounds string
indexing in their own parsers). Swift's fatalError can't be caught inside
the same process, so those inputs are listed in
Sources/EmailBench/SkipList.swift and
omitted from the library's accuracy denominator. The report surfaces the skip
count and the reason in a separate section.
To re-discover crashers (e.g. after adding new corpus cases) use the worker mode:
swift build -c release
for a in OursAscii OursAsciiUnicode OursUnicode \
EvanRobertsonAscii EvanRobertsonInternational \
MimeParser Bdolewski JweltonEquivalent; do
start=0
while : ; do
.build/arm64-apple-macosx/release/EmailBench \
--worker "$a" --start "$start" 2>/dev/null > /tmp/w.log || true
grep -q '"kind":"done"' /tmp/w.log && break
crash=$(grep '"kind":"begin"' /tmp/w.log | tail -1 \
| sed -E 's/.*"idx":([0-9]+).*/\1/')
echo "$a crashed at idx $crash"
start=$((crash + 1))
done
doneUse --list to map indices back to email strings.