【问题标题】:Cannot logout from IMAP server (Ruby)无法从 IMAP 服务器注销 (Ruby)
【发布时间】:2016-07-14 20:16:54
【问题描述】:

我正在使用 Ruby 编写一个从 IMAP 服务器同步邮件的守护进程。我有多个帐户,我一个接一个地登录并下载未读消息。但是,我无法重用与 IMAP 服务器的现有连接。

这是我想要做的一个粗略的例子:

require 'net/imap'

imap = Net::IMAP.new('imap.example.com')

imap.login('login@example.com', 'R2D2C3PO')
imap.select('INBOX')

# interacting with the server, like fetching the messages etc.
# for example:
puts imap.fetch(3, "BODYSTRUCTURE")

# now I want to log out of the account and log in with another
imap.logout

imap.login('anotherlogin@example.com', 'R2D2C3PO')
imap.select('INBOX')    

# again - interacting with the server
puts imap.fetch(3, "BODYSTRUCTURE")

imap.disconnect

但是调用logout 方法时会引发异常:

/usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/monitor.rb:110:in `sleep': No live threads left. Deadlock? (fatal)
        from /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/monitor.rb:110:in `wait'
        from /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/monitor.rb:110:in `wait'
        from /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/imap.rb:1166:in `get_tagged_response'
        from /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/imap.rb:1225:in `block in send_command'
        from /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/monitor.rb:211:in `mon_synchronize'
        from /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/imap.rb:1207:in `send_command'
        from /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/imap.rb:435:in `login'
        from test.rb:13:in `<main>'

我完全被线程异常弄糊涂了,因为守护进程只是单线程的。在引擎盖下,进程在等待服务器响应时挂在条件变量上。为什么调用之前的方法(LOGINSELECT等命令)没有问题,而发送LOGOUT命令时却出现问题?


编辑:

不知何故,我完全错过了这样一个事实,即LOGOUT 命令使与 IMAP 服务器的连接不再可用(正如@HolgerJust 指出的那样)。虽然我重用连接的想法惨遭失败,但重点仍然存在:发送LOGOUT 命令时引发异常,此时仍是合法操作,不应造成任何麻烦。

【问题讨论】:

  • 您的问题似乎是“登录”,而不是“注销”。
  • 我非常怀疑 LOGIN 命令有问题,因为在第一次登录后,我可以毫不费力地下载所有邮件。
  • 对不起,我完全误解了你。是的,这确实是LOGIN 命令的问题。不知何故,我一直坚信问题出在LOGOUT 命令上。我不知道为什么。

标签: ruby imap


【解决方案1】:

从 IMAP 会话中注销后,您必须创建一个新连接才能执行任何其他命令。在 LOGOUT 后,该连接不允许再次使用。

引用RFC 3501:

LOGOUT 命令通知服务器客户端已完成 连接。服务器必须发送一个 BYE 未标记的响应 在(标记的)OK响应之前,然后关闭网络 连接。

在 Ruby 代码中,这实际上意味着在您对 imap 对象调用了 logout 之后,您将无法再对它做任何有用的事情。相反,通过创建一个新的imap 对象来创建一个新的连接。

【讨论】:

  • 啊,现在我错过的这个小事实把我的想法变成了瓦砾!但是,它仍然没有回答我的问题 - 当我实际完成连接并想要清理操场时,LOGOUT 命令仍然会引发异常。附带说明:调用imap.disconnect 方法确实有效,但感觉就像一个肮脏的小黑客。我更愿意通过LOGOUT 命令通知服务器我已完成连接,例如 RFC 标准状态及其预期方式。
  • 第二次调用 login 时引发异常,而不是在堆栈跟踪中显示的 logout 上。可能是您的行号有点偏离。至于你的其他评论,请看我的编辑。
  • 多么尴尬。是的你是对的。我误读了堆栈跟踪并被行号误导。现在一切都合适了。但是,我不太明白您对连接的新评论,即 IMAP 对象在发送新命令时会自动创建新连接。每次断开连接后调用login 方法时,都会出现流关闭的异常。它不会以任何方式重新连接。还是你的意思是别的?
  • 嗯,原来我错过了阅读文档。对此感到抱歉。事实上,在注销或断开连接后,无法使用现有的imap 对象。一旦套接字关闭,重新打开它的唯一方法是创建一个新的imap 对象。因此,我的答案的原始版本仍然有效。
猜你喜欢
  • 2017-09-08
  • 2013-08-28
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-09
  • 2021-10-23
  • 2015-12-13
相关资源
最近更新 更多