# Spam filtering

Lettermint scans each inbound message for spam and email authentication results. Set a threshold to mark messages as spam on one route.

When the filter is enabled, `is_spam` is `true` if the score is equal to or higher than the threshold.

## Set the threshold

1. Open the inbound route and select **Settings**.
2. Find **Spam filter** and enable the control.
3. Set the **Spam threshold**.
4. Select **Save changes**.

When you enable the filter, the dashboard starts at `5`. A lower value marks more messages as spam. A higher value marks fewer messages as spam.

| Setting | Result |
| --- | --- |
| Score below the threshold | `is_spam` is `false` |
| Score equal to the threshold | `is_spam` is `true` |
| Score above the threshold | `is_spam` is `true` |
| Spam filter disabled | Scanning continues, but the score does not set `is_spam` to `true` |

Disabling the threshold does not stop scanning. The webhook still contains `spam_score`, `spam_symbols`, and `authentication_results`.

Use these fields for diagnostics and rules in your application.

## Read the spam result

```json
{
  "is_spam": true,
  "spam_score": 6.4,
  "spam_symbols": [
    {
      "name": "MISSING_MID",
      "score": 2.5,
      "description": "Message-ID header is missing"
    }
  ]
}
```

| Field | Use |
| --- | --- |
| `is_spam` | Read the result of the configured route threshold. Use it to quarantine or mark a message. |
| `spam_score` | Read the numeric scanner score. Use it with your application rules. |
| `spam_symbols` | Find scanner rules that supplied diagnostic information. Use them to investigate a result. |

Scanner symbols can change when scanner rules change. Do not make long-term application rules depend on one symbol name.

## Read authentication results

Use `authentication_results` for SPF, DKIM, and DMARC results:

```json
{
  "authentication_results": {
    "dkim": {
      "result": "pass",
      "domain": "example.com",
      "selector": "mail"
    },
    "dmarc": {
      "result": "pass",
      "domain": "example.com",
      "policy": "none"
    },
    "spf": {
      "result": "pass",
      "domain": "example.com"
    }
  }
}
```

Authentication results show if the message passed these checks. They do not prove that a message is safe. They also do not prove that the visible sender is trustworthy.

Combine these results with `is_spam`, your sender history, and the risk of the requested action.

For example, a support inbox can accept and mark a high-scoring message. An email-based account change must use more verification, even when all authentication checks pass.

## Apply the result in your handler

```typescript
const message = event.data

if (message.is_spam) {
  await quarantine(message.message_id, message)
  return
}

if (message.authentication_results.dmarc.result !== 'pass') {
  await requireManualReview(message.message_id, message)
  return
}

await processInboundMessage(message)
```

The webhook contains the scanner result. Your application must decide what to do with the message.

Do not use the spam threshold as a webhook delivery control. Your endpoint can still receive a `message.inbound` event.

See the [`message.inbound` reference](/platform/webhooks/events#messageinbound) for the complete field definitions.
