ERPNext не отправляет письма: scheduler, воркеры, Email Queue
АйТи Фреш
Linux, Docker и DevOps

ERPNext не отправляет письма: scheduler, воркеры, Redis и Email Queue

Автор: , директор ООО «АйТи-Фреш» · · ~13 мин чтения
Техник открывает щиток с тремя рубильниками, письма застряли у шлагбаума: ERPNext не отправляет почту
Письмо стоит, пока не включён хотя бы один из трёх фоновых механизмов.

Если ERPNext не отправляет письма, сначала откройте Email Queue: письма со статусом Not Sent чаще всего ждут остановленный планировщик или воркер. Потом проверьте bench doctor и Email Account. Ниже порядок диагностики за пять минут и профилактика повторов.

Письма не уходят: что проверить за пять минут в Email Queue и Email Account

Начинаю всегда с одного места: список Email Queue. Любое письмо из ERPNext — уведомление, кнопка согласования Workflow, счёт покупателю — сначала записывается в очередь, и только потом отдельным процессом уходит на SMTP-сервер. Если письма нет в очереди, проблема в уведомлении или правиле. Если есть, смотрим статус: в коде Frappe у статуса пять вариантов — Not Sent, Sending, Sent, Partially Sent и Error. Not Sent означает, что письмо никто не взял в работу, Error — что взяли, но сервер отказал, и причина записана в поле Error. Это два разных расследования, и путать их нельзя.

Not Sent с накоплением записей — это почти всегда фон: не работает планировщик или нет воркера. Error с текстом — это почта: неверный пароль, закрытый порт, адрес отправителя, который сервер не принимает. Если у вас помощь с запуском и настройкой почты входит в ERPNext под ключ, такие вещи мы проверяем на первом этапе, но проверить это самому не сложно.

Пятиминутный порядок, который я использую: 1. Открыть Email Queue и отфильтровать по статусу: сколько Not Sent и сколько Error. 2. Открыть самую старую запись Not Sent и посмотреть дату создания и поле Send After. 3. Открыть одну запись Error и прочитать текст ошибки целиком. 4. Проверить Email Account: включён ли Enable Outgoing и отмечен ли аккаунт как Default Outgoing. 5. Выполнить на сервере диагностику фоновых процессов (раздел ниже) и посмотреть, включён ли scheduler.

Таблица «симптом — причина — действие» для первого прохода: | Симптом | Вероятная причина | Что делать | |---|---|---| | Письма Not Sent копятся | остановлен scheduler или воркер | диагностика bench doctor, перезапуск воркера | | Ошибка подключения Email Account | Gmail без пароля приложения | создать пароль приложения | | Microsoft отклоняет отправку | адрес отправителя не совпадает с авторизованным OAuth | слать с авторизованного адреса | | Кнопки Workflow Action не пришли | scheduler или воркеры | bench doctor и перезапуск | | Письма ушли, но не дошли | проблема на стороне почтового сервера, не ERPNext | смотреть SPF, DKIM и фильтры получателя |

Как работают фоновые задачи: scheduler, воркеры и Redis

ERPNext не отправляет письмо в момент нажатия кнопки. Он кладёт его в очередь и возвращает управление пользователю: иначе интерфейс ждал бы ответа SMTP-сервера. Дальше работают три механизма. Планировщик (scheduler) по расписанию ставит в очередь периодические задачи. Redis хранит очереди заданий. Воркеры забирают задания и выполняют. Если остановить любой из трёх, письма и другие фоновые операции перестают двигаться, а интерфейс при этом работает как ни в чём не бывало, и именно это сбивает с толку.

В хуках Frappe отправка очереди писем записана как событие планировщика с частотой «all»: функция сброса очереди (flush) и повторной отправки (retry_sending_emails) вызываются регулярно, без привязки к конкретным часам. Входящая почта подтягивается каждые десять минут, напоминания о неотвеченных письмах идут каждые пятнадцать. Поэтому «письмо ушло не сразу, а через минуту» — нормально, а «через час» — уже нет.

В контейнерной установке frappe_docker компоненты разнесены по сервисам. В актуальном compose.yaml это frontend (Nginx), backend, websocket, scheduler и два воркера: queue-short слушает очереди short и default, queue-long — long, default и short. MariaDB и два Redis (redis-cache и redis-queue) подключаются оверрайдами. Важная для почты деталь из кода Frappe v15: регулярные события с частотой «all», включая сброс очереди писем, планировщик ставит в очередь default, а её слушают оба воркера. Поэтому письма перестают уходить, когда встал планировщик или упали оба воркера, а не один из них. Длинные задачи (импорт, тяжёлые отчёты, событие с пометкой Long) идут в очередь long, и их обслуживает только queue-long. | Компонент | За что отвечает | Что видно при остановке | |---|---|---| | scheduler | ставит периодические задачи в очередь | письма не уходят, регулярные задачи не идут | | redis-queue | хранит задания | фоновые задачи не ставятся совсем | | redis-cache | кэш сессий и метаданных | замедление, странные ошибки интерфейса | | queue-short | очереди short и default | без второго воркера встают письма и короткие задачи | | queue-long | очереди long, default и short | зависают импорт и большие отчёты |

Про Redis оговорка. В главах нашей базы знаний подробных сценариев отказа Redis нет, и я не буду выдумывать «типичные сообщения об ошибках». Что мы делаем на практике: проверяем, что контейнеры redis-cache и redis-queue запущены, смотрим их логи и диагностику, перезапускаем сервис. Конкретный вывод зависит от версии и конфигурации, поэтому сверяйте с логами вашей системы.

Что показывает bench doctor и как читать его вывод

Команда bench doctor в документации Frappe описана как получение диагностики по фоновым воркерам. Анализ кода показывает, что она выводит число работающих воркеров, статус планировщика для каждого сайта (отключён, на паузе, неактивен, режим обслуживания) и список ожидающих заданий по очередям с названиями методов. Это именно то, что нужно: нули в числе воркеров или сообщение о выключенном планировщике сразу объясняют, почему письма стоят.

Набор команд для диагностики, который я держу под рукой, выглядит так:

bench --site example.com doctor
bench --site example.com scheduler status
bench --site example.com show-pending-jobs
bench --site example.com scheduler resume
bench --site example.com enable-scheduler

У планировщика в Frappe v15 два разных выключателя, и их часто путают. Пауза (команда scheduler pause, флаг pause_scheduler в конфиге сайта) снимается командой scheduler resume. Отключение (disable-scheduler или scheduler disable) снимается командой enable-scheduler. Включить отключённый планировщик и забыть про паузу значит оставить письма стоять. В контейнерной установке команды выполняются внутри контейнера backend, например через docker compose exec backend bench --site example.com doctor; имя сервиса и сайта подставьте свои. Точный формат вывода зависит от версии, поэтому опирайтесь на смысл: сколько воркеров, включён ли планировщик, есть ли застрявшие задания.

Как читать результат. Планировщик отключён или на паузе — включаем и повторяем проверку. Воркеров ноль — смотрим состояние контейнеров или процессов, поднимаем их. Воркеры есть, планировщик включён, а очередь Redis не растёт и не уменьшается — смотрим логи воркера и Redis. Много ожидающих заданий одного метода — это признак зависшей задачи, и нужно посмотреть журнал ошибок. Для сервера в режиме обслуживания (maintenance mode) планировщик не работает: после обновления бывает, что режим забыли отключить.

Что команда не показывает. Она не скажет, почему почтовый сервер отказал в приёме: это видно в поле Error конкретного письма. Она не проверит DNS, SPF и DKIM вашего домена. Если письма уходят из очереди, но не доходят, проблема на уровне почтовой инфраструктуры, и там помогают другие материалы: про аутентификацию писем SPF, DKIM, DMARC и про ограничения релея в Postfix.

Почта Gmail и Microsoft: пароли приложений и OAuth

Вторая по частоте причина после остановленного фона — настройка аккаунта. Для Gmail в документации ERPNext сказано, что может потребоваться двухфакторная аутентификация и пароль приложения (App Password), которые создаются в настройках аккаунта Google. Обычный пароль часто отклоняется. Для почты Microsoft в нашей базе знаний записано, что отправка с адреса, не совпадающего с авторизованным в OAuth, блокируется. Это работает так: система пытается отправить письмо от имени одного адреса через авторизацию другого, и сервер отказывает.

Настройку я проверяю по пунктам: у аккаунта включён Enable Outgoing, установлен Default Outgoing (иначе уведомления будут уходить с другого адреса), указаны правильный SMTP-сервер и порт, шифрование (TLS или SSL, по документации SSL использует порт 465), пароль приложения записан в Email Account. Для основных почтовых провайдеров Email Domain заводить не нужно, для корпоративного сервера — нужно. Если вы используете собственный почтовый сервер, хорошо, когда он принадлежит вам и вы видите его журналы; о выборе читайте в материале про собственный почтовый сервер или облако.

Практический совет: не используйте личный ящик сотрудника как отправителя уведомлений. Когда человек уходит и его аккаунт блокируют, перестают работать все уведомления системы. Заводите служебный ящик для системы и записывайте пароль приложения в сейф с понятным именем. Ещё одна частая беда — переход Gmail на новые политики безопасности: то, что работало год, перестаёт работать после очередного изменения на стороне провайдера. Поэтому для критичных уведомлений, например согласований, я предпочитаю собственный SMTP-сервер или проверенного транзакционного провайдера.

Ограничение, о котором стоит знать. ERPNext не показывает, дошло ли письмо до ящика получателя: статус Sent говорит только о том, что ваш SMTP-сервер принял письмо. Если получатель утверждает, что письма нет, проверьте папку «Спам» и журнал почтового сервера, прежде чем искать причину в ERPNext.

Как «Окна без Хлопот» вернули уведомления Workflow на 20 рабочих мест

Условный пример. Сервисная компания «Окна без Хлопот», 20 рабочих мест: замеры, монтаж и сервис остекления. В ERPNext настроено согласование выезда: заявка сервиса уходит руководителю, тот получает письмо с кнопками согласования. В понедельник утром руководитель сообщил, что с пятницы письма не приходят. Цифры и сроки в примере — иллюстрация процесса.

Диагностика заняла около получаса. В Email Queue нашли сотни писем со статусом Not Sent, самое старое — вечер пятницы. Ошибок в поле Error не было, значит, дело не в почте. Диагностика фоновых процессов показала, что планировщик стоит на паузе после ночного обновления сервера: при обслуживании его приостановили командой pause и не возобновили. Паузу сняли командой scheduler resume (enable-scheduler здесь не помог бы, он снимает другой флаг), письма начали уходить в течение нескольких минут и ушли все накопленные. Проблема оказалась в процессе, а не в настройке: в регламенте обновления не было пункта «проверить планировщик и очередь».

Что мы изменили после этого. Добавили в чек-лист обновления проверку диагностики и пустой очереди писем. Настроили еженедельную проверку: открыть Email Queue, отфильтровать Not Sent за сутки, убедиться, что очередь пуста или почти пуста. Рядом положили контрольное тестовое письмо раз в неделю на служебный адрес. Накопившиеся письма о старых согласованиях руководитель получил пачкой и часть закрыл вручную: уведомления пятницы потеряли актуальность. Это важный нюанс: после долгого простоя очередь выгружает все письма разом, и перед запуском стоит оценить, нужны ли пользователям старые уведомления.

Как не допустить повтора: мониторинг очередей и контрольное письмо

Починить один раз — полдела. Остальное — сделать так, чтобы следующий простой заметили за час, а не за три дня. Мы используем три уровня контроля. Первый — автоматический: скрипт раз в несколько минут проверяет число писем Not Sent старше десяти минут и количество воркеров, при отклонении присылает уведомление администратору. Второй — еженедельный ручной: открыть Email Queue и посмотреть ошибки. Третий — контрольное письмо раз в неделю, которое должно прийти на служебный ящик.

Чек-лист после починки: - диагностика bench doctor без предупреждений, число воркеров ненулевое; - планировщик включён, режим обслуживания выключен; - в Email Queue нет писем Not Sent старше нескольких минут; - тестовое письмо дошло и не попало в спам; - кнопки Workflow Action пришли руководителю; - пароль приложения или данные OAuth записаны в сейф, а не в чат.

Если вы строите мониторинг на Zabbix, имеет смысл вынести метрики очереди писем и числа воркеров в отдельный шаблон; подробнее — в нашей услуге мониторинг на Zabbix. Для сервера с сайтом и почтой полезен и контроль сертификатов: об этом материал про мониторинг SSL-сертификатов. Если вы хотите понять, как устроены очереди и кэш на Redis вообще, есть разбор кластера Redis для кэширования и очередей.

Что остаётся за рамками. Этот материал не заменяет регламента обновлений и резервного копирования, и не описывает все варианты отказа очередей: подробных сценариев отказа Redis в нашей базе знаний нет, и я не буду их придумывать. Для критичных процессов рекомендую иметь запасной канал: например, дублировать согласования в мессенджер или отдельный отчёт «ждут согласования», чтобы остановка почты не парализовала работу. Показать, как выглядят очередь писем и согласование, можно на демостенде erp-demo.itfresh.ru по запросу.

Частые вопросы

Почему ERPNext не отправляет письма?

Чаще всего письма ждут в Email Queue со статусом Not Sent из-за остановленного планировщика или воркера, реже неверно настроен Email Account. Для Gmail нужен пароль приложения, а Microsoft отклоняет отправку с адреса, не совпадающего с авторизованным OAuth. Статус и текст ошибки видны в списке Email Queue.

Как проверить, работает ли scheduler в ERPNext?

Выполните на сервере bench --site имя_сайта doctor: в выводе есть число воркеров и статус планировщика по сайту. Команда bench --site имя_сайта scheduler status показывает состояние отдельно; паузу снимает scheduler resume, а отключение — enable-scheduler. В контейнерной установке команды запускают внутри контейнера backend.

Чем отличаются воркеры queue-short и queue-long в Docker-установке ERPNext?

В compose.yaml репозитория frappe_docker queue-short слушает очереди short и default, а queue-long — long, default и short. Отправку писем планировщик ставит в очередь default, поэтому её подхватит любой из двух воркеров. Тяжёлые задачи из очереди long, например импорт, выполняет только queue-long. Имена сервисов сверяйте с compose-файлом своего релиза.

Что делать, если очередь Redis недоступна?

Проверьте, что контейнеры redis-cache и redis-queue запущены, посмотрите их логи и результат диагностики, при необходимости перезапустите сервис. Подробные сценарии отказа Redis в нашей базе знаний не разобраны, поэтому конкретные шаги проверьте на своём стенде и не полагайтесь на типовые советы из форумов.

Почему не уходит письмо через Gmail из ERPNext?

Gmail требует пароль приложения при включённой двухфакторной аутентификации: обычный пароль аккаунта часто отклоняется. Проверьте Enable Outgoing, Default Outgoing, SMTP-сервер, порт и шифрование. Ошибка подключения Email Account видна в журнале ошибок и в поле Error письма.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи