# `Mailglass.Deliverability.Result`
[🔗](https://github.com/szTheory/mailglass/blob/v1.0.0/lib/mailglass/deliverability/result.ex#L1)

Shared plain-data contract for `mix mail.doctor` runtime results.

The result shape is the single source of truth for both human and JSON
output. Formatters must consume this data directly rather than scraping text.

## Status Contract

Findings use a closed status set:

- `:pass`
- `:warn`
- `:fail`
- `:cannot_verify`

`:cannot_verify` is a first-class outcome. Resolver uncertainty, missing
explicit DKIM selectors, and malformed DNS answers must stay visible as data
instead of being coerced into `:fail`.

# `facts`

```elixir
@type facts() :: %{spf: map(), dkim: map(), dmarc: map(), mx: map(), bimi: map()}
```

# `finding`

```elixir
@type finding() :: %{
  :area =&gt; atom(),
  :check =&gt; atom(),
  :status =&gt; status(),
  :title =&gt; String.t(),
  :why_it_matters =&gt; String.t(),
  :observed =&gt; String.t(),
  :remediation =&gt; String.t(),
  optional(:evidence) =&gt; term()
}
```

# `resolver_error`

```elixir
@type resolver_error() :: %{
  :lookup =&gt; :txt | :mx | :cname,
  :domain =&gt; String.t(),
  :reason =&gt; atom(),
  optional(:context) =&gt; map()
}
```

# `status`

```elixir
@type status() :: :pass | :warn | :fail | :cannot_verify
```

# `summary`

```elixir
@type summary() :: %{
  pass: non_neg_integer(),
  warn: non_neg_integer(),
  fail: non_neg_integer(),
  cannot_verify: non_neg_integer()
}
```

# `t`

```elixir
@type t() :: %{
  schema_version: pos_integer(),
  domain: String.t(),
  dkim_selectors: [String.t()],
  summary: summary(),
  findings: [finding()],
  facts: facts(),
  resolver_errors: [resolver_error()]
}
```

# `empty_facts`

```elixir
@spec empty_facts() :: %{spf: %{}, dkim: %{}, dmarc: %{}, mx: %{}, bimi: %{}}
```

# `empty_summary`

```elixir
@spec empty_summary() :: %{pass: 0, warn: 0, fail: 0, cannot_verify: 0}
```

# `new`

```elixir
@spec new(keyword() | map()) :: {:ok, t()} | {:error, term()}
```

# `schema_version`

```elixir
@spec schema_version() :: 1
```

# `status?`

```elixir
@spec status?(term()) :: boolean()
```

# `statuses`

```elixir
@spec statuses() :: [status(), ...]
```

# `summary`

```elixir
@spec summary([finding()]) :: summary()
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
