---
title: "POST /mail/scan"
method: POST
path: "/mail/scan"
tags: ["mail"]
---

# POST /mail/scan

`POST /mail/scan`

## Request

- Base URL: `https://api.ismalicious.com`
- URL: `https://api.ismalicious.com/mail/scan`
- Auth: API key in header `X-API-KEY`

## Request body

- MailScanRequest
  - `context` MailContext
    - `authservId` string, nullable: The `authserv-id` your receiving system writes in its `Authentication-Results` header. Only a header carrying it is read as SPF/DKIM/DMARC evidence; anyone else can write one into a message.
    - `connectingIp` string, nullable: The address that connected to your infrastructure, when you already have it. Overrides the `Received` chain.
    - `trustAuthenticationResults` boolean: Say that every `Authentication-Results` header in the message was added by your own infrastructure (Exchange Online writes it without an `authserv-id`). Needed, with or instead of `authservId`, for a message to be `clean`.
    - `trustedHops` integer, nullable: `Received` headers, counted from the top, that your own hosts wrote. The connecting address is the one the last of them recorded. Default 1.
  - `eml` string, nullable: The whole message as UTF-8 text. Use `emlBase64` for 8-bit or binary parts.
  - `emlBase64` string, nullable: The whole message, RFC 5322 (`.eml`), base64. Up to 10 MiB decoded. Send exactly one of `emlBase64`, `eml` and `message`.
  - `message` MailStructuredMessage: A message already parsed by the caller.
    - `attachments` MailStructuredAttachment[]: Attachments as metadata and digests. Contents are never needed.
      - `contentType` string, nullable
      - `filename` string, nullable
      - `inline` boolean: A part shown inside the body (`isInline` in Graph). One with a picture's type and name is listed, not looked up; any other inline part is read like an attachment.
      - `md5` string, nullable
      - `sha1` string, nullable
      - `sha256` string, nullable: Lowercase or uppercase hex. Any of the three is enough.
      - `size` integer, nullable
    - `from` string, nullable: `From`, when `headers` does not carry it: `Name <address>` or an address.
    - `headers` MailStructuredHeader[]: Every header, in message order, as received (`internetMessageHeaders` in Microsoft Graph). Needed for `Received` and `Authentication-Results`.
      - `name` string, required
      - `value` string, required
    - `html` string, nullable: The HTML body.
    - `replyTo` string, nullable
    - `returnPath` string, nullable
    - `subject` string, nullable
    - `text` string, nullable: The plain-text body.

## Response `200`

Verdict, action, reasons and coverage

- MailScanResponse
  - `attachments` MailAttachment[], required
    - `contentType` string, nullable
    - `detectedType` string, nullable: What the bytes are, for a message sent raw: `pe`, `elf`, `macho`, `lnk`, `zip`, `ooxml`, `jar`, `ole`, `pdf`, `rtf`, `html`, `text`, `image`, `gzip`, `rar`, `7z`, `cab`, `iso` or `unknown`. Absent for a message that came as metadata and digests.
    - `digests` MailDigests, required
      - `md5` string, nullable
      - `sha1` string, nullable
      - `sha256` string, nullable
    - `family` string, nullable
    - `filename` string, nullable
    - `flags` string[], required: From the name and the declared type: `risky_extension`, `double_extension`, `bidi_override`, `type_mismatch`, `archive`. From the bytes, for a message sent raw: `disguised_program`, `macro_project`, `encrypted_archive`, `archive_risky`, `remote_template`, `embedded_object`, `pdf_launch`, `pdf_script`, `html_smuggling`, `password_form`, `svg_script`, `command_line`. `attached_message` marks a `message/rfc822` attachment, read as a message of its own.
    - `inline` boolean, required: Shown inside the body: listed, not looked up.
    - `knownGood` boolean, required: NSRL knows the file as known software.
    - `origin` string, nullable: `attached_message` when the file came out of a `message/rfc822` attachment; absent for the message's own attachments.
    - `originName` string, nullable: The attached message the file came out of.
    - `size` integer, nullable
    - `verdict` string, required: What the hash tier says: `malicious` | `suspicious` | `clean` | `unknown`. `unknown` is not a safety claim.
  - `authentication` MailAuthentication, required
    - `dkim` string, nullable
    - `dmarc` string, nullable
    - `headerFrom` string, nullable
    - `spf` string, nullable
    - `status` string, required: `trusted` when the result below comes from a header you vouched for, `unverified` when none did. This scan does not verify SPF, DKIM or DMARC itself yet.
  - `connectingIp` MailConnectingIp
    - `address` string, required
    - `listed` string[], required
    - `sources` integer, required
    - `verdict` string, required: `malicious` | `suspicious` | `clean` | `unknown`.
  - `contacts` MailContact[], required: Addresses and numbers written in the body.
    - `kind` string, required: `email` | `phone`.
    - `reasons` string[], required
    - `value` string, required
    - `verdict` string, required: `malicious` | `suspicious` | `unknown`.
  - `coverage` MailCoverage, required
    - `ran` string[], required
    - `skipped` MailSkipped[], required
      - `check` string, required
      - `reason` string, required
    - `truncated` boolean, required: A body, a header list, a link list or the attachment list hit a limit.
  - `headline` string, required: One sentence a ticket or a chat message can carry.
  - `injection` MailInjection, required
    - `families` string[], required
    - `hiddenScore` number, double, required: The same score over text a reader never sees.
    - `score` number, double, required: Prompt-injection heuristics over the whole body, as `/gate/scan` runs them. 0.0..=1.0.
  - `latencyMs` integer, required
  - `links` MailLink[], required
    - `anchorText` string, nullable
    - `flags` string[], required: `anchor_mismatch`, `ip_host`, `userinfo`, `punycode`, `mixed_script`, `shortener`, `redirect_param`.
    - `host` string, required
    - `origin` string, nullable: Where the link was found when it is not the message's own text or HTML: `attachment` (read out of a file's bytes) or `attached_message`.
    - `originName` string, nullable: The attachment or attached message the link was found in.
    - `shownDomain` string, nullable: The domain the visible text names, when it is not the target's.
    - `sources` integer, required
    - `url` string, required: As written in the message. Defang it before relaying.
    - `verdict` string, required: `malicious` | `suspicious` | `clean` | `unknown`.
  - `reasons` MailReason[], required: The strongest findings first.
    - `code` string, required: Stable machine code: `link.listed`, `attachment.double_extension`…
    - `evidence` string, nullable: What it is about; hosts are defanged (`evil[.]test`).
    - `severity` string, required: `high` | `medium` | `low` | `info`.
    - `summary` string, required
  - `recommendedAction` string, required: `quarantine` | `review` | `warn` | `deliver`. `deliver` means no objection from this scan; it never releases a message another engine held.
  - `riskScore` integer, required: 0-100. 90 and above only for `malicious`.
  - `sender` MailSender, required
    - `address` string, nullable
    - `displayName` string, nullable
    - `disposable` boolean, required
    - `domain` string, nullable
    - `freeProvider` boolean, required
    - `mx` boolean, nullable: The domain publishes MX hosts, from cached DNS; absent when not cached.
    - `posture` MailPosture: The sender domain's DNS-published mail posture, from the cached aggregate ([`super::posture`]).
      - `dmarcPolicy` string, nullable: The DMARC policy that applies: `none` | `quarantine` | `reject`.
      - `grade` string, nullable: `A`..`F`, as the report's DNS card grades it.
      - `hasDmarc` boolean, nullable: A DMARC record applies to the sender domain: its own, or its organizational domain's.
      - `hasMx` boolean, nullable
      - `hasSpf` boolean, nullable
      - `spfAll` string, nullable: The qualifier of the SPF record's `all`: `fail` | `softfail` | `neutral` | `pass`. Absent without an SPF record or without an `all`.
      - `spoofable` boolean, nullable: Nothing the domain publishes would make a receiver that checks DMARC reject a message forged with it: no DMARC record, a `p=none` record, or a policy applied to under half of the failing mail. Absent when the DNS answer cannot say.
    - `replyTo` string[], required
    - `returnPath` string, nullable
    - `verdict` string, required: What the dataset says about the address and its domain: `malicious` | `suspicious` | `unknown`. Never `clean`: the dataset has no allowlist for addresses.
  - `verdict` string, required: `malicious` | `suspicious` | `clean` | `inconclusive`. `clean` is a positive claim: it needs your own system's DMARC pass, a sender domain the dataset knows as established (among the 100 000 most visited, and not a free mailbox) and every attachment and link vouched for or read. A message with nothing against it and no such evidence is `inconclusive`: a DMARC pass shows who sent a message, not that they can be trusted.

## Other responses

- `400`: No message, several inputs, or input that is not an email
- `401`: Unauthorized
- `413`: The message exceeds 10 MiB
- `429`: Scan quota exceeded
- `503`: The scan is busy: retry after the delay in Retry-After

## Changes

- **2026-10-05** `9dfa82b5838d`: 9 info
  - added the optional property `billingIssue` to the response with the `429` status
  - added the optional property `cta` to the response with the `429` status
  - added the optional property `docs` to the response with the `429` status
  - added the optional property `message` to the response with the `429` status
  - …5 more
- **2026-10-01** `9c119a3231ae`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api/changes/mail/scan/post.md)

---

[API](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api.md) - [All operations](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api/revisions/b6f45e6169a7?raw)
