MailCheck API

Programmatic access to email analysis reports

← Back to MailCheck
Rate Limiting: Trace creation is limited to 1 request per 30 seconds per IP address. Exceeding this returns HTTP 429 with a JSON error body and Retry-After header.

Endpoints

POST /api/trace

Create a new trace. Returns a unique email address to send a test email to and a trace ID for polling.

Example:
curl -X POST https://mailcheck.biz/api/trace
Response:
{
  "email": "abcdefgh@xyzabc.mailcheck.biz",
  "traceID": "xyzabc-abcdefgh"
}

GET /api/status/{id}

Poll the status of a trace. Returns the current processing state.

Example:
curl https://mailcheck.biz/api/status/xyzabc-abcdefgh
Response:
{
  "status": "pending"
}
StatusMeaning
pendingWaiting for email to arrive
analyzingEmail received, analysis in progress
readyAnalysis complete, report available
expiredTrace expired (5 min timeout)
notfoundUnknown trace ID

GET /api/report/{id}

Retrieve the full analysis report as JSON. Stored reports are normalized on read, so old trace files are returned using the current public contract.

Example:
curl https://mailcheck.biz/api/report/xyzabc-abcdefgh
Response excerpt:
{
  "id": "xyzabc-abcdefgh",
  "timestamp": "2026-03-06T14:30:00Z",
  "email_auth": {
    "spf": { "result": "pass" },
    "dkim": [{
      "result": "pass",
      "domain": "example.com",
      "selector": "google",
      "algorithm": "rsa-sha256",
      "key_type": "rsa",
      "key_bits": 2048,
      "alignment_result": "pass",
      "alignment_mode": "relaxed",
      "security_score": 82,
      "security_rating": "good",
      "selector_provider": "Google Workspace",
      "signing_software": "Gmail",
      "replay_window": "moderate",
      "header_coverage": {
        "critical_count": 9,
        "critical_total": 13,
        "missing_critical": ["Reply-To", "CC"]
      }
    }],
    "dmarc": {
      "result": "fail",
      "lookup_status": "present",
      "policy": "reject"
    }
  },
  "blacklists": {
    "status": "clean",
    "checked": ["zen.spamhaus.org", "b.barracudacentral.org"],
    "clean": true
  },
  "domain_dns": {
    "mx_state": "explicit",
    "mx_records": [{"host": "mail.example.com", "priority": 10}]
  },
  "active_scan": {
    "banner": "220 mail.example.com ESMTP Postfix",
    "mta_name": "Postfix",
    "jarm_hash": "2ad2ad16d2ad2ad0004...",
    "probe_os_guess": "Linux 4.x-6.x",
    "probe_ja4ts": "65535_2-1-3-1-1-4-1-1-8_1460_8",
    "probe_os_confidence": 0.6,
    "ja4tscan_hash": "65535_2-1-3-1-1-4-1-1-8_1460_8_1-2-4-8",
    "ja4tscan_pattern": "Linux/FreeBSD (exponential backoff)",
    "ja4x_hash": "a5c7e3d...",
    "ja4s_hash": "t13d1716..."
  },
  "server_identity": {
    "primary_mta": "Postfix",
    "trust_score": 87,
    "rating": "Good"
  }
}
Key field semantics:
FieldMeaning
email_auth.dmarc.resultDMARC message verdict: pass, fail, or unknown
email_auth.dmarc.lookup_statusDMARC DNS lookup status: present, none, temperror, or permerror
email_auth.dkim[].resultDKIM verification: pass, fail, none, or temperror
email_auth.dkim[].security_scorePer-signature security score 0-100 (higher = better)
email_auth.dkim[].security_ratingRating: excellent (≥90), good (≥75), fair (≥50), poor (≥25), critical (<25)
email_auth.dkim[].alignment_resultDMARC alignment: pass or fail
email_auth.dkim[].selector_providerDetected email provider from DKIM selector (e.g. "Google Workspace", "Microsoft 365")
email_auth.dkim[].signing_softwareDetected signing software (e.g. "Gmail", "Rspamd", "OpenDKIM")
email_auth.dkim[].replay_windowReplay attack window: safe (≤7d), moderate (7-30d), wide (>30d), unlimited
email_auth.dkim[].header_coverageObject: critical_count, critical_total, missing_critical[], oversigned[]
email_auth.dkim[].security_checks[]Array: id, title, status (pass/warn/fail/info), severity, detail
email_auth.dkim[].body_hash_verifiedIndependent body hash check: pass, fail, or error
email_auth.dkim[].body_modifiedTrue if body was modified after DKIM signing (bh= mismatch)
email_auth.dkim[].failure_typeClassified failure: body_modified, header_modified, key_mismatch, dns_error, syntax_error, expired, revoked
email_auth.dkim[].syntax_validTrue if DKIM-Signature syntax passes all RFC 6376 checks
blacklists.statusAuthoritative DNSBL state: clean, listed, or unknown
blacklists.cleanCompatibility boolean. true only when status=clean; use status for tri-state logic.
domain_dns.mx_stateMail routing state: explicit, implicit, none, or dns_error
tls.parrot_analysis.verdictuTLS / TLS parrot verdict: clean, suspicious (max_conf ≥ 0.7), or parrot_detected (max_conf ≥ 0.9)
tls.parrot_analysis.max_confidenceHighest confidence value among triggered parrot rules (0.0–1.0)
tls.parrot_analysis.triggered_rules[]Array of {key, value, confidence, evidence} for each rule that fired
tls.parrot_analysis.extension_order_hashSHA-256 prefix of ClientHello extension type order — stable across sessions for honest stacks
tls.parrot_analysis.ch_length_mod_512ClientHello length mod 512 (Chrome pads to 512-byte boundary; non-zero on Chrome impostors)
tls.parrot_analysis.psk_binder_lengthsLengths of PSK binders, if pre_shared_key extension present
tls.parrot_analysis.has_cookieWhether the cookie extension (44) was present in the initial ClientHello (illegal — only valid in HRR retry)
tls.parrot_analysis.grease_values[]GREASE codepoints observed across cipher_suites/extensions/groups
tls.parrot_analysis.ch_record_countNumber of TLS records the ClientHello was split across (Chrome ≥ 124 fragments, libraries don't)
tls.parrot_analysis.handshake_rtt_nsWall-clock duration of the handshake in nanoseconds
tls.parrot_analysis.ech_grease_aeads[]ECH GREASE AEAD IDs offered (Chrome only sends AES-128-GCM = 0x0001)
tls.parrot_analysis.ech_grease_payload_lenECH GREASE payload length in bytes (must be a multiple of 32 for Chrome)
tls.parrot_analysis.session_history_countNumber of recent ClientHellos seen from this source IP (used by cross-session rule)

TLS Parrot Rule Catalog

The detector evaluates 31 invariant rules. Each rule emits a signal with source=tls-parrot, a stable key, and a confidence in [0,1]. The verdict is derived from the maximum confidence:

Rule keyConfidenceWhat it detects
cookie_in_initial_ch0.95cookie extension (44) in initial CH — only legal on HRR retry
psk_binder_length_invalid0.90PSK binder length doesn't match negotiated hash size
psk_not_last0.95pre_shared_key extension is not the final extension (RFC 8446 violation)
keyshare_pq_advertised_not_sent0.90X25519MLKEM768 in supported_groups but not in key_share
chrome_profile_with_firefox_ext0.95Chrome GREASE+ALPS+CompressCert plus Firefox-only extensions
chrome_missing_padding_no_pq0.95Chrome profile but no padding extension and no PQ key share
grease_outside_chrome_set0.85GREASE codepoints used that don't match Chrome's published rotation
ext_order_mismatch_chrome0.85Extension order hash doesn't match any known Chrome golden preset
ext_order_mismatch_firefox0.85Extension order hash doesn't match any known Firefox golden preset
ja3_chrome_ja4_firefox0.90JA3 fingerprint says Chrome but JA4 says Firefox (or vice versa)
alps_codepoint_pair_invalid0.85Only one of ALPS 17513/17613 present (Chrome always sends both)
compress_cert_brotli_only_chrome0.80compress_certificate=brotli without other Chrome markers
delegated_cred_with_legacy_sig0.80delegated_credential extension paired with legacy SHA-1 sig algs
renegotiation_info_in_tls130.75renegotiation_info extension on a TLS 1.3-only client (illegal)
session_ticket_with_psk0.75session_ticket extension and PSK both present (mutually exclusive)
tls12_only_with_chrome_profile0.85Chrome markers but no TLS 1.3 in supported_versions
sni_with_dot_atend0.70SNI hostname ends in trailing dot (some libs forget to strip)
ext_count_outlier_chrome0.75Extension count outside Chrome's known range
ech_grease_chacha200.90ECH GREASE offers ChaCha20 AEAD (Chrome never does)
ech_grease_aes2560.85ECH GREASE offers AES-256-GCM (Chrome only sends AES-128-GCM)
ech_grease_payload_length_wrong0.80ECH GREASE payload length not a multiple of 32 bytes
ext_order_unstable_cross_session0.85Extension order hash differs across sessions from same IP (Chrome is stable)
ch_not_fragmented_chrome0.80Chrome profile but ClientHello fits in 1 record (Chrome ≥124 fragments)
ch_length_mod_512_nonzero_chrome0.75Chrome profile but CH length not aligned to 512-byte boundary
pq_advertised_fast_handshake0.65X25519MLKEM768 advertised but handshake completed in <2ms (no real PQ math)
hrr_response_inconsistent0.85Active HRR probe: client refused to retry with selected group (impostor doesn't implement HRR)
hrr_no_response0.70Active HRR probe: client never responded to HelloRetryRequest
unknown_ext_rejected0.75Active probe: client aborted on unknown ServerHello extension (real stacks ignore)
alpn_mismatch_accepted0.85Active probe: client accepted server ALPN it didn't offer
downgrade_canary_ignored0.90Active probe: client accepted forged TLS 1.2 ServerHello downgrade (no canary check)
backconnect_lib_mismatch0.80Backconnect JA3S indicates a different TLS library than the inbound CH claimed

GET /api/report/{id}?fields=...

Retrieve a filtered report with only the specified fields. The id and timestamp fields are always included. Unknown field names are silently ignored.

Example:
curl "https://mailcheck.biz/api/report/xyzabc-abcdefgh?fields=tls,email_auth"
Query parameter:
ParameterTypeDescription
fieldsstringComma-separated list of top-level field names to include. Nested field selection is not supported.
Available fields:
  • envelope
  • dns_queries
  • tcp_fingerprint
  • tls
  • email_auth
  • ptr
  • blacklists
  • dns_leak
  • headers
  • smtp_dialog
  • active_scan
  • client_verdict
  • domain_dns
  • ns_servers
  • whois
  • geoip
  • mail_security
  • port_scan
  • web_probe
  • web_fingerprint
  • network_anomalies
  • server_identity
  • received_analysis
  • route_trace
  • transport_fp

Trust Score & Server Identity

The server_identity field includes a category-based Trust Score (0-100) with detailed breakdown and actionable recommendations.

Example:
curl "https://mailcheck.biz/api/report/xyzabc-abcdefgh?fields=server_identity"
Response (server_identity object):
{
  "server_identity": {
    "primary_mta": "Postfix",
    "mta_confidence": 0.95,
    "trust_score": 87,
    "rating": "Good",
    "bonus": 4,
    "categories": [
      {"name": "authentication", "cap": 30, "penalty": 0},
      {"name": "blacklists", "cap": 25, "penalty": 0},
      {"name": "dns_config", "cap": 15, "penalty": 5},
      {"name": "tls", "cap": 10, "penalty": 0},
      {"name": "server_identity", "cap": 10, "penalty": 0},
      {"name": "headers", "cap": 5, "penalty": 0},
      {"name": "advanced", "cap": 5, "penalty": 0}
    ],
    "recommendations": [
      {
        "category": "dns_config",
        "priority": "high",
        "title": "Fix forward-confirmed rDNS",
        "fix": "Ensure the A record resolves to the sending IP",
        "impact": 5
      }
    ]
  }
}
Trust Score categories:
CategoryMax PenaltyDescription
authentication30SPF, DKIM (incl. per-signature security score), DMARC results and policy strength
blacklists25DNSBL listings (tiered by severity)
dns_config15PTR, FCrDNS, EHLO/PTR match, MX record
tls10Certificate validity, self-signed, cross-port consistency
server_identity10MTA/OS/TLS consistency, anomaly detection
headers5Received chain integrity, timestamp order, TLS hops
advanced5DNS leak, domain age, web presence
infrastructure30Open proxies, VPN services, suspicious ports, HTTPS cert, HTTP/2, TLS versions
Infrastructure penalties (detailed):
FindingPenalty
Open proxy detected-25
Suspicious ports (IRC, database, etc.)-15
Tor relay detected-10
VPN service detected-8
RDP exposed (port 3389)-5
Self-signed HTTPS certificate-5
Legacy TLS only (no TLS 1.2+)-3
SMTP/HTTPS cert mismatch-2
No HTTP/2 support-1
Rating scale:
ScoreRating
90-100Excellent
75-89Good
50-74Fair
25-49Poor
0-24Critical
Recommendation priority levels: high, medium, low. Each recommendation includes an impact field showing how many points would be recovered if the issue is fixed. Bonus points (up to +10) are awarded for advanced security standards: MTA-STS enforce (+3), DANE TLSA (+3), BIMI (+1), DMARC p=reject (+1).

TLS Fields (tls)

The tls field contains detailed TLS analysis of the sender's STARTTLS connection, including ClientHello fingerprinting, cipher suite analysis, and security assessment.

FieldTypeDescription
usedbooleanWhether TLS was used (STARTTLS)
versionstringNegotiated TLS version (e.g. "TLS 1.2")
cipher_suitestringNegotiated cipher suite name
server_namestringSNI hostname from ClientHello
ja3_hashstringJA3 fingerprint (MD5 hash)
ja3_stringstringRaw JA3 string before hashing
ja4_hashstringJA4 TLS fingerprint (SHA-256 based)
session_resumedbooleanWhether TLS session was resumed via ticket/PSK
negotiated_alpnstringALPN protocol negotiated (unusual for SMTP)
detected_librarystringDetected TLS library (OpenSSL, Go, BoringSSL, etc.)
inferred_mtastringMTA inferred from TLS library
inferred_mta_methodstringMethod used for MTA inference: tls_deep_fingerprint
inferred_mta_evidencestring[]Evidence list supporting the MTA inference (e.g. cipher composition, extension order patterns)

Security Assessment (tls.security)

FieldTypeDescription
gradestringOverall TLS grade: A+, A, B, C, D, F
forward_secrecybooleanWhether all offered ciphers use forward secrecy (ECDHE/DHE)
aead_onlybooleanWhether only AEAD ciphers are offered (GCM, CCM, ChaCha20)
min_versionstringLowest TLS version offered
max_versionstringHighest TLS version offered
has_tls13booleanWhether TLS 1.3 is offered
has_deprecatedbooleanWhether deprecated TLS 1.0/1.1 is offered
weak_ciphersstring[]List of weak cipher suites offered (NULL, RC4, 3DES)
strong_ciphersstring[]List of strong AEAD cipher suites offered
warningsstring[]Security warnings

ClientHello (tls.client_hello)

FieldTypeDescription
record_versionstringTLS record layer version
client_versionstringClientHello protocol version
session_id_lengthintLength of legacy session ID (0=TLS 1.3 native, 32=compat)
client_hello_lengthintTotal raw ClientHello size in bytes
grease_countintNumber of GREASE values (indicates BoringSSL/Chrome)
supported_versionsstring[]TLS versions offered (e.g. ["TLS 1.3", "TLS 1.2"])
cipher_suitesstring[]Offered cipher suites with IANA names
extensionsstring[]TLS extensions with names
supported_groupsstring[]Elliptic curve / DH groups with names
key_share_groupsstring[]Deprecated. Use key_share_entries instead. Still present for backward compatibility
signature_algorithmsstring[]Signature algorithms with names
compression_methodsstring[]Compression methods (should be ["null"] only)
psk_modesstring[]PSK key exchange modes (TLS 1.3)
alpn_protocolsstring[]ALPN protocol list (unusual for SMTP)
ec_point_formatsstring[]EC point format list
extension_flagsobjectBoolean flags for 13 notable TLS extensions (see table below)
compress_cert_algorithmsstring[]Certificate compression algorithms from ext 27 (brotli, zlib, zstd)
signature_algorithms_certstring[]Certificate-specific signature algorithms from ext 50
record_size_limitintRecord size limit value from ext 28 (0 if absent)
padding_lengthintPadding extension data length in bytes from ext 21
key_share_entriesobject[]Key share groups with key lengths ({group, key_length}). Replaces key_share_groups
delegated_cred_algorithmsstring[]Delegated credential signature algorithms from ext 34
has_cbc_suitesboolWhether CBC-mode cipher suites are offered
has_ccm_suitesboolWhether CCM-mode cipher suites are offered (wolfSSL/mbed TLS)
has_ffdhe_groupsboolWhether finite-field DH groups are offered (GnuTLS/Java)
has_post_quantumboolWhether post-quantum/hybrid key exchange groups are offered
tls13_cipher_orderstringTLS 1.3 cipher suite order (e.g. "1301→1302→1303")
cipher_suite_countintTotal number of cipher suites offered
extension_countintTotal number of extensions in ClientHello
key_share_countintNumber of key share entries offered
cipher_categoriesobjectCipher suite composition breakdown by key exchange type (see Cipher Composition below)
strength_orderedboolWhether cipher suites appear in @STRENGTH order (256-bit before 128-bit)
extension_order_firststringFirst non-GREASE extension name (e.g. "server_name", "extended_master_secret")
extension_order_hashstringSHA-256 hash of extension ID order (GREASE filtered, 12 hex chars)
group_order_patternstringNamed group order pattern (e.g. "x25519_first", "p256_first", "p384_before_p521")
ffdhe_countintNumber of finite-field DH groups (ffdhe2048, ffdhe3072, etc.)
version_patternstringTLS version triplet: record/handshake/max (e.g. "rec=0301,hs=0303,max=0304")
has_legacy_versionsboolWhether TLS 1.0 or 1.1 is in supported_versions extension

Cipher Composition (tls.client_hello.cipher_categories)

Breaks down offered cipher suites by key exchange and authentication type. Useful for distinguishing MTAs with similar TLS libraries (e.g. Postfix vs Exim on OpenSSL).

FieldTypeDescription
ecdhe_ecdsaintNumber of ECDHE-ECDSA cipher suites
ecdhe_rsaintNumber of ECDHE-RSA cipher suites
dhe_rsaintNumber of DHE-RSA cipher suites
rsaintNumber of static RSA cipher suites
otherintNumber of other cipher suites (PSK, anon, etc.)
has_camelliaboolWhether Camellia cipher suites are offered
has_ariaboolWhether ARIA cipher suites are offered
has_ccmboolWhether CCM cipher suites are offered
has_ccm8boolWhether CCM-8 (short tag) cipher suites are offered
has_low_gradeboolWhether low-grade cipher suites are offered (EXPORT, NULL)

Extension Flags Reference

Flag keyExt IDWhat it indicates
extended_master_secret23Protection against triple handshake attack
encrypt_then_mac22Encrypt-then-MAC for CBC suites (OpenSSL/GnuTLS)
session_ticket35TLS session resumption via tickets
renegotiation_info65281Secure renegotiation (TLS 1.2)
status_request5OCSP stapling support
signed_cert_timestamps18Certificate Transparency (SCT)
greaseGREASE values present (BoringSSL/NSS)
padding21ClientHello padding (BoringSSL)
post_handshake_auth49Post-handshake authentication (NSS/Firefox)
compress_certificate27Certificate compression (BoringSSL/NSS)
alps17513Application-Layer Protocol Settings (BoringSSL only)
ech65037Encrypted Client Hello (modern browsers)
delegated_credential34Delegated Credentials (RFC 9345)

Client Certificate (tls.client_cert)

Present only when the sending server provides a client certificate during TLS handshake (mTLS). Rare in SMTP but seen on corporate mail servers. Includes full x509 certificate details and chain information.

FieldTypeDescription
presentedboolWhether a client certificate was presented
acquisition_methodstringserver_requested_client_provided or server_requested_not_provided
subjectstringFull subject DN
issuerstringFull issuer DN
organizationstringSubject Organization (O) — company name
organizational_unitstringSubject Organizational Unit (OU)
countrystringSubject Country (C)
provincestringSubject State/Province (ST)
localitystringSubject Locality/City (L)
common_namestringSubject Common Name (CN)
sanstring[]Subject Alternative Names (DNS + IP)
email_addressesstring[]Email addresses from SAN extension
urisstring[]URI SANs
valid_fromstringCertificate NotBefore date
valid_tostringCertificate NotAfter date
remaining_validitystringHuman-readable remaining validity or "expired X ago"
is_expiredboolWhether the certificate has expired
is_self_signedboolWhether subject matches issuer
is_caboolWhether BasicConstraints CA flag is set
serial_numberstringCertificate serial number (hex)
versionintX.509 version (typically 3)
signature_algorithmstringSignature algorithm (e.g. ECDSA-SHA256)
fingerprintstringSHA-256 fingerprint of DER certificate
key_typestringPublic key algorithm (RSA, ECDSA, Ed25519)
key_bitsintPublic key size in bits
key_usagestring[]Key usage flags (DigitalSignature, KeyEncipherment, etc.)
ext_key_usagestring[]Extended key usage (ClientAuth, EmailProtection, etc.)
subject_key_idstringSubject Key Identifier (hex)
authority_key_idstringAuthority Key Identifier (hex)
ocsp_serversstring[]OCSP responder URLs
crl_distribution_pointsstring[]CRL distribution point URLs
issuing_certificate_urlstring[]Issuing CA certificate URLs (AIA)
chain_lengthintTotal number of certificates in the chain
chain_certsobject[]Intermediate/root certificates (same fields as above, excluding chain-specific fields)
ja4x_hashstringJA4X fingerprint of the client certificate (OID-based hash of issuer/subject/extensions using raw hex OID bytes per JA4+ spec)
ja4x_softwarestringCertificate generation software identified via JA4X lookup (e.g. "OpenSSL", "Go crypto/x509", "Let's Encrypt")

TLS Security Grading

GradeCriteria
A+TLS 1.3 only, all AEAD ciphers
ATLS 1.2+ with AEAD ciphers and forward secrecy
BTLS 1.2+ but CBC ciphers offered
C3DES cipher suites offered
DTLS 1.0/1.1 or RC4 offered
FNULL ciphers offered — no encryption

Active Scan & TCP Fingerprinting

The active_scan field contains results from actively probing the sender's mail server on port 25: SMTP banner, EHLO capabilities, JARM TLS fingerprint, TCP SYN-ACK fingerprint, JA4TScan OS detection, and TLS certificate details.

Example:
curl "https://mailcheck.biz/api/report/xyzabc-abcdefgh?fields=active_scan"
Response (active_scan object):
{
  "active_scan": {
    "banner": "220 mail.example.com ESMTP Postfix",
    "mta_name": "Postfix",
    "jarm_hash": "2ad2ad16d2ad2ad00042d42d00000069d641f34fe76acdc05c40262f8815e5",
    "ehlo_caps": ["PIPELINING", "SIZE 10240000", "STARTTLS", "AUTH PLAIN LOGIN"],
    "probe_os_guess": "Linux 4.x-6.x",
    "probe_ja4ts": "65535_2-1-3-1-1-4-1-1-8_1460_8",
    "probe_os_confidence": 0.6,
    "ja4tscan_hash": "65535_2-1-3-1-1-4-1-1-8_1460_8_1-2-4-8",
    "ja4tscan_os": "Linux 4.x-6.x",
    "ja4tscan_retransmits": "1-2-4-8",
    "ja4tscan_pattern": "Linux/FreeBSD (exponential backoff)",
    "server_uptime": "14d 6h",
    "cert_subject": "mail.example.com",
    "cert_issuer": "Let's Encrypt"
  }
}
Key fields:
FieldTypeDescription
bannerstringSMTP banner from port 25
mta_namestringDetected MTA software (Postfix, Exim, Exchange, etc.)
jarm_hashstringJARM TLS fingerprint of port 25
ehlo_capsstring[]EHLO capability lines
probe_os_guessstringOS guess from SYN-ACK TCP fingerprint
probe_ja4tsstringJA4TS hash of the server's SYN-ACK response (window_options_mss_ws)
probe_os_confidencefloatOS detection confidence (0.0–0.7, capped because SYN-ACK depends on client's SYN)
ja4tscan_hashstringFull JA4TScan hash: JA4TS + retransmit timing section
ja4tscan_osstringOS guess from JA4TScan (combines SYN-ACK + retransmit pattern)
ja4tscan_retransmitsstringRetransmit timing pattern, e.g. 1-2-4-8 (exponential) or 1-1-1-R2 (flat+RST)
ja4tscan_patternstringClassified OS family: Linux/FreeBSD (exponential backoff), Windows (RST after retransmits), macOS (flat 1s retransmits)
ja4x_hashstringJA4X TLS certificate fingerprint (OID-based hash of server certificate using raw hex OID bytes)
ja4x_softwarestringCertificate generation software identified via JA4X (e.g. "OpenSSL", "Go crypto/x509", "Let's Encrypt")
ja4s_hashstringJA4S ServerHello fingerprint (server-selected TLS parameters hash)
ja3s_hashstringJA3S hash (MD5) of SMTP ServerHello — compatible with Shodan/GreyNoise databases
server_hello_extensionsstring[]Extensions present in the server's ServerHello response
server_uptimestringEstimated server uptime from TCP timestamps
JA4TScan methodology:

JA4TScan sends a standardized SYN packet (MSS=1460, WS=7, SACK, Timestamps) and captures the server's SYN-ACK response plus retransmissions over 15 seconds. The retransmit timing pattern is OS-specific:

PatternOS FamilyExample
Exponential backoffLinux / FreeBSD1-2-4-8
Flat + RSTWindows1-1-1-R2
Flat 1smacOS1-1-1-1-1

Web & Infrastructure Fingerprint (web_fingerprint)

The web_fingerprint field contains results from analyzing the sender's web infrastructure on ports 80/443: TLS fingerprints, HTTP/2 fingerprint, web server detection, certificate analysis, reverse IP lookup, open proxy/VPN detection, and port scanning.

Example:
curl "https://mailcheck.biz/api/report/xyzabc-abcdefgh?fields=web_fingerprint"
Response (web_fingerprint object):
{
  "web_fingerprint": {
    "ja3s": "ae4eef27d57a55a3c5765e9f8cfd5bf0",
    "ja4s": "t13d3112_a5b2c3...",
    "jarm_https": "27d40d40d00042d...",
    "tls_versions": [
      {"version": "TLS 1.2", "supported": true, "cipher_suite": "ECDHE-RSA-AES128-GCM-SHA256"},
      {"version": "TLS 1.3", "supported": true, "cipher_suite": "TLS_AES_128_GCM_SHA256"}
    ],
    "http2_supported": true,
    "http2_fingerprint": "3:128;4:65535|0|0",
    "http2_server": "nginx",
    "server_detect": {
      "server": "nginx",
      "version": "1.24.0",
      "confidence": 0.92,
      "technology": "PHP",
      "cdn": "Cloudflare"
    },
    "reverse_ip_domains": ["example.com", "shop.example.com"],
    "cert_comparison": {"verdict": "smtp_neglected"},
    "proxy_checks": [{"port": 1080, "protocol": "socks5", "status": "open"}],
    "port_profile": "proxy_host",
    "scan_level": 2
  }
}
Key fields:
FieldTypeDescription
ja3sstringJA3S hash (MD5) of HTTPS ServerHello
ja4sstringJA4S hash (SHA-256) of HTTPS ServerHello
jarm_httpsstringJARM fingerprint of port 443
tls_versionsobject[]TLS version support (1.0-1.3) with cipher per version
http2_supportedboolHTTP/2 support via ALPN h2
http2_fingerprintstringAkamai-format HTTP/2 fingerprint
server_detectobjectWeb server detection (12 methods, see below)
reverse_ip_domainsstring[]Domains from SAN of default cert (no SNI)
cert_comparisonobjectSMTP vs HTTPS cert comparison verdict
proxy_checksobject[]Open proxy detection (SOCKS4/5, HTTP CONNECT)
vpn_checksobject[]VPN detection (OpenVPN, PPTP, WireGuard, etc.)
port_profilestringProfile: clean, proxy_host, vpn_server, compromised
open_portsobject[]Open ports: port, transport (tcp/udp), category, banner, response_ms, level (1 or 2)
scan_levelint1 (25 key ports) or 2 (expanded, triggered by proxy/VPN findings)
https_certobjectHTTPS certificate (with SNI): subject, issuer, san_domains, san_ips, valid_from, valid_to, key_type, chain_length, self_signed, expired, fingerprint, ja4x, is_wildcard
domain_certobjectCertificate from domain A-record IP (if different from sender IP). Same structure as https_cert
domain_cert_ipstringIP that the domain resolved to (if different from sender)
default_certobjectCertificate without SNI (reveals shared hosting). Same structure as https_cert
web_presenceobjectWeb presence analysis (same structure as top-level web_probe)
ja4x_httpsstringJA4X certificate OID fingerprint (HTTPS cert)
ja4x_softwarestringCertificate software identified via JA4X
http2_serverstringWeb server matched from HTTP/2 SETTINGS (nginx, Apache, Caddy, etc.)
http2_settingsobjectHTTP/2 SETTINGS values: HEADER_TABLE_SIZE, MAX_CONCURRENT_STREAMS, INITIAL_WINDOW_SIZE, etc.
errorstringWeb fingerprint error (if any)
Server detection methods:
MethodConfidenceWhat it checks
HTTP/2 SETTINGS0.90Server defaults for MAX_CONCURRENT_STREAMS, INITIAL_WINDOW_SIZE
Error page0.85Default 404/403 page HTML patterns
Unique headers0.90x-envoy-*, X-LiteSpeed-*, X-Powered-By
ETag format0.80ETag structure differs per server
Method handling0.80Response codes for OPTIONS, DELETE, unknown methods
Header order0.70Order of Date/Server/Content-Type
Keep-Alive0.70timeout= max= format (Apache-unique)
URL handling0.75Case sensitivity, backslash (IIS)
Cookies0.80PHPSESSID, JSESSIONID, ASP.NET_SessionId
Endpoints0.85/server-status, /aspnet_client/
WAF/CDN0.90Cloudflare, Akamai, Sucuri headers
HTTP/30.70Alt-Svc h3 advertisement
Proxy status values:
StatusMeaning
openConfirmed open proxy
auth_requiredProxy requires authentication
blockedCONNECT method blocked
confirmedVPN service confirmed
possiblePort open but not confirmed
Cert comparison verdicts:
VerdictMeaning
same_infraSame cert on SMTP and HTTPS
shared_infraDifferent certs, same CA
smtp_neglectedSMTP self-signed, HTTPS from CA
self_signed_bothBoth self-signed
no_webNo HTTPS response
split_infraDifferent infrastructure

Transport FP (transport_fp)

Transport-layer fingerprinting combining two analysis techniques to detect proxies and identify TLS libraries from application data record patterns.

Example:
curl "https://mailcheck.biz/api/report/xyzabc-abcdefgh?fields=transport_fp"
Response (transport_fp object):
{
  "transport_fp": {
    "cross_layer_rtt": {
      "tcp_rtt_us": 45230,
      "smtp_rtt_us": 89450,
      "starttls_rtt_us": 92340,
      "tls_rtt_us": 95120,
      "smtp_ratio": 1.97,
      "starttls_ratio": 2.04,
      "tls_ratio": 2.10,
      "max_rtt_diff_us": 49890,
      "proxy_detected": true,
      "proxy_type": "socks5",
      "confidence": 0.87,
      "evidence": ["smtp_ratio_elevated", "consistent_gradient", "latency_pattern_socks5"]
    },
    "tls_record_analysis": {
      "record_sizes": [100, 100, 100, 512, 512, 512],
      "pattern": "uniform_then_large",
      "tls_library": "OpenSSL",
      "confidence": 0.92,
      "avg_record_size": 341,
      "first_record": 100,
      "growth_detected": true,
      "evidence": ["size_pattern_openssl", "record_distribution_match"]
    }
  }
}
Cross-Layer RTT fields:
FieldTypeDescription
tcp_rtt_usintTCP handshake round-trip time in microseconds
smtp_rtt_usintSMTP banner response RTT in microseconds
starttls_rtt_usintSTARTTLS response RTT in microseconds
tls_rtt_usintTLS handshake completion RTT in microseconds
smtp_ratiofloatSMTP RTT / TCP RTT ratio (detection threshold: >1.5 suggests proxy)
starttls_ratiofloatSTARTTLS RTT / TCP RTT ratio
tls_ratiofloatTLS RTT / TCP RTT ratio
max_rtt_diff_usintMaximum difference between any two RTT measurements (indicates proxy variance)
proxy_detectedboolWhether proxy detection threshold was exceeded
proxy_typestringInferred proxy type if detected: socks5, socks4, http_tunnel, unknown
confidencefloatProxy detection confidence (0.0–1.0)
evidencestring[]Array of evidence signals supporting the detection (e.g. "smtp_ratio_elevated", "consistent_gradient", "latency_pattern_socks5")
TLS Record Analysis fields:
FieldTypeDescription
record_sizesint[]Observed TLS Application Data record sizes in bytes (first 6 records captured)
patternstringClassified size pattern: uniform_then_large (OpenSSL), small_constant (Go), large_constant (BoringSSL), varied (rustls/other)
tls_librarystringIdentified TLS library from record pattern (OpenSSL, Go, BoringSSL, rustls, etc.)
confidencefloatPattern match confidence (0.0–1.0)
avg_record_sizefloatAverage record size across captured records
first_recordintFirst record size (distinctive for some libraries)
growth_detectedboolWhether records grow over time (OpenSSL pattern)
evidencestring[]Array of pattern-matching evidence (e.g. "size_pattern_openssl", "record_distribution_match")

Envelope (envelope)

SMTP session metadata captured when the email arrived.

FieldTypeDescription
client_ipstringSender's IP address
client_portintSender's TCP port
helostringHELO/EHLO hostname from SMTP session
mail_fromstringMAIL FROM address
rcpt_tostring[]RCPT TO addresses

TCP Fingerprint (tcp_fingerprint)

Passive TCP/IP fingerprint from the sender's SYN packet.

FieldTypeDescription
ttlintObserved Time-To-Live
initial_ttlintEstimated initial TTL (64/128/255)
window_sizeintTCP window size
mssintMaximum Segment Size
mtuintCalculated MTU (MSS + 40)
window_scaleintWindow scale factor
calculated_windowintEffective window (window_size << window_scale)
options_layoutstringTCP options order (e.g. mss,sack,ts,nop,ws)
df_bitboolDon't Fragment flag set
sack_permittedboolSACK permitted option present
timestampsboolTCP timestamps present
ecnboolECN flags set
dscpintIP DSCP value
ip_idintIP Identification field (0=Linux, incremental=Windows)
p0f_signaturestringp0f-compatible fingerprint string
os_guessstringOS guess from TCP stack behavior
ja4t_hashstringJA4T TCP fingerprint hash
Network & Tunnel Detection
hop_countintNumber of network hops (initial_ttl - ttl)
network_typestringDetected network type: Direct Ethernet, WireGuard, OpenVPN, PPPoE, GRE, Mobile LTE/5G, etc.
network_detailstringAdditional detail about network type
tunnel_overheadintTunnel overhead in bytes (1500 - MTU), 0 = no tunnel
window_mss_ratiostringWindow/MSS ratio: mss×20 (Linux default), 65535 (max), or custom
Timestamp Analysis
timestamp_modestringTCP timestamp mode: Randomized per-connection (Linux 4.10+), Not supported (Windows), Disabled, Present (mode unknown)
tcp_timer_hzintDetected TCP timer frequency in Hz (250/1000 typical for Linux)
tcp_timer_reliableboolWhether Hz detection is reliable (false for Linux with randomized timestamps)
server_uptimestringEstimated server uptime or "N/A (randomized)" for Linux
uptime_sourcestringHow uptime was determined
Consistency Checks
ttl_os_consistentboolWhether TTL matches expected OS (Linux=64, Windows=128)
ttl_os_detailstringTTL/OS consistency detail with explanation
os_consistencyobjectCross-module OS comparison: consistent (bool), sources (array of {source, os}), detail (string)
Stack Hardening
ip_id_behaviorstringIP ID classification: Zero with DF (RFC 6864), Non-zero (per-destination counter), etc.
stack_hardeningobjectHardening assessment: rating (Default/Moderate/Hardened), score (0-3), indicators (array of {name, present, detail})
Active TCP Probes
isn_analysisobjectISN analysis: gcd, isr (counter rate), sp (predictability 0-300+), responses (out of 6), assessment (Secure/Moderate/Predictable/Indeterminate)
ip_id_sequencestringIP ID sequence classification: Z (zero), I (incremental), BI (broken), RD (random), RI (random incremental)
ecn_probeobjectECN probe result: cc (Y/N/S/O = ECN support), quirks (R=reserved bits, U=urgent pointer), window, df, ttl
tcp_probesarrayT2-T4 behavior probes: name, responded, df, window, flags, seq_test (Z/S/O), ack_test (Z/S/S+/O), quirks

SMTP Dialog (smtp_dialog)

Recorded SMTP session between sender and our server.

FieldTypeDescription
ehlo_hostnamestringHostname from EHLO command
pipelining_usedboolWhether SMTP pipelining was used
sends_quitboolWhether client sent QUIT before disconnecting
re_ehlo_after_tlsboolWhether client re-sent EHLO after STARTTLS
ehlo_countintTotal EHLO commands sent
mail_from_paramsstringMAIL FROM parameters (SIZE, BODY, etc.)
entriesobject[]Dialog entries: is_from_client, command, full_line, timestamp, delta_ms
raw_transcriptobject[]Raw transcript lines: dir (C/S), text, ts, delta_ms

PTR / rDNS (ptr)

Reverse DNS lookup and forward-confirmed verification.

FieldTypeDescription
client_ipstringIP address looked up
ptr_recordstringPrimary PTR hostname
all_ptr_recordsstring[]All PTR records
forward_confirmedboolPTR hostname resolves back to client_ip (FCrDNS)
matches_heloboolPTR hostname matches EHLO hostname

DNS Queries (dns_queries)

DNS queries that arrived to our authoritative server for the trace subdomain.

FieldTypeDescription
timestampstringQuery timestamp (RFC3339)
source_ipstringIP of the DNS resolver
query_namestringQueried domain name
query_typestringDNS query type (A, MX, TXT, etc.)
response_codestringResponse code (NOERROR, NXDOMAIN, etc.)

Email Headers (headers)

Key email headers extracted from the received message.

FieldTypeDescription
subjectstringEmail subject line
fromstringFrom header
tostringTo header
datestringDate header
message_idstringMessage-ID header
x_mailerstringX-Mailer or User-Agent header (if present)
content_typestringContent-Type header

Client Verdict (client_verdict)

Aggregated fingerprinting verdict from all signal sources.

FieldTypeDescription
osstringDetected operating system
mtastringDetected mail transfer agent
tls_librarystringDetected TLS library
mail_clientstringDetected mail client (if identifiable)
server_uptimestringEstimated server uptime
confidencefloatOverall confidence (0.0–1.0)
ja4t_hashstringJA4T hash used for verdict
signalsobject[]All signals: source, key, value, confidence, evidence

Domain DNS Audit (domain_dns)

DNS records and configuration audit for the sender's domain.

FieldTypeDescription
domainstringSender domain
mx_statestringMail routing: explicit, implicit, none, dns_error
mx_recordsobject[]MX records: host, priority, ips
a_recordsstring[]A records for the domain
aaaa_recordsstring[]AAAA records
ns_recordsstring[]NS records
soaobjectSOA record: primary_ns, admin_email, serial, refresh, retry, expire, min_ttl
txt_recordsstring[]TXT records (SPF, DKIM, DMARC, etc.)
cname_recordstringCNAME record (if any)
all_ptr_recordsstring[]All PTR records for the domain's IPs
ptr_matches_domainboolPTR matches the sender domain
issuesobject[]DNS issues found: type, category (ns/mx/spf/ptr/soa), description

NS Servers (ns_servers)

Nameserver software detection for the sender's domain.

FieldTypeDescription
hostnamestringNS hostname
ipsstring[]Resolved IP addresses
softwarestringDetected software (BIND, PowerDNS, etc.)
versionstringSoftware version (if exposed)
detection_methodstringMethod used: chaos_query, behavioral, etc.

WHOIS (whois)

Domain registration and age information.

FieldTypeDescription
created_datestringDomain creation date
updated_datestringLast updated date
expiry_datestringExpiry date
domain_agestringHuman-readable age (e.g. "2 years")
registrarstringDomain registrar
domain_statusstring[]EPP status codes
warningsstring[]Warnings (e.g. young domain)
errorstringWHOIS lookup error (if any)

GeoIP / ASN (geoip)

Geographic and network information for the sender's IP. Displayed in the report UI but the geoip JSON field may be absent in older reports.

FieldTypeDescription
countrystringCountry name
country_codestringISO country code
citystringCity
asnintAutonomous System Number
as_orgstringAS organization name
is_hostingboolWhether the IP belongs to a hosting provider

Mail Security Policies (mail_security)

Advanced mail security policy checks for the sender's domain.

FieldTypeDescription
mta_sts — MTA-STS policy
mta_sts.has_policyboolWhether an MTA-STS policy exists
mta_sts.modestringPolicy mode: enforce, testing, none
mta_sts.mx_hostsstring[]Authorized MX hosts
mta_sts.max_ageintPolicy max age in seconds
dane — DANE TLSA records
dane.has_tlsaboolWhether TLSA records exist
dane.dnssec_validboolWhether DNSSEC validates
dane.recordsobject[]TLSA records: mx_host, usage, selector, matching_type, cert_hash
bimi — Brand Indicators
bimi.has_recordboolWhether a BIMI record exists
bimi.logo_urlstringLogo URL (SVG)
bimi.authority_urlstringVMC authority URL
tls_rpt — TLS Reporting
tls_rpt.has_recordboolWhether a TLS-RPT record exists
tls_rpt.report_uristringReport URI (mailto: or https:)

Port Scan (port_scan)

SMTP port scan results with STARTTLS, cert, and JARM per port.

FieldTypeDescription
portsobject[]Array of port scan results (see below)

Each port object:

FieldTypeDescription
portintPort number (25, 465, 587, 993, 4190, etc.)
servicestringService name (SMTP, SMTPS, IMAP, etc.)
openboolWhether the port is open
bannerstringService banner
starttls_supportedboolWhether STARTTLS is supported
tls_versionstringTLS version negotiated
jarm_hashstringJARM fingerprint for this port
cert_subjectstringTLS certificate subject
cert_issuerstringCertificate issuer
cert_fingerprintstringCertificate SHA-256 fingerprint
ehlo_capsstring[]EHLO capabilities (SMTP ports)
auth_methodsstring[]Advertised AUTH methods
raw_transcriptstringRaw SMTP transcript (C:/S: format)

DNS Leak Detection (dns_leak)

Detects if the sender's DNS resolver differs from their SMTP IP (ASN mismatch).

FieldTypeDescription
detectedboolWhether a DNS leak was detected
severitystringSeverity: info, warning, critical
smtp_client_ipstringSMTP sender IP
descriptionstringHuman-readable description
resolversobject[]DNS resolvers seen: ip, is_public_dns, public_dns_name, classification

Mail Route & Timeline (received_analysis)

Parsed Received header chain with timing analysis and anomaly detection.

FieldTypeDescription
total_hopsintNumber of mail hops
total_timestringTotal transit time (human-readable)
total_time_msintTotal transit time in milliseconds
hopsobject[]Each hop (see below)
anomaliesobject[]Anomalies: type, severity, hop_index, detail
ip_matchobjectreceived_ip, client_ip, match (bool)

Each hop:

FieldTypeDescription
indexintHop number (0-based)
from_hoststringSending host
from_ipstringSending IP
by_hoststringReceiving host
protocolstringProtocol (SMTP, ESMTP, ESMTPS, etc.)
tls_usedboolWhether TLS was used for this hop
timestampstringTimestamp from Received header
delta_msintTime since previous hop (ms)
delta_classstringfast (≤5s), medium (5–30s), slow (>30s)

Anomaly types: tls_downgrade, clock_skew, private_ip, hostname_mismatch, large_delay, ip_mismatch.

Network Route Trace (route_trace)

The route_trace field contains traceroute results from our server to the sender's IP, enriched with GeoIP, ASN, node classification, and cross-referenced with Received headers and TCP TTL analysis.

Example:
curl "https://mailcheck.biz/api/report/xyzabc-abcdefgh?fields=route_trace"
Response (route_trace object):
{
  "route_trace": {
    "hops": [
      {
        "number": 1,
        "nodes": [
          {
            "ip": "10.0.0.1",
            "hostname": "gw.isp.net",
            "avg_rtt_ms": 1.2,
            "min_rtt_ms": 0.8,
            "max_rtt_ms": 1.5,
            "country": "FR",
            "city": "Paris",
            "asn": 16276,
            "as_name": "OVH",
            "lat": 48.8566,
            "lon": 2.3522,
            "node_type": "isp_router",
            "provider": "OVH"
          }
        ],
        "loss_pct": 0,
        "timeout": false
      }
    ],
    "target_ip": "1.2.3.4",
    "target_reached": true,
    "total_hops": 12,
    "total_time_ms": 28.5,
    "duration": "6.2s",
    "correlation": {
      "estimated_hops": 12,
      "traceroute_hops": 12,
      "hops_delta": 0,
      "ttl_anomaly": "none",
      "matched_hops": [
        {
          "received_hop_index": 0,
          "traceroute_hop_num": 12,
          "ip": "1.2.3.4",
          "hostname": "mail.example.com"
        }
      ],
      "findings": [
        {
          "type": "ttl_consistent",
          "severity": "info",
          "detail": "TTL estimation (12 hops) matches traceroute (12 hops)"
        }
      ],
      "asn_overlap": "1 shared (Google)",
      "transit_countries": "FR → NL → DE → US"
    }
  }
}
Top-level fields:
FieldTypeDescription
hopsarrayTraceroute hops from our server to sender IP
target_ipstringSender's IP address (traceroute destination)
target_reachedboolWhether traceroute reached the target
total_hopsintNumber of hops to reach target
total_time_msfloatRTT to final responding hop (ms)
durationstringWall-clock time of traceroute run
correlationobjectCross-reference with Received headers and TCP TTL
Hop fields (hops[]):
FieldTypeDescription
numberintHop number (1-based)
nodesarrayResponding nodes (multiple = ECMP load balancing)
loss_pctfloatPacket loss percentage (0-100)
timeoutboolAll probes timed out at this hop
Node fields (hops[].nodes[]):
FieldTypeDescription
ipstringIP address of responding node
hostnamestringReverse DNS hostname
avg_rtt_msfloatAverage round-trip time (ms)
min_rtt_msfloatMinimum RTT (ms)
max_rtt_msfloatMaximum RTT (ms)
countrystringCountry code (GeoIP)
citystringCity (GeoIP)
asnintAutonomous System Number
as_namestringAS organization name
node_typestringClassification: isp_router, ixp, cdn, cloud, enterprise, endpoint, unknown
providerstringDetected provider name (e.g. Cloudflare, AWS, Cogent)
Correlation fields (correlation):
FieldTypeDescription
estimated_hopsintEstimated hops from TCP SYN TTL (initial_ttl − observed_ttl)
traceroute_hopsintActual hops from traceroute
hops_deltaintAbsolute difference between estimated and actual
ttl_anomalystringTTL analysis result: none, nat_likely, vpn_likely, proxy_likely, unknown, not_available
matched_hopsarrayIPs found in both SMTP Received chain and traceroute
findingsarrayCorrelation findings: type, severity, detail
asn_overlapstringShared ASNs between SMTP and network routes
transit_countriesstringCountries traversed in order (e.g. "FR → NL → DE → US")
Finding types:

direct_route, ttl_consistent, ttl_mismatch_minor, ttl_mismatch_major, vpn_detected, proxy_detected, ip_match_found, ip_match_none, asymmetric_route, relay_chain, internal_relay, high_loss_path, country_transit.

Node type classifications:
TypeDescription
isp_routerISP or backbone router
ixpInternet Exchange Point
cdnCDN edge node
cloudCloud provider infrastructure
enterpriseCorporate gateway
endpointDestination server
unknownUnclassified node

Web Presence (web_probe)

HTTP/HTTPS probing of the sender's domain with deep content analysis.

Basic fields:
FieldTypeDescription
has_websiteboolWhether the domain has a working website
urlstringFinal URL after redirects
status_codeintHTTP status code
server_headerstringServer response header
x_powered_bystringX-Powered-By header
cdnstringDetected CDN (Cloudflare, Akamai, etc.)
tls_versionstringTLS version of HTTPS connection
cert_issuerstringHTTPS certificate issuer
cert_expirystringCertificate expiry date
has_hstsboolHSTS header present
cmsstringDetected CMS (WordPress, etc.)
website_verdictstringOverall website assessment
errorstringProbe error (if any)
robots.txt analysis:
FieldTypeDescription
has_robots_txtboolWhether robots.txt exists
robots_validboolWhether robots.txt parses correctly
robots_rule_countintNumber of Disallow rules
robots_sitemap_urlsstring[]Sitemap URLs referenced
robots_crawl_delayintCrawl-Delay value (seconds)
robots_hosting_panelstringHosting panel detected (cPanel, Plesk, etc.)
security.txt analysis:
FieldTypeDescription
has_security_txtboolWhether security.txt exists
security_txt_validboolWhether it complies with RFC 9116
security_txt_contactstringContact URI
security_txt_expiresstringExpiration date
security_txt_expiredboolWhether it has expired
security_txt_signedboolPGP signed
security_txt_verdictstringAssessment verdict
security_txt_fieldsobjectAll parsed fields (Encryption, Policy, Acknowledgments, etc.)
sitemap.xml analysis:
FieldTypeDescription
has_sitemapboolWhether sitemap.xml exists
sitemap_validboolWhether sitemap parses correctly
sitemap_url_countintNumber of URLs in sitemap
sitemap_newest_modstringNewest lastmod date
sitemap_oldest_modstringOldest lastmod date
sitemap_is_indexboolWhether it's a sitemap index
Favicon analysis:
FieldTypeDescription
favicon_validboolWhether favicon was found
favicon_hashstringSHA-256 hash of favicon
favicon_formatstringImage format (ico, png, svg)
favicon_sizeintFile size in bytes
favicon_defaultboolWhether it matches a known default favicon
HTML page analysis:
FieldTypeDescription
page_titlestringHTML <title> content
page_generatorstringGenerator meta tag (WordPress, Joomla, etc.)
page_languagestringPage language (html lang attribute)
page_link_countintNumber of links on page
page_css_countintNumber of CSS files
page_js_countintNumber of JS files
page_has_formsboolWhether page contains forms
page_sizeintPage size in bytes
page_verdictstringPage quality assessment

Network Anomalies (network_anomalies)

TCP/IP anomalies detected from passive fingerprinting (VPN/proxy/tunnel indicators).

FieldTypeDescription
typestringAnomaly type (ttl_mismatch, mss_anomaly, etc.)
detailstringHuman-readable description
confidencefloatDetection confidence (0.0–1.0)
evidencestringSupporting evidence

POST /api/compare?parentID={traceID}

Create a comparison child trace for OPSEC server comparison. Returns a new email address to send from a second server. The parent report must exist (on disk or in memory). Rate limited separately from /api/trace.

Query Parameter:
ParameterTypeDescription
parentIDstringTrace ID of the first (parent) report. Required.
Example:
curl -X POST "https://mailcheck.biz/api/compare?parentID=xyzabc-abcdefgh"
Response:
{
  "email": "newlocal@newsub.mailcheck.biz",
  "traceID": "newsub-newlocal"
}
Errors:
CodeBodyMeaning
400{"error":"parentID required"}Missing parentID query parameter
400{"error":"parent report not found"}Parent report does not exist
400{"error":"comparison already in progress"}A child trace already exists for this parent
429{"error":"rate limit exceeded"}Rate limit (1 req / 30s per IP)

GET /api/compare-status/{parentID}

Poll the status of a comparison trace. Returns the child trace ID and its processing state.

Example:
curl https://mailcheck.biz/api/compare-status/xyzabc-abcdefgh
Response:
{
  "status": "ready",
  "childTraceID": "newsub-newlocal"
}
StatusMeaning
pendingWaiting for email from second server
analyzingEmail received, analysis in progress
readyChild report ready — fetch via GET /api/report/{childTraceID}
notfoundNo comparison trace for this parent

GET /api/eml/{id}

Returns the raw .eml email file as text/plain. Contains full email headers and body as received by the server.

Example:
curl https://mailcheck.biz/api/eml/xyzabc-abcdefgh
Response:

Raw email content (headers + body) as text/plain; charset=utf-8. Returns 404 if email file not found.

GET /health

Server health check.

Example:
curl https://mailcheck.biz/health
Response:
{
  "status": "ok",
  "uptime": "2d 5h 30m",
  "version": "go1.23.6"
}

Typical Workflow

  1. POST /api/trace — get a unique email address and trace ID
  2. Send an email to the returned address
  3. Poll GET /api/status/{id} until status is ready
  4. Fetch report with GET /api/report/{id}

Server Comparison (OPSEC Audit)

  1. Complete the workflow above to get a report for Server A
  2. POST /api/compare?parentID={traceID} — get a new email address
  3. Send an email from Server B to the new address
  4. Poll GET /api/compare-status/{parentID} until status is ready
  5. Fetch Server B report with GET /api/report/{childTraceID}
  6. Compare the two JSON reports to detect correlations (shared IP, JA3/JA4, JARM, TLS cert, SMTP banner, etc.)

Error Responses

CodeMeaning
404Report or trace not found
405Method not allowed (e.g. GET on /api/trace)
429Rate limit exceeded. Response includes Retry-After header and JSON body: {"error": "rate limit exceeded"}