# Командная строка

```text
spamscanner <command> [options]
```

| Команда                                    | Что делает                                                                                      |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| `scan [file\|-]`                           | Проверяет письмо из файла или стандартного ввода                                                |
| `filter -f <sender> -- <recipients...>`    | Контент-фильтр Postfix: проверяет стандартный ввод, добавляет заголовки, передаёт письмо дальше |
| `milter`                                   | Milter для Postfix и Sendmail, порт 7831                                                        |
| `http`                                     | HTTP API, порт 7832                                                                             |
| `server`                                   | Простой TCP-сервер, порт 7830                                                                   |
| `spamd`                                    | Сервер spamd, совместимый со SpamAssassin, порт 783                                             |
| `train`                                    | Обучает модель на файлах mbox, каталогах Maildir, папках или наборах данных                     |
| `eval`                                     | Измеряет качество модели на размеченной почте                                                   |
| `learn spam\|ham [file\|-] --model <file>` | Обучает модель на одном письме                                                                  |
| `llm-test`                                 | Проверяет настройки языковой модели на трёх примерах писем                                      |
| `models`                                   | Выводит список рекомендуемых открытых моделей                                                   |
| `version`, `help`                          |                                                                                                 |


## scan

```sh
spamscanner scan message.eml
spamscanner scan - < message.eml
spamscanner scan message.eml --json
spamscanner scan message.eml --headers > tagged.eml
spamscanner scan message.eml --subject-tag "[SPAM]" > tagged.eml
```

| Параметр                   | Значение                                                     |
| -------------------------- | ------------------------------------------------------------ |
| `--json`                   | Вывести полный результат в JSON                              |
| `--headers`                | Вывести письмо с добавленными заголовками `X-Spam-*`         |
| `--subject-tag <tag>`      | Также добавлять префикс к теме спама                         |
| `--verbose`                | Показать все тесты и самые сильные признаки классификатора   |
| `--threshold <n>`          | Оценка, при которой письмо считается спамом (по умолчанию 5) |
| `--reject-threshold <n>`   | Оценка, при которой письмо отклоняется (по умолчанию 15)     |
| `--model <file>`           | Файл модели вместо встроенной                                |
| `--no-classifier`          | Не использовать классификатор                                |
| `--config <file>`          | JSON-файл с [параметрами библиотеки](https://spamscanner.net/ru/docs/api/#options)         |
| `--allow-language <codes>` | Допустимые языки, например `en,de,fr`                        |

Коды выхода: 0 — ham, 1 — спам, 2 — ошибка.

### SMTP-сессия

| Параметр            | Значение                                        |
| ------------------- | ----------------------------------------------- |
| `--ip <address>`    | IP-адрес клиента, отправившего письмо           |
| `--hostname <name>` | Проверенное имя клиента в обратной зоне DNS     |
| `--helo <name>`     | Имя, которое клиент указал в HELO или EHLO      |
| `--from <address>`  | Отправитель в конверте (MAIL FROM)              |
| `--to <address>`    | Получатель в конверте; повторите для нескольких |

### Проверки

| Параметр              | Значение                                                                       |
| --------------------- | ------------------------------------------------------------------------------ |
| `--auth`              | Проверять SPF, DKIM, DMARC и ARC (нужен `--ip`)                                |
| `--dnsbl <zone>`      | Чёрный список IP, например `zen.spamhaus.org`; можно повторять                 |
| `--uribl <zone>`      | Чёрный список доменов для ссылок, например `dbl.spamhaus.org`; можно повторять |
| `--dns-server <ip>`   | Сервер имён для DNS-проверок; можно повторять                                  |
| `--no-cloudflare`     | Не спрашивать фильтрующие резолверы Cloudflare о ссылках                       |
| `--clamav [socket]`   | Проверять вложения через clamd на сокете по умолчанию или указанном            |
| `--allowlist <value>` | Всегда принимать этот IP-адрес, домен или адрес; можно повторять               |
| `--denylist <value>`  | Всегда отклонять этот IP-адрес, домен или адрес; можно повторять               |

### Языковая модель

| Параметр                                                   | Значение                                                                                                                                   |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `--llm <provider>`                                         | `ollama`, `clef-flash`, `jev`, `openai`, `anthropic` и другие ([список](https://spamscanner.net/ru/docs/llm/#providers))                                                 |
| `--llm-model <name>`                                       | Модель, например `qwen3.5:4b` или `claude-haiku-4-5`                                                                                       |
| `--llm-method <method>`                                    | `decision` (вероятность каждого вердикта за один шаг; по умолчанию, где доступно) или `generate` ([методы](https://spamscanner.net/ru/docs/llm/#decision-or-generation)) |
| `--llm-account <id>`                                       | ID аккаунта Cloudflare, для `clef` и `clef-flash`                                                                                          |
| `--llm-url <url>`                                          | Базовый URL, например `http://10.0.0.5:11434`                                                                                              |
| `--llm-host`, `--llm-port`, `--llm-path`, `--llm-protocol` | Изменить одну часть URL провайдера                                                                                                         |
| `--llm-api-key <key>`                                      | Ключ API; см. также переменные окружения ниже                                                                                              |
| `--llm-auth <type>`                                        | `bearer`, `x-api-key`, `api-key`, `basic`, `header` или `none`                                                                             |
| `--llm-auth-header <name>`                                 | Заголовок для ключа, вместе с `--llm-auth header`                                                                                          |
| `--llm-username`, `--llm-password`                         | Для `--llm-auth basic`                                                                                                                     |
| `--llm-header "Name: value"`                               | Дополнительный заголовок запроса; можно повторять                                                                                          |
| `--llm-mode <mode>`                                        | `auto` (только спорные случаи, по умолчанию) или `always`                                                                                  |
| `--llm-timeout <ms>`                                       | По умолчанию 30000                                                                                                                         |
| `--llm-policy <text>`                                      | Дополнительные правила для модели, например «Мы никогда не отправляем счета»                                                               |
| `--llm-redact`, `--no-llm-redact`                          | Сначала удалять персональные данные; по умолчанию включено для удалённых провайдеров                                                       |


## filter

[Контент-фильтр Postfix](https://spamscanner.net/ru/docs/postfix/#content-filter). Он читает письмо из стандартного ввода, добавляет заголовки `X-Spam-*` и передаёт его sendmail с тем же конвертом.

```sh
spamscanner filter -f "$sender" -- "$recipient"
```

| Параметр              | Значение                                                                   |
| --------------------- | -------------------------------------------------------------------------- |
| `--sendmail <path>`   | По умолчанию `/usr/sbin/sendmail`                                          |
| `--subject-tag <tag>` | Добавлять префикс к теме спама                                             |
| `--reject`            | Возвращать отправителю письма на пороге отклонения, а не передавать дальше |
| `--discard`           | Удалять письма на пороге отклонения, а не передавать дальше                |

Коды выхода следуют соглашениям sendmail, которые читает Postfix: 0 — доставлено (или удалено), 64 — не указаны получатели, 69 — отклонено как спам (Postfix возвращает его отправителю), 75 — любой сбой, и тогда Postfix сохраняет письмо и повторяет попытку позже.


## milter, http, server и spamd

```sh
spamscanner milter --port 7831 --reject --subject-tag "[SPAM]"
spamscanner http --port 7832 --token "$SPAMSCANNER_TOKEN"
spamscanner server --port 7830
spamscanner spamd --port 783
```

Порт 783 клиенты SpamAssassin используют по умолчанию. Для портов ниже 1024 нужны права root или привилегия `CAP_NET_BIND_SERVICE`; используйте другой порт, например `--port 7833`, и укажите его клиенту.

| Параметр              | Значение                                                                               |
| --------------------- | -------------------------------------------------------------------------------------- |
| `--port <n>`          | TCP-порт                                                                               |
| `--host <ip>`         | Адрес для прослушивания (по умолчанию 127.0.0.1)                                       |
| `--socket <path>`     | Слушать вместо этого Unix-сокет                                                        |
| `--reject`            | Milter: отклонять почту на пороге отклонения                                           |
| `--reject-code <n>`   | Milter: 451, повторить позже (по умолчанию), или 550                                   |
| `--quarantine`        | Milter: помещать спам в карантин почтового сервера                                     |
| `--name <hostname>`   | Milter: имя этого сервера в Authentication-Results                                     |
| `--token <secret>`    | HTTP: требовать `Authorization: Bearer <secret>`; нужно для `/learn`                   |
| `--allow-tell`        | spamd: принимать запросы TELL (`spamc -L spam`) для обучения                           |
| `--out <file>`        | HTTP и spamd: сохранять результаты обучения в этот файл модели                         |
| `--subject-tag <tag>` | Milter и spamd: добавлять префикс к теме спама                                         |
| `--verbose`           | Milter: записывать в журнал каждую проверку. TCP-сервер: отвечать одной строкой текста |

Параметры проверки, описанные выше, применяются и к серверам. [Milter](https://spamscanner.net/ru/docs/postfix/#milter), [HTTP API, TCP-сервер и spamd](https://spamscanner.net/ru/docs/http-api/).


## train, eval и learn

```sh
spamscanner train --spam ~/Mail/Junk --ham ~/Mail/Archive --out my-model.json
spamscanner eval --model my-model.json --spam test/spam.mbox --ham test/ham.mbox
spamscanner learn spam message.eml --model my-model.json
```

| Параметр                                        | Значение                                                                     |
| ----------------------------------------------- | ---------------------------------------------------------------------------- |
| `--spam <path>`                                 | Спам: файл mbox, каталог Maildir или папка с файлами `.eml`; можно повторять |
| `--ham <path>`                                  | Ham, аналогично; можно повторять                                             |
| `--dataset <file>`                              | Файл CSV или JSON Lines со столбцами текста и метки; можно повторять         |
| `--text-column <name>`, `--label-column <name>` | Имена столбцов, если они не определяются автоматически                       |
| `--out <file>`                                  | Куда записать модель (по умолчанию `spamscanner-model.json`)                 |
| `--merge`                                       | Начать со встроенной модели (или `--model`), а не с пустой                   |

`learn` обновляет файл модели на месте, а при первом запуске создаёт его из встроенной модели. [Обучение](https://spamscanner.net/ru/docs/training/)


## llm-test и models

```sh
spamscanner models
spamscanner llm-test --llm ollama --llm-model qwen3.5:4b
```

`llm-test` отправляет модели одно обычное письмо и два мошеннических, на английском и итальянском, выводит её вердикты, время на каждый, использованный метод и оборудование, и завершается с кодом 0, только если все три верны.


## Файл конфигурации

`--config file.json` (или переменная окружения `SPAMSCANNER_CONFIG`) загружает [параметры библиотеки](https://spamscanner.net/ru/docs/api/#options). Параметры командной строки имеют приоритет над файлом.

```json
{
  "threshold": 6,
  "authentication": true,
  "dnsbl": {"ip": ["zen.spamhaus.org"], "domain": ["dbl.spamhaus.org"]},
  "dns": {"servers": ["127.0.0.1"]},
  "clamav": {"socket": "/var/run/clamav/clamd.ctl"},
  "llm": {"provider": "ollama", "model": "qwen3.5:4b"},
  "scores": {"deceptiveLink": 4, "FROM_NAME_BRAND": 3}
}
```


## Переменные окружения

| Переменная                                                                                                                                                                                                                                                                                                                 | Значение                                        |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `SPAMSCANNER_CONFIG`                                                                                                                                                                                                                                                                                                       | Файл конфигурации                               |
| `SPAMSCANNER_MODEL`                                                                                                                                                                                                                                                                                                        | Файл модели, используемый вместо встроенной     |
| `SPAMSCANNER_TOKEN`                                                                                                                                                                                                                                                                                                        | Токен для HTTP API                              |
| `SPAMSCANNER_LLM_API_KEY`                                                                                                                                                                                                                                                                                                  | Ключ API для любого провайдера языковых моделей |
| `CLOUDFLARE_API_TOKEN` и `CLOUDFLARE_ACCOUNT_ID`, `TYPESAFE_API_KEY`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `MISTRAL_API_KEY`, `GROQ_API_KEY`, `OPENROUTER_API_KEY`, `DEEPSEEK_API_KEY`, `XAI_API_KEY`, `TOGETHER_API_KEY`, `FIREWORKS_API_KEY`, `CEREBRAS_API_KEY`, `HF_TOKEN`, `AZURE_OPENAI_API_KEY` | Собственный ключ каждого провайдера             |
| `NODE_DEBUG=spamscanner*`                                                                                                                                                                                                                                                                                                  | Отладочный журнал                               |
