Перейти к документации
CLI

Файлы, импорт и настройки

Каждая команда для файлов, которые хранит ящик, импорта старого ящика или аккаунта Resend, календаря, найденного в почте, и настроек рабочего пространства и каждого адреса.

Обзор

Пять пространств имён охватывают то, что окружает саму почту. openemail files это страница «Файлы»: каждое отправленное и полученное вложение и каждый загруженный файл, с его байтами и ссылками на скачивание, в виде которых он уходил. openemail imports переносит старый ящик в один адрес, а openemail provider-imports переносит аккаунт Resend. openemail calendar читает события, найденные в почте, а openemail settings читает и меняет настройки ящика, а также подпись и отслеживание каждого адреса.

  • Идентификатор говорит, что он называет: file_ для файла, imp_ для импорта ящика, pimp_ для импорта из Resend и cal_ для события календаря, в каждом случае с 24 шестнадцатеричными символами после префикса. У ссылки на скачивание свой идентификатор, из files list-links или files create-link.
  • --address-id у импорта это идентификатор адреса из openemail domains list-addresses <id>, а не сам адрес.
  • Пространства имён откликаются также на file, import, provider-import или providerImports и setting. Глаголы принимают обычные псевдонимы там, где они есть: ls для list, show и view для get, new и add для create, edit для settings update, а также rm, del и remove для files delete.
  • Ни одна из этих команд не спрашивает у входа через браузер код подтверждения. Те, что меняют что-то навсегда, просят подтверждения, а в скрипте за вас отвечает --yes.
  • openemail <command> --help перечисляет каждый аргумент и флаг с типом, scope, который нужен вызову, методом и путём и тем, что возвращается. Добавьте --json, чтобы получить ту же страницу как данные.

Файлы

openemail files читает каждый файл, который хранит ящик, и управляет им: пришедшими вложениями, ушедшими вложениями и файлами, загруженными на страницу «Файлы». openemail open files открывает ту же страницу в веб-приложении.

КомандаЧто делает
openemail files listПоказать одну страницу файлов с именем, типом, размером, направлением, адресом, на который пришёл каждый, и тем, можно ли его удалить
openemail files get <id>Прочитать один файл с цепочкой и письмом, которым он принадлежит, его usage и deletable
openemail files statsПосчитать файлы и занимаемые ими байты с разбивкой на полученные, отправленные и загруженные, с самыми частыми типами и адресами, последними 30 днями и ещё работающими ссылками
openemail files download <id>Получить байты файла ровно так, как они хранятся, в --out <file> или в stdout при передаче в конвейер
openemail files list-links <id>Показать ссылки на скачивание, в виде которых уходил файл, новые сверху, с тем, сколько раз каждую скачивали и отозвана ли она
openemail files create-link <id>Опубликовать файл по новой публичной ссылке на скачивание, которая открывается без входа
openemail files revoke-link <id> <link-id>Навсегда остановить публичную ссылку, в том числе в уже отправленной почте. Просит подтверждения
openemail files upload <data>Загрузить файл по пути или из stdin через -, до 100 МБ
openemail files delete <id>Навсегда удалить загрузку, от которой ничего не зависит. Просит подтверждения
openemail files delete-many <ids...>Удалить до 100 файлов за один вызов и сообщить, какие оставлены и какие не найдены. Просит подтверждения
  • files list сужается через --q (имя и тип), --kind (image, pdf, audio, video или text), --direction (inbound, outbound или uploaded), --address, --since и --until и сортируется через --sort (newest, oldest, largest или name). --since и --until принимают дату или дату со временем в ISO 8601: --since включает свой момент, а --until останавливается перед ним.
  • Удалить можно только загрузку, от которой ничего не зависит, и deletable сообщает об этом заранее. usage говорит, что удерживает любой другой файл: received, sent, linked для загрузки, ссылка на скачивание которой ещё работает, или scheduled для файла, прикреплённого к письму, которое ещё не ушло. delete отклоняет такие с 409 file_in_use. delete-many удаляет то, что может, перечисляет остальное в kept с причиной для каждого и перечисляет неизвестные идентификаторы в missing.
  • upload читает файл по указанному пути и сохраняет его под именем этого файла с типом, который подразумевает расширение. --filename и --content-type их переопределяют. Для stdin через - нужен --filename, а без --content-type тип будет application/octet-stream. Загрузка ждёт до 10 минут, что меняет --timeout-ms.
  • Идентификатор, который возвращает upload, прикрепляет файл к отправке как { "fileId": "…" } в openemail emails send --attachments, и именно так уходит файл больше встроенного предела в 5 МБ.
  • Пустой файл это 400 upload_empty, программа или скрипт (судя по имени) это 400 upload_dangerous, а файл больше 100 МБ это 413 upload_too_large. Рабочее пространство хранит до 10 ГБ загрузок и принимает 500 загрузок в час.
  • download в терминале нужен --out <file>, без него она останавливается с кодом выхода 2. В конвейере байты идут в stdout, и --out - тоже просит stdout. Весь файл держится в памяти.
  • create-link при каждом вызове создаёт новую ссылку со своим счётчиком скачиваний, и ссылка работает, пока её не отзовут или файл не удалят. Она размещается на домене файлов домена из --domain, если он у него есть, например files.acme.com, иначе на домене файлов адреса файла, иначе на адресе API. Программа или скрипт отклоняется с 422 file_unshareable.
  • revoke-link можно безопасно повторять: уже отозванная ссылка возвращается без изменений.
  • Ключ или вход, ограниченный определёнными адресами или доменами, видит только файлы, пришедшие на них, и никогда не видит файлы, загруженные для всего рабочего пространства, а его собственные загрузки принадлежат первому выданному ему адресу.
  • Индекс файлов начинается со дня своего выпуска. Более старые вложения по-прежнему лежат в своих письмах, где их читает openemail threads list-attachments <id>.

Импорт почтовых ящиков

openemail imports переносит старый ящик в один адрес: архивы Google Takeout, файлы .mbox из Apple Mail, Thunderbird и большинства настольных приложений, файлы .eml и архивы .zip или .tgz, содержащие любые из них, до 100 ГБ на файл и 50 файлов на импорт. Цепочки, даты и метки переносятся. Импортированная почта ведёт себя тихо: она не запускает правил, пересылок, уведомлений, сводок и вебхуков.

import-files это то, что нужно большинству: она создаёт импорт, загружает каждый файл частями со строкой прогресса и запускает его. Остальные глаголы это те же шаги по одному, чтобы завершить остановившуюся загрузку или вести её самому. create возвращает план, chunkBytes и chunks каждого файла, upload-chunk отправляет одну часть, upload-state говорит, какие части пришли, а start ставит импорт в очередь. openemail open imports показывает те же импорты в веб-приложении.

КомандаЧто делает
openemail imports listПоказать одну страницу импортов рабочего пространства, новые сверху, со статусом, прочитанными байтами и счётчиками. --address-id оставляет один адрес
openemail imports get <id>Прочитать один импорт со статусом, прогрессом и счётчиками. Опрашивайте его, пока он не станет completed, failed или cancelled
openemail imports create --address-id <value> --files <json|@file|->Создать импорт из списка { name, bytes } и получить его план загрузки со status, равным uploading
openemail imports upload-state <id>Для каждого файла индексы частей, которые уже сохранены, чтобы остановившаяся загрузка отправляла только недостающее
openemail imports upload-chunk <id> <file> <chunk> <data>Загрузить одну часть одного файла по пути или из stdin через -. Повторная отправка части заменяет её
openemail imports start <id>Проверить, что пришли все части, распознать формат каждого файла и поставить импорт в очередь
openemail imports cancel <id>Остановить импорт в его следующей контрольной точке. Уже импортированная почта остаётся. Просит подтверждения
openemail imports list-failures <id>Показать каждое письмо или элемент архива, который не перенёсся, с причиной
openemail imports delete-upload <id>Удалить загруженные файлы. Уже импортированная почта остаётся. Просит подтверждения
openemail imports import-files --address-id <value> --files <path>Создать, загрузить и запустить импорт одной командой и вернуться, как только он встанет в очередь
  • Адрес должен быть на собственных доменах рабочего пространства, и ключ или вход должен иметь право действовать от его имени. На адрес выполняется только один импорт: ещё один, пока первый в очереди или выполняется, даёт 409 already_running.
  • import-files принимает --files по одному разу на файл или несколько путей через запятую и отправляет каждый под его собственным именем. --options принимает JSON, например {"keepInbox":false,"includeSpam":true}. В create те же три это переключатели: --options-keep-inbox, --options-include-spam и --options-include-trash, каждый выключается приставкой --no-, как в --no-options-keep-inbox.
  • keepInbox включён по умолчанию, поэтому почта из старых входящих попадает во «Входящие» с признаком непрочитанности. Если выключить, всё раскладывается в «Архив». Спам и корзина остаются на месте, если вы их не включите.
  • create принимает --files в виде JSON, встроенно или из файла через @path, и каждый bytes должен точно равняться размеру файла, который вы затем загрузите.
  • Каждая часть имеет длину ровно chunkBytes, кроме последней части файла, а часть неверной длины даёт 400 bad_chunk. start отклоняет файл с недостающими частями с 412 missing_chunks, а файл, который не является архивом или почтовым ящиком, с 400 unsupported_file. Для импорта, который уже вышел из uploading, она возвращает импорт без изменений.
  • Если часть по-прежнему не проходит после повторов, import-files останавливается, оставив импорт в uploading. Блок ниже отправляет недостающие части первого файла и запускает импорт.
  • Импорт сообщает processedBytes из totalBytes, а также counts с seen, imported, duplicate, filtered, failed и threads. lastError задан, только когда status равен failed.
  • list-failures даёт каждой неудаче reason: too-large (больше 50 МБ), unparseable, no-date, storage-error, unreadable-entry, encrypted-entry или archive-limit, с темой и отправителем, если их удалось прочитать.
  • cancel для завершённого импорта даёт 409 not_cancellable. delete-upload отменяет импорт, который ещё загружается, и отклоняет импорт в очереди или в работе с 409 still_running, поэтому сначала отмените его.
Завершить остановившуюся загрузку
openemail imports get "$import_id" --json > import.jsonopenemail imports upload-state "$import_id" --json > state.jsonchunk=$(jq .chunkBytes import.json)chunks=$(jq '.files[0].chunks' import.json)for i in $(seq 0 $((chunks - 1))); do  jq -e --argjson i "$i" '.received[0] | any(. == $i)' state.json > /dev/null && continue  dd if=takeout-001.zip bs="$chunk" skip="$i" count=1 2> /dev/null |    openemail imports upload-chunk "$import_id" 0 "$i" -doneopenemail imports start "$import_id"

Импорт из Resend

openemail provider-imports переносит рабочее пространство из Resend по одному API-ключу Resend с полным доступом. Подавления сохраняют причину, сегменты становятся аудиториями, подписанные контакты приходят с именами, а шаблоны приходят как HTML-шаблоны с объявленными переменными. Вебхуки регистрируются выключенными, потому что доставки здесь подписываются иначе. Ключ подписи или токен не может покинуть Resend, поэтому домены и API-ключи возвращаются вместо этого списком дел в отчёте.

КомандаЧто делает
openemail provider-imports inspect <api-key>Посчитать, что хранит аккаунт Resend, по ресурсам, до импорта. Ничего не сохраняется, и ключ не хранится
openemail provider-imports create --resend-key <value> --resources <a,b>Поставить в очередь импорт названных ресурсов
openemail provider-imports listПоказать одну страницу импортов от провайдеров отправки, новые сверху, каждый с отчётом
openemail provider-imports get <id>Прочитать один импорт: его статус, текущий шаг и отчёт на данный момент
openemail provider-imports cancel <id>Остановить импорт и стереть ключ Resend. То, что уже перенеслось, остаётся. Просит подтверждения
  • Передайте ключ Resend как @path, чтобы прочитать его из файла, или как -, чтобы прочитать из stdin, и он не попадёт в историю оболочки и список процессов. Ключ, набранный в командной строке, тоже работает, но с предупреждением. --dry-run выводит тело со скрытым ключом.
  • --resources принимает любые из suppressions, audiences, contacts, templates, webhooks, domains и api-keys, через запятую или повторением.
  • Ключ только для отправки даёт 400 restricted_key. Создайте для импорта ключ с полным доступом в Resend, а после отзовите его.
  • inspect читает первую страницу каждого ресурса и возвращает counts, по одному { count, more } на ресурс, где more задан, если ресурс выходит за пределы первой страницы.
  • В рабочем пространстве одновременно выполняется один импорт, а второй даёт 409 already_running. Двойной запуск того же импорта ничего не дублирует. Ключ хранится в зашифрованном виде только пока идёт импорт и стирается, когда он заканчивается, не проходит или отменяется.
  • Контакты, отписавшиеся в Resend, пропускаются и учитываются в report.contacts.unsubscribed.
  • report.domains перечисляет каждый домен Resend с state: absent, когда его нет в этом рабочем пространстве, added, когда он есть, но не подтверждён, и verified, вместе с записями, которые у него были в Resend. Недостающий добавьте через openemail domains create. report.apiKeys называет ключи, которые нужно создать заново через openemail keys create.
  • При входе через браузер эти команды может использовать только владелец рабочего пространства, а участник получает 403 owner_only. На API-ключ это не распространяется. Ключ или вход, ограниченный определёнными адресами или доменами, не может осмотреть или создать импорт, поскольку аудитории, подавления и шаблоны принадлежат всему рабочему пространству.
  • create нужен также scope каждого ресурса, который он переносит: audiences:write для аудиторий, contacts:write и audiences:write для контактов, templates:write для шаблонов, webhooks:write для вебхуков и domains:read для доменов.

Календарь

openemail calendar читает события календаря, найденные в почте. Все три команды только читают. list-events разворачивает каждое событие в его повторения внутри заданного периода, так что еженедельная встреча это одна строка в неделю, а get-event и get-event-ics читают одно событие целиком. openemail open calendar открывает календарь в веб-приложении.

КомандаЧто делает
openemail calendar list-events --from <when> --to <when>Показать одну страницу повторений между двумя моментами, по времени начала, каждое со ссылкой на своё событие через eventId
openemail calendar get-event <id>Прочитать событие с участниками и их ответами, правилом повторения, исключёнными датами, организатором и напоминаниями
openemail calendar get-event-ics <id>Скачать событие как документ iCalendar, выведенный на экран или записанный в --out <file>
  • --from и --to это дата и время в ISO 8601, например 2026-10-01T00:00:00Z. --to должен быть позже --from и не больше чем на 366 дней, поскольку у повторяющейся серии нет конца, до которого можно перечислять. Отсутствующая граница даёт 422 invalid_parameter. Граница, которая не разбирается, перевёрнутый или слишком длинный период или неизвестный часовой пояс дают 400 invalid_parameter.
  • --timezone это часовой пояс IANA, например Europe/London, а если его не указать, UTC. Он разворачивает события, сохранённые без собственного часового пояса, и решает, на какой день попадёт событие на весь день.
  • get-event и get-event-ics принимают eventId повторения, а не uid iCalendar. Повторяющаяся серия это одно событие, поэтому её start и end описывают первый экземпляр.
  • Отменённые события тоже перечисляются, со status, равным CANCELLED. myPartstat это ответ, записанный для любого адреса, который рабочее пространство держит на своих доменах, и null, если ни один из них не участник.
  • Страницы продолжаются через --cursor с тем же периодом. Ключ или вход, ограниченный определёнными адресами, видит только события, которые один из них организует или посещает, а любое другое событие даёт 404.
  • get-event-ics объявляет METHOD:PUBLISH, поэтому при импорте событие показывается как есть, без предложения принять или отклонить. События со временем записываются как моменты в UTC, а события на весь день как даты. DTSTAMP это время скачивания, поэтому два скачивания неизменного события различаются этой строкой.

Настройки

openemail settings читает и меняет настройки ящика, такие как часовой пояс, язык, формат времени и списки блокировки. Четыре настройки принадлежат адресу, а не рабочему пространству: signature, openEmailSignature (футер OpenEmail), trackOpens и trackClicks. Назовите адрес через --address или *@acme.com для catch-all домена.

КомандаЧто делает
openemail settings getПрочитать все настройки с подставленными значениями по умолчанию. С --address четыре настройки адреса читаются так, как их определяет отправка с этого адреса
openemail settings updateИзменить переданные настройки, остальные сохранить. Ответ содержит все настройки, прочитанные после записи
  • Без --address get читает четыре настройки адреса как встроенные значения по умолчанию: без подписи, футер OpenEmail включён, отслеживание открытий и ссылок включено. С ним они берутся из собственных значений адреса, затем из catch-all его домена, если этот адрес подхватил catch-all, затем из значений по умолчанию. Плюс-адрес без собственных настроек читает настройки своего основного адреса.
  • Без --address update отклоняет --signature, --open-email-signature, --track-opens и --track-clicks с 422 address_required и ничего не записывает. С ним update принимает только эти четыре, а всё остальное даёт 422 not_per_address. Адрес должен быть в этом рабочем пространстве или быть *@domain для подтверждённого здесь домена с включённым catch-all.
  • Переключатели выключаются приставкой --no-: --no-open-email-signature, --no-track-opens и --no-track-clicks.
  • --signature это HTML длиной не более 150 000 символов, очищаемый при записи, так что возвращается именно то, что будет отправлено. Пустая строка удаляет подпись. Добавит ли её отправка, решает отправка: см. --signature в openemail emails send --help.
  • Флаги покрывают частые поля. --data принимает любую сохранённую настройку в виде JSON, встроенно, из файла через @path или из stdin через -, например timeFormat, weekStart, undoSendEnabled, blockedSenders или blockedDomains. Ключи, которых настройки не знают, отбрасываются без ошибки, а известный ключ с неверным типом даёт 422 invalid_parameter.
  • Список, такой как blockedDomains, заменяется целиком, поэтому сначала прочитайте его и отправьте обратно со своим изменением, как в примере ниже. Запись списка блокировки, слишком короткая, чтобы быть правилом, даёт 422 blocklist_entry_too_broad.
  • --timezone и --language сохраняются как есть, без проверки, поэтому проверьте часовой пояс или код языка до отправки.
  • Поля конфиденциальности, externalImages, trustedSenders, blockedSenders, blockedDomains, blockedWords и useDefaultBlockedWords, принадлежат рабочему пространству. Ключ или вход, ограниченный определёнными адресами или доменами, не может их менять и может назвать в --address только выданный ему адрес или catch-all на домене, который выдан ему целиком. Любой из этих отказов даёт 422 capability_unsupported.
  • Обновление без содержимого ничего не меняет и возвращает текущие настройки. defaultEmailAlias только заранее выбирает адрес From в редакторе веб-приложения, и API никогда не использует его, чтобы выбрать отправителя.

Примеры

Загрузить файл и поделиться им по ссылке
file_id=$(openemail files upload ./price-list.pdf --json | jq -r .id)openemail files create-link "$file_id" --domain acme.com --json | jq -r .urlopenemail files list-links "$file_id"openemail files download "$file_id" --out copy.pdf

Каждый create-link создаёт новую ссылку, поэтому запустите его один раз и читайте ссылку через list-links. revoke-link позже останавливает её, в том числе в уже ушедшей почте.

Удалить все загрузки, которые ничем не используются
openemail files list --direction uploaded --all | jq -r 'select(.deletable) | .id' > deletable.txtwc -l < deletable.txtxargs -r -n 100 openemail files delete-many --yes --json < deletable.txt | jq -c '.kept[]'

С --all в конвейере files list выводит по одному файлу в строке. xargs -n 100 передаёт delete-many не больше 100 идентификаторов за вызов, а файл, который тем временем начал использоваться, возвращается в kept с причиной, а не проваливает вызов.

Импортировать старый ящик и следить за ним
domain_id=$(openemail domains list --all | jq -r 'select(.domain == "acme.com") | .id')address_id=$(openemail domains list-addresses "$domain_id" --all | jq -r 'select(.address == "[email protected]") | .id')openemail imports import-files --address-id "$address_id" --files ~/Downloads/takeout-001.zip --files ~/Downloads/takeout-002.zip --json > import.jsonimport_id=$(jq -r .id import.json)until openemail imports get "$import_id" --json | jq -e '.status != "queued" and .status != "running"' > /dev/null; do  sleep 60doneopenemail imports get "$import_id" --json | jq '{status, counts, lastError}'openemail imports list-failures "$import_id" --json | jq -r '.data[] | [.reason, .subject] | @tsv'

--dry-run у import-files выводит POST /imports, который она отправила бы, с именем и размером каждого файла, и ничего не загружает. list-failures читает по 100: передайте выведенный nextCursor как --after для следующей страницы.

Переезд с Resend
openemail provider-imports inspect @resend-key.txtopenemail provider-imports create --resend-key @resend-key.txt --resources suppressions,audiences,contacts,templates,webhooks,domains,api-keys --json > resend.jsonpimp_id=$(jq -r .id resend.json)until openemail provider-imports get "$pimp_id" --json | jq -e '.status != "queued" and .status != "running"' > /dev/null; do  sleep 10doneopenemail provider-imports get "$pimp_id" --json | jq '.report | {contacts, domains: [.domains[] | {name, state}], apiKeys: [.apiKeys[].name]}'
Прочитать встречи за месяц
openemail calendar list-events --from 2026-10-01T00:00:00Z --to 2026-11-01T00:00:00Z --timezone Europe/London --all |  jq -r 'select(.status != "CANCELLED") | [.start, .summary, .myPartstat] | @tsv'openemail calendar get-event cal_8d3f0a2b9c4e41f7a6b5c2d1 --json | jq '.attendees[] | {email, partstat}'openemail calendar get-event-ics cal_8d3f0a2b9c4e41f7a6b5c2d1 --out standup.ics
Подпись, отслеживание и список блокировки
openemail settings get --address [email protected] --json | jq '{signature, openEmailSignature, trackOpens, trackClicks}'openemail settings update --address [email protected] --signature "$(cat signature.html)" --no-track-clicks --dry-runopenemail settings update --address [email protected] --signature "$(cat signature.html)" --no-track-clicksopenemail settings update --address '*@acme.com' --no-track-opensopenemail settings update --timezone Europe/London --language enopenemail settings get --json | jq -c '{blockedDomains: ((.blockedDomains + ["spam.example"]) | unique)}' |  openemail settings update --data -

Пробный запуск выводит PATCH /settings?address=sales%40acme.com и его тело, не отправляя его. Строка с catch-all задаёт отслеживание для каждого адреса, который подхватывает catch-all acme.com, а последняя строка добавляет один домен в список блокировки, не убирая остальные.

Scope, подтверждения и ошибки

ScopeКоманды
files:readfiles list, get, stats, download, list-links
files:writefiles create-link, revoke-link, upload, delete, delete-many
threads:readimports list, get, list-failures
threads:writeimports create, upload-state, upload-chunk, start, cancel, delete-upload, import-files
settings:readprovider-imports list, get, а также settings get
settings:writeprovider-imports inspect, create, cancel, а также settings update
calendar:readcalendar list-events, get-event, get-event-ics
  • Вход или ключ без нужного scope останавливается с кодом выхода 4, называет недостающий scope и объясняет, как его получить.
  • files revoke-link, files delete, files delete-many, imports cancel, imports delete-upload и provider-imports cancel просят подтверждения. Ответ «нет» завершает их с кодом 10 и ничего не меняет. Без присмотра и без --yes они останавливаются с кодом выхода 2 до любой отправки.
  • Ни одна команда здесь не спрашивает код подтверждения, ни при входе через браузер, ни с API-ключом, поэтому скрипту нужен только --yes.
  • --dry-run выводит запрос, который отправило бы изменение, с его телом и завершается с кодом 0, не отправляя его и не прося подтверждения. Тело-файл показывается своим размером и типом.
  • files list, files list-links, imports list, provider-imports list и calendar list-events читают одну страницу: --limit принимает от 1 до 100, а если его не указать, сервер отдаёт 25, и --cursor принимает nextCursor предыдущей страницы. --all читает все страницы, --max <n> останавливается после стольких элементов, а --ndjson или --all в конвейере выводит по одному JSON-объекту в строке. С --json они выводят один документ { items, hasMore, nextCursor }.
  • imports list-failures листает по-своему: --after принимает nextCursor предыдущей страницы, --limit не больше 100, что и есть значение по умолчанию, а --all нет. С --json она выводит { object, data, nextCursor }.
  • Чтения и изменения, которые дважды дают один и тот же результат, повторяются после сбоя сети: files revoke-link, imports upload-chunk, imports start и settings update. Любое другое изменение отправляется один раз. После потерянного ответа посмотрите, прежде чем пробовать снова: второй upload сохраняет вторую копию, а второй create-link создаёт вторую ссылку, 404 на вашем втором files delete значит, что первый сработал, а второй delete-many перечисляет в missing то, что удалил первый.
  • Отказ завершается кодом своего статуса: 4 для 403, 5 для 404, 6 для 409, 7 для 400 или 422 и 8 для 429.

Куда дальше

Ваши входящие,
на ваших условиях.

Почтовая инфраструктура для бизнеса, ИИ, агентов и личной почты. Создана для масштаба, приватности и контроля. Всё, что должно было быть в почте с первого дня.

OpenEmail

Почтовая инфраструктура для бизнеса, ИИ, агентов и личной почты. Создана для масштаба, приватности и контроля. Всё, что должно было быть в почте с первого дня.

© 2026 OpenEmail. Все права защищены.