Email::Processor 不应以 mail=nil 调用

我的错误日志充满了这些消息:

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

Backtrace:
/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' 

我想知道 @receiverdiscourse/lib/email/processor.rb at 84f590ab83b90d4c6754e247744567f75274fb69 · discourse/discourse · GitHub 中是如何变成 nil 的。

1 个赞

我目前的理解是,Email::Processor.process! 使用 mail=nil 调用 Email::Receiver.new,这会引发一个 Email::Receiver.EmptyEmailError,导致 @receiver 未定义。

接下来的 rescue 部分期望一个已初始化的 @receiver

难道不应该在调用 Email::Processor.initialize 时传入 mail==nil 时引发某种错误吗?

我的猜测是 :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 个赞

谢谢,这封邮件似乎是由第三方(腾讯/中国)生成的。我查看了邮件头,发现了一些不寻常的地方(我在下面高亮了有趣的部分)。邮件完全没有正文,但它似乎是对发送到该 qq 邮箱的邮件的自动回复。

我快速搜索了 X-QQ-MIME,发现许多其他网站在处理来自 qq.com 地址的邮件时也遇到了类似的问题。

我认为我们可以安全地跳过任何不包含邮件正文的邮件。我们可以对其进行静默记录,并防止错误被引发。

From: "=?utf-8?B?YWJjYzEwMDQwNTA3?=" <abcc10040507@qq.com>
Subject: =?utf-8?B?6Ieq5Yqo5Zue5aSNOiBGb2N1cyBhbmQgRmxvYXQg?=\n =?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 标头字段在检测自动生成的电子邮件的机制引发错误之前被识别。

此外,您可能仍然希望通过执行 Sam 建议 的操作来解决此特定错误。

我 base64 解码了邮件主题,得到:
你好,我是Focus and Flat Agile 17

我认为这是由于中文字符,它们在发送前被 base64 编码了。这解释了发件人姓名和主题的乱码格式。

我希望现有的逻辑已经处理了这个问题,但我会检查一下我们在处理 pop3 邮件时是如何处理附件和邮件主题的。

我认为这会被当前的邮件处理逻辑跳过。当正文中没有文本但其他一切都到位时,我会得到:

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

我通过使用空的 Gmail 多部分正文(纯文本和 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 超时导致了空邮件:

Job exception: Net::ReadTimeout

Backtrace

/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 小时后自动关闭。不再允许回复。