---
title: "Отправить письмо или сохранить черновик"
method: POST
path: "/api/v1/mail/accounts/{id}/messages"
tags: ["Mail messages"]
---

# Отправить письмо или сохранить черновик

`POST /api/v1/mail/accounts/{id}/messages`

## Request

- Base URL: `https://erp.akeda.ru`
- URL: `https://erp.akeda.ru/api/v1/mail/accounts/{id}/messages`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://erp.akeda.ru/oauth2/authorize`, token URL `https://erp.akeda.ru/oauth2/token`, scopes: `akeda:delegate`)

При save_as_draft равном true письмо только СОХРАНЯЕТСЯ в «Черновиках» и ждёт человека — получателю оно не уходит. Без этого признака письмо встаёт в очередь отправки; после принятия SMTP-сервером его нельзя отозвать, но это принятие не подтверждает доставку или прочтение получателем. Для агента черновик — единственный способ подготовить ответ, не отправив его от чужого имени без подтверждения. В одном письме не больше 200 получателей и не больше 20 файлов. С send_at письмо откладывается: ждёт в «Исходящих» до этого времени, пока его не отправят сразу (send-now) или не вернут в черновики (cancel-send). Замена черновика (replace_draft_id) атомарна: прежняя версия удаляется той же записью. Устаревший replace_draft_id (вторая вкладка, повтор) заменяет живого преемника этого черновика, а не создаёт второй; если преемник уже отправлен — 409 mail.draft_sent, и ничего не сохраняется. Отправленное или чужое письмо по replace_draft_id не заменяется — 404.

## Request body

- MailComposeInput: Отправка письма или сохранение черновика. Поле in_reply_to_id указывает на письмо в нашей базе, а не на Message-ID: заголовки ответа собираем мы.
  - `subject` string
  - `to` string[]: Одна строка может содержать несколько адресов через запятую
  - `cc` string[]
  - `bcc` string[]
  - `body_text` string
  - `body_html` string
  - `in_reply_to_id` string, uuid
  - `forward_of_id` string, uuid
  - `upload_ids` UUID[]: Идентификаторы заранее загруженных файлов
  - `save_as_draft` boolean: Значение true СОХРАНЯЕТ письмо в «Черновиках» и не отправляет его; без признака письмо встаёт в очередь, а принятие SMTP-сервером не подтверждает доставку или прочтение получателем
  - `replace_draft_id` string, uuid
  - `keep_attachment_ids` UUID[]: Вложения заменяемого черновика, которые остаются в письме; только вместе с replace_draft_id
  - `send_at` string, date-time, nullable: Отложенная отправка: письмо ждёт в «Исходящих» до этого времени. Время в прошлом — 400 mail.schedule_past, дальше года — 400 mail.schedule_too_far, вместе с save_as_draft — 400 mail.schedule_draft

## Response `201`

Созданное письмо и его запись в очереди отправки

- object
  - `message` MailMessage, required: Письмо в копии кабинета. Внутренние координаты IMAP (UID и UIDVALIDITY) наружу не отдаются. Тело в HTML хранится таким, каким его прислал отправитель: обезвреживание живёт на отдаче, а не в хранимой копии.
    - `id` string, uuid, required
    - `account_id` string, uuid, required
    - `folder_id` string, uuid, required
    - `thread_id` string, uuid, required
    - `message_ref` string, required: Message-ID без угловых скобок; письму без него присваивается наш
    - `in_reply_to` string: Заголовок In-Reply-To
    - `references` string: Заголовок References целиком
    - `subject` string, required
    - `from_address` string, required
    - `from_name` string, required
    - `addresses` MailMessageAddress[]: Конверт письма целиком
      - `kind` string, required: Вид адреса: from, to, cc, bcc, reply_to. Значение list_id несёт идентификатор рассылки, а не адрес человека
      - `address` string, required
      - `name` string, required: Имя отправителя или получателя, если оно было в конверте
      - `position` integer, required: Порядок адреса в своей группе
    - `snippet` string, required: Короткий пересказ письма для списка
    - `body_text` string
    - `body_html` string
    - `size_bytes` integer, required
    - `direction` 'inbound' | 'outbound', required
    - `is_read` boolean, required
    - `is_flagged` boolean, required
    - `is_answered` boolean, required
    - `is_draft` boolean, required
    - `has_attachments` boolean, required
    - `spam_verdict` 'unknown' | 'spam' | 'ham', required: Вердикт по спаму; unknown — состояние по умолчанию. Вердикт справочный и с папкой не связан: письмо во «Входящих» может нести spam от провайдера (флаг $Junk на сервере почты), а папку «Спам» задаёт только перенос. Решение человека (spam_source=user) сильнее флага сервера и правил.
    - `spam_source` 'provider' | 'rule' | 'user' | 'agent': Кто вынес вердикт. Решение человека сильнее флага сервера и правил
    - `spam_reason` string
    - `delivery` MailDeliveryState
      - `status` 'queued' | 'sending' | 'sent' | 'failed' | 'cancelled', required
      - `attempts` integer, required
      - `error_code` string
      - `next_attempt_at` string, date-time: Срок ближайшей попытки у письма в очереди: время отложенной отправки или следующего повтора после сбоя
      - `scheduled` boolean: Письмо отложено человеком: попыток ещё не было, а срок первой — next_attempt_at в будущем. Экран показывает «Запланировано на …»
    - `delivery_failure` MailDeliveryFailure: Отказ доставки, пришедший на наше отправленное письмо отдельным письмом сервера (ERP-1865). Окончательный отказ сильнее задержки.
      - `severity` 'failed' | 'delayed', required: failed — не доставлено (5.x.x), delayed — доставка задерживается (4.x.x)
      - `recipient` string, required: Адрес, которому письмо не дошло
      - `status` string: Код RFC 3463 из отчёта сервера, например 5.1.1
      - `reason` 'user_unknown' | 'domain_unknown' | 'mailbox_full' | 'mailbox_disabled' | 'policy' | 'unreachable' | 'rejected' | 'delayed', required: Причина кодом; экран показывает её словами
      - `diagnostic` string: Ответ сервера получателя как есть
      - `report_message_id` string, uuid
    - `bounce_of_id` string, uuid
    - `sent_at` string, date-time, nullable, required
    - `received_at` string, date-time, required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `attachments` MailAttachment[]
      - `id` string, uuid, required
      - `message_id` string, uuid, required
      - `filename` string, required
      - `content_type` string, required
      - `size_bytes` integer, required
      - `content_id` string: Заполняется у картинок, вставленных в тело письма через cid:
      - `is_inline` boolean, required: Встроенная в тело картинка, а не документ
      - `scan_status` 'pending' | 'clean' | 'infected' | 'skipped', required: Состояние антивирусной проверки файла. pending существует потому, что письмо сохраняется целиком, а проверка идёт потоком: видеть письмо можно сразу, скачать вложение — только после вердикта.
      - `created_at` string, date-time, required
  - `outbound` MailOutbound, required: Исходящее письмо в очереди отправки. Постоянный отказ SMTP (код 5xx) не повторяется: повторять отклонённое навсегда письмо вредно для репутации отправителя.
    - `id` string, uuid, required
    - `account_id` string, uuid, required
    - `message_id` string, uuid, required
    - `status` 'queued' | 'sending' | 'sent' | 'failed' | 'cancelled', required
    - `attempts` integer, required
    - `max_attempts` integer, required
    - `next_attempt_at` string, date-time, nullable, required
    - `last_error` string, required
    - `last_error_code` string, required
    - `sent_at` string, date-time, nullable, required
    - `created_by` integer, required: Сотрудник, отправивший письмо
    - `created_at` string, date-time, required

## Other responses

- `400`: Некорректный запрос или нарушение бизнес-правила
- `401`: Сессия, ключ или кабинет не подтверждены
- `403`: Текущая роль не имеет требуемого права
- `404`: Запись не найдена или не видима текущему пользователю
- `409`: Конфликт версии, идемпотентности или бизнес-состояния

---

[API](https://skmtc.dev/akeda/apis/akeda-erp-client-api.md) · [All operations](https://skmtc.dev/akeda/apis/akeda-erp-client-api/llms.txt) · [OpenAPI document](https://skmtc.dev/akeda/apis/akeda-erp-client-api/revisions/3c60ded179f2?raw)
