Email::Processor не ожидает вызова с mail=nil

Мой лог ошибок переполнен такими сообщениями:

Job exception: undefined method `is_bounce?' for nil.

Трассировка стека:
/var/www/discourse/lib/email/processor.rb:27:in `rescue in process!' 
/var/www/discourse/lib/email/processor.rb:16:in `process!' 
/var/www/discourse/lib/email/processor.rb:13:in `process!' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:23:in `process_popmail' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:43:in `block (2 levels) in poll_pop3' 
net-pop-0.1.2/lib/net/pop.rb:669:in `each' 
net-pop-0.1.2/lib/net/pop.rb:669:in `each_mail' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:40:in `block in poll_pop3' 
net-pop-0.1.2/lib/net/pop.rb:531:in `start' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:39:in `poll_pop3' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:14:in `execute' 
/var/www/discourse/app/jobs/base.rb:249:in `block (2 levels) in perform' 
rails_multisite-4.0.1/lib/rails_multisite/connection_management.rb:80:in `with_connection'
/var/www/discourse/app/jobs/base.rb:236:in `block in perform' 
/var/www/discourse/app/jobs/base.rb:232:in `each' 
/var/www/discourse/app/jobs/base.rb:232:in `perform' 
/var/www/discourse/app/jobs/base.rb:297:in `perform' 
mini_scheduler-0.15.0/lib/mini_scheduler/manager.rb:122:in `process_queue' 
mini_scheduler-0.15.0/lib/mini_scheduler/manager.rb:70:in `worker_loop' 
mini_scheduler-0.15.0/lib/mini_scheduler/manager.rb:59:in `block (2 levels) in ensure_worker_threads' 

Меня интересует, как @receiver мог стать nil в

1 лайк

Мое текущее понимание таково, что Email::Processor.process! вызывает Email::Receiver.new с аргументом mail=nil, что приводит к выбросу исключения Email::Receiver.EmptyEmailError, в результате чего @receiver остаётся неопределённым.

Далее блок rescue ожидает инициализированный @receiver.

Разве Email::Processor.initialize не должен выбрасывать ошибку при вызове с mail==nil?

Мне кажется, что somehow :arrow_double_up: вызывает сбой.

Я думаю, что PR, который изменит:

@receiver.is_bounce? на @receiver&.is_bounce?, будет приемлем, по крайней мере ошибка попадет в handle_bounce.

Мы сталкиваемся с той же проблемой, см. https://meta.discourse.org/t/problems-with-email-processing-undefined-method-is-bounce-for-nil-nilclass/259813/2. Есть ли какое-либо обходное решение, что-то, что мы можем сделать, чтобы обработка писем возобновилась? Вызвано ли это конкретным письмом или пользователем?

Обновление: Хорошо, проблема точно подтверждена. Благодаря анализу @thoka я теперь знал, на что обращать внимание: проблема действительно в пустых письмах. Обратите внимание, как сообщения остаются непрочитанными ровно до того момента, пока не появится пустое письмо?

Удаление его из входящих снова разблокирует обработку. То есть, пока не будет достигнуто следующее пустое письмо:

Итак, пустые письма в настоящее время блокируют систему для нас, по крайней мере, после определённого количества, поскольку кажется, что это немного лотерея — застрянет ли она навсегда или нет.

Пока, видимо, придётся следить за ситуацией, но было бы здорово, если бы это действительно исправили. Спасибо!!

Привет, @mekentosj, я разбираюсь с этой проблемой. Вы знаете, как в настоящее время генерируются пустые письма? Мне интересно, есть ли первопричина, которую мне нужно изучить (в дополнение к исправлению ошибки).

1 лайк

Отлично, спасибо за то, что разбираетесь в этом! Я не до конца понимаю, как им удаётся отправлять такие письма. Примеры на скриншоте, похоже, являются ответами, в которых кто-то (или их почтовое приложение) просто удалил всё содержимое тела письма перед отправкой ответа (это, кажется, чаще случается, когда люди отвечают на китайском, возможно, из-за проблемы с кодировкой символов или определённого типа почтового приложения). Но другие способы, которые, как я могу представить, были бы актуальны/возможны в нашей настройке: кто-то отправляет нам только вложение без текста тела и только с темой, или (некоторые люди до сих пор так делают) формулирует весь вопрос в теме письма, без текста тела.

1 лайк

На самом деле, я только что нашёл письмо и отправлю файл eml в личное сообщение (так как в нём указан адрес электронной почты пользователя). Возможно, там есть дополнительные подсказки.

2 лайка

Спасибо. Похоже, это письмо сгенерировано третьей стороной (Tencent/Китай). Я просмотрел заголовки письма и заметил несколько необычных моментов (ниже я выделил интересные части). В письме полностью отсутствует тело, но оно, судя по всему, является автоматическим ответом на письмо, отправленное на этот почтовый ящик qq.

Я быстро поискал X-QQ-MIME и выяснил, что ряд других сайтов сталкивается с аналогичными проблемами при обработке почты с адресов qq.com.

Я считаю, что нам безопасно пропускать любые письма, не содержащие тело. Мы можем тихо логировать их и предотвращать возникновение ошибки.

From: "=?utf-8?B?YWJjYzEwMDQwNTA3?=" <abcc10040507@qq.com>
Subject: =?utf-8?B?6Ieq5Yqo5Zue5aSNOiBGb2N1cyBhbmQgRmxvYXQg?=
 =?utf-8?B?d2l0aCBBZ2VuZGEgMTc=?=
Content-Transfer-Encoding: base64
X-QQ-AUTO-REPLY: true
Message-ID: <tencent_2BE587DA387104D27A33C94B@qq.com>
X-QQ-MIME: TCMime 1.0 by Tencent
1 лайк

Круто, да, это подтверждает моё ощущение, что проблема в основном затрагивала пользователей из Китая в нашем сообществе.

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

Да, главное, чтобы не пропускались письма, содержащие только вложения, даже если отправитель ничего не написал (я не эксперт в электронной почте, поэтому, возможно, в таком случае тело всё же присутствует).

Другой сценарий, который я упоминал, когда пользователь пишет только тему, но оставляет само письмо пустым, полагаю, сейчас уже пропускается? Если нет, то как-то нужно будет отличать такие письма от вызывающих проблему.

Альтернативой было бы распознавание заголовка X-QQ-AUTO-REPLY: true до того, как механизм обнаружения автоматически сгенерированных писем вызовет ошибку.

Кроме того, вы, вероятно, всё равно захотите решить эту конкретную ошибку, следуя тому, что предложил Сэм здесь.

Я декодировал тему письма в base64 и получил:
你好,我是 Focus and Flat Agile 17

Думаю, это связано с китайскими символами: перед отправкой они кодируются в base64. Это объясняет искажённый формат имени отправителя и темы.

Надеюсь, что существующая логика уже обрабатывает этот случай, но я проверю, как мы работаем с вложениями и темой письма при обработке почты через POP3.

Думаю, текущая логика обработки почты пропускает такие письма. Если в теле нет текста, но всё остальное на месте, я получаю:

Email can not be processed: Email::Receiver::NoBodyDetectedError

Я протестировал это, используя пустое multipart-тело Gmail для plain-text и HTML:

Content-Type: multipart/alternative; boundary="00000000000042cfbf05faef451e"

--00000000000042cfbf05faef451e
Content-Type: text/plain; charset="UTF-8"



--00000000000042cfbf05faef451e
Content-Type: text/html; charset="UTF-8"

<div dir="ltr"><br></div>

--00000000000042cfbf05faef451e--
1 лайк

:+1:

Да, я так и думал/ожидал.

В моём случае, похоже, тайм-аут POP3 привёл к пустому письму:

Исключение задачи: Net::ReadTimeout

Трассировка

/usr/local/lib/ruby/3.2.0/net/protocol.rb:229:in `rbuf_fill'
/usr/local/lib/ruby/3.2.0/net/protocol.rb:199:in `readuntil'
/usr/local/lib/ruby/3.2.0/net/protocol.rb:377:in `each_message_chunk'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/net-pop-0.1.2/lib/net/pop.rb:958:in `block in retr'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/net-pop-0.1.2/lib/net/pop.rb:1016:in `critical'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/net-pop-0.1.2/lib/net/pop.rb:956:in `retr'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/net-pop-0.1.2/lib/net/pop.rb:810:in `pop'
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:41:in `block (2 levels) in poll_pop3'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/net-pop-0.1.2/lib/net/pop.rb:669:in `each'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/net-pop-0.1.2/lib/net/pop.rb:669:in `each_mail'
1 лайк

Я внес обновление, чтобы предотвратить ошибку, вызванную is_bounce?.

Существует настройка сайта для отслеживания логов почты:

SiteSetting.log_mail_processing_failures
Вести журнал всех сбоев обработки электронной почты в /logs

Если эта опция включена, ошибка пустого письма всё ещё будет отображаться в логах почты, но не приведёт к сбою задачи, как это происходит в настоящее время. Ссылка на детали коммита для справки:

1 лайк

В логах я вижу эту ошибку, она связана с этим? Похоже, мы не получали письма по POP3 уже несколько дней, и это вызывает множество проблем. Я проверил — в POP3 нет пустых писем. Как мне разблокировать процесс? Я только что обновился до последней версии, но это не помогло.

750194 Невозможно обработать письмо: Email::Receiver::EmptyEmailError

/var/www/discourse/lib/email/processor.rb:183:in `log_email_process_failure' 
/var/www/discourse/lib/email/processor.rb:29:in `rescue in process!' 
/var/www/discourse/lib/email/processor.rb:16:in `process!' 
/var/www/discourse/lib/email/processor.rb:13:in `process!' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:23:in `process_popmail' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:43:in `block (2 levels) in poll_pop3' 
net-pop-0.1.2/lib/net/pop.rb:669:in `each' 
net-pop-0.1.2/lib/net/pop.rb:669:in `each_mail' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:40:in `block in poll_pop3' 
net-pop-0.1.2/lib/net/pop.rb:531:in `start' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:39:in `poll_pop3' 
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:14:in `execute' 
/var/www/discourse/app/jobs/base.rb:249:in `block (2 levels) in perform' 
rails_multisite-4.0.1/lib/rails_multisite/connection_management.rb:80:in `with_connection'
/var/www/discourse/app/jobs/base.rb:236:in `block in perform' 
/var/www/discourse/app/jobs/base.rb:232:in `each' 
/var/www/discourse/app/jobs/base.rb:232:in `perform' 
/var/www/discourse/app/jobs/base.rb:297:in `perform' 
mini_scheduler-0.16.0/lib/mini_scheduler/manager.rb:122:in `process_queue' 
mini_scheduler-0.16.0/lib/mini_scheduler/manager.rb:70:in `worker_loop' 
mini_scheduler-0.16.0/lib/mini_scheduler/manager.rb:59:in `block (2 levels) in ensure_worker_threads' 

Эта тема была автоматически закрыта через 37 часов. Новые ответы больше не принимаются.