Письма с дайджестом/сводкой активности не отправляются пользователям, хотя все условия выполнены (Discourse 3.6)

Мы используем Discourse 3.6 и столкнулись с проблемой: некоторые пользователи, которые должны получать дайджест-письма, никогда их не получают.

Вот что мы подтвердили для затронутого пользователя:

  • enable_digest_emails установлено в true

  • Пользователь был неактивен достаточно долго, чтобы сработал триггер дайджеста

  • Адрес электронной почты действителен и подтверждён

  • Со стороны почтового провайдера нет отказов или блокировок

  • Другие письма (уведомления и т. д.) отправляются без проблем

  • В логе отправленных писем (Администрирование → Электронная почта → Отправлено) нет записей о дайджест-письме

  • При использовании функции «Тест дайджеста» в разделе Администрирование → Электронная почта система корректно показывает «Да, дайджест должен быть отправлен», однако письмо не отправляется и не фиксируется в логах

В логах Sidekiq или продакшн-логах связанных ошибок не обнаружено.

Сталкивался ли кто-нибудь ещё с тем, что дайджест-письма на версии 3.6 молча не отправляются, даже когда все настройки и проверки доступности в административном интерфейсе указывают на то, что пользователь должен их получать?

Вы проверили настройки пользователя во вкладке «Предпочтения — Электронная почта»?

Да, вот их настройка, и вот отображение дайджеста для них, сообщающее, что его следует отправить.

Обновление / Шаги для воспроизведения (Discourse 3.6)

Я выполнил явное воспроизведение через консоль Rails, чтобы подтвердить, что происходит на уровне задачи. Вот что мы видим для затронутого пользователя:

site: hvac

now: 2025-10-15 17:23:01 UTC

disable_emails: “no”

disable_digest_emails: false

default_email_digest_frequency_minutes: 10080

ENV_DISABLE_EMAILS: nil

perform_deliveries: nil

smtp_address: “smtp.netcorecloud.net

smtp_port: 587

– ПОЛЬЗОВАТЕЛЬ –

id: 42122

username: XXXXXXXXXX

active: true

suspended: false

email_digests: true

digest_after_minutes: 10080

eligible_by_time: true

– ПОСЛЕДНИЕ 15 ЗАПИСЕЙ ЖУРНАЛА ЭЛЕКТРОННОЙ ПОЧТЫ –

2025-10-01 | type=digest | bounced=false

2025-09-22 | type=digest | bounced=false

perform_deliveries_now: true

Затем, когда я принудительно создал дайджест вручную, Discourse думает, что создаёт его, но возвращает:

mail = UserNotifications.digest(u)

=> Built digest mail: subject=nil bytes=50

Таким образом, Discourse считает, что дайджест создан, но на самом деле он пуст (subject=nil) — и поэтому задача пропускает его молча. Запись в EmailLog не создаётся, и ничего не отправляется.

Это подтверждает:

  • Задача успешно ставится в очередь

  • SMTP и доставка включены

  • Задача дайджеста завершается без ошибок, поскольку mailer возвращает пустой дайджест

Запуск задачи напрямую с помощью:

Jobs::UserEmail.new.execute(“type” => “digest”, “user_id” => u.id)

даёт тот же результат — новая строка в EmailLog не создаётся.

Возможная причина:

Кажется, дайджест пропускается из-за условия «пустого дайджеста» — возможно, что-то изменилось в том, как Discourse 3.6 оценивает контент для включения. Предпросмотр в Администрирование → Электронная почта → Тест дайджеста отображает дайджест корректно, но фоновая задача не видит ничего для включения.

Краткое резюме:

:white_check_mark: Пользователь имеет право на получение

:white_check_mark: Активная почта + корректный SMTP

:white_check_mark: Тестовый просмотр дайджеста в админке отображается правильно

:cross_mark: Фоновая задача создания дайджеста молча пропускает (пустой дайджест)

:cross_mark: Нет записи в EmailLog или попытки отправки

Будем благодарны за подтверждение от команды — возможно, в версии 3.6 произошло регрессионное изменение в том, как UserNotifications.digest собирает контент?

Проведя дополнительную работу, мы обнаружили несколько (из 4000) пользователей, которые действительно стабильно получают сводки активности.

Сравнение одного из таких пользователей, получающего сводки, с тем, кто их не получает, не выявило никаких различий в их настройках.

===== xxxxx (ID: 4149) =====
Активен: true, Приостановлен: false, Заглушен: false
Подтвержденный email: false
Сводка включена: true
Частота сводки: 10080 минут
Последний вход: 2025-03-24 20:58:55 UTC
Последняя отправка email: 2025-10-16 17:07:53 UTC
Заглушенные категории:
Попытка получения сводки статистики пользователя: 2025-10-16 17:07:53 UTC
Всего отправлено email: 16
===== xxxxxxx (ID: 42206) =====
Активен: true, Приостановлен: false, Заглушен: false
Подтвержденный email: false
Сводка включена: true
Частота сводки: 10080 минут
Последний вход: 2025-09-14 15:52:54 UTC
Последняя отправка email: 2025-10-01 23:30:33 UTC
Заглушенные категории:
Попытка получения сводки статистики пользователя: 2025-10-16 17:32:34 UTC
Всего отправлено email: 2

Конечно, существуют и другие настройки, но в любом случае это интересное сравнение.

Может ли кто-нибудь предоставить команду Rails, которую можно запустить, чтобы проверить, сколько дайджестов/сводок активности действительно просрочены? По сути, это проверка работоспособности, подтверждающая, что система действительно отправляет сводки, как и задумано.

Вы можете попробовать выполнить следующий запрос в консоли Rails для получения активных пользователей, у которых включены email-дайджесты и которым пора получить следующее письмо:

User.joins(:user_option)
  .where("user_options.email_digests = ?", true)
  .where("users.suspended_at IS NULL")
  .where("COALESCE(users.last_emailed_at, users.created_at) < (NOW() - INTERVAL '1 minute' * user_options.digest_after_minutes)")
  .count

Возможно, сводка была пропущена, потому что пользователь не заходил в течение количества дней до отключения дайджеста?

@jahan_gagan Это полезно, но это покажет нам, кто получит дайджест/сводку активности, а не кто её не получил. Понятно? Вопрос в том, как увидеть тех, кто не получает дайджест, хотя должен.

@Moin мы установили значение в 0 — так что это не должно быть фактором.

Вы уверены, что 0 отключает это? Вы пробовали большое число вместо этого?

@Moin Спасибо — нет, я не уверен. Изменил на 3000 — изменений в отправке дайджеста нет. Всё ещё вижу сотни с недельной частотой (уже более двух недель), но они не отправляются.

Хорошо, вот тест, чтобы проверить, кто сейчас имеет право:

Мы принудительно инициируем отправку прямо сейчас, но ничего не отправляется…

Берём пример пользователя, который не получает дайджест, проверяем административный интерфейс, и он, похоже, полностью соответствует требованиям…

Хорошо, так как других идей не нашлось, мы через админку изменили частоту рассылки дайджеста для всех пользователей на ежедневную (1440 минут).

И вдруг все дайджесты были отправлены…

У кого-нибудь есть идея, почему это произошло? Изменение частоты не должно было повлиять, учитывая, что мы видим, что эти пользователи были бы eligible и при еженедельной частоте.

Ой, поспешил. Перенос частоты сработал для одной группы пользователей (один сайт), но для другой — ничего не изменил. Загадка остаётся…

Думаю, это может быть связано с одним из последних требований в запросе, на который я ссылался выше.

После проверки того, что пользователь реален, активирован, не находится в тестовом режиме и не заблокирован, а также проверки того, что он не отключил дайджесты и частота больше 0, есть основной адрес электронной почты и показатель отскоков в норме, выполняются проверки по времени:

Последний визит был более digest_after_minutes минут назад
Последний визит находится в пределах suppress_digest_email_after_days
Последняя проверка, должен ли пользователь получать дайджест, проводилась digest_after_minutes минут назад.

Думаю, последняя проверка может быть причиной. Если Discourse пытался отправить дайджест вчера, а digest_after_minutes установлен на неделю, то повторная попытка не произойдет, пока не пройдет неделя. Если уменьшить это значение, следующая попытка произойдет раньше.

@Jacob_Peebles Похоже, вы боретесь с этой проблемой уже довольно давно! Я думаю, что тема от марта по адресу Digest Emails Not Sending to All Users – Need Help Debugging касается той же проблемы, я прав?

Помог ли вам последний пост от Мойна? Если да, дайте нам знать, чтобы мы могли закрыть эту тему.

@Jacob_Peebles, что вы хотите сделать с этой темой? Стоит ли нам её закрыть или у вас появилась какая-то новая информация по поводу этой истории?