修复 offlineimap 无法收邮件的问题

不使用 ssl

.offlineimaprc 配置

ssl = no

offlineimap 收邮件出错

$ offlineimap
...
 Establishing connection to imap.xxxxxx.com:143
 ERROR: Could not connect via SSL to host 'imap.xxxxxx.com' and non-standard ssl port 143 configured. Make sure you connect to the correct port.
...

意外地使用了 ssl 进行连接。

telnet 邮件服务器进行诊断

$ telnet imap.xxxxxx.com 143
Connected to imap.xxxxxx.com.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS] Courier-IMAP ready. Copyright 1998-2011 Double Precision, Inc.  See COPYING for distribution information.

输出的 CAPABILITY 包含 STARTTLS,应该是邮件服务器配置有误

修改 offlineimap 的源代码文件 imapserver.py ,我们的邮箱不使用 tls

269  def __start_tls(self, imapobj):
270          if 'STARTTLS' in imapobj.capabilities and not self.usessl:

改成

269  def __start_tls(self, imapobj):
270          if 'STARTTLS' in imapobj.capabilities and not self.usessl and self.repos.account.name != 'xxxxxx':
  • 更好的做法

    在 imap 协议许可的情况下,加强容错性,tls 连接失败后,使用普通连接重连。 .offlineimaprc 新加禁用 tls 的配置项,警告用户服务器可能配置有误,提示用户禁用 tls。

  • 相关的问题

    Optional TLS by mativs · Pull Request #54 · OfflineIMAP/offlineimap

    有这个问题的 patch,但是没有下文。

  • offlineimap 新加的 starttls 选项解决了这个问题
    commit ac2a547ec46d590d041d410723f90f45fcb802fe
    Author: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
    Date:   Thu Jun 23 03:55:00 2016 +0200
    
    learn to disable STARTTLS
    
    Some servers might have this feature broken.
    
    Github-ref: https://github.com/OfflineIMAP/offlineimap/issues/207
    Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
    

    在 .offlineimaprc 中添加禁用 starttls 配置项

    starttls = no
    

使用 ssl

.offlineimaprc 配置

ssl = yes

offlineimap 收邮件出错

$ offlineimap
...
 Establishing connection to imap.xxxxxx.com:993
 ERROR: Unknown SSL protocol connecting to host 'imap.xxxxxx.com' for repository 'XxxxxxRemote'. OpenSSL responded:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
...

ssl 证书验证失败。

curl 邮件服务器进行诊断

$ curl https://imap.xxxxxx.com:993/
curl: (60) SSL certificate problem: self signed certificate

邮件服务器的 ssl 证书是自签名的

从服务器提取证书

echo | openssl s_client -connect imap.xxxxxx.com:993 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/imap.xxxxxx.com.pem

.offlineimaprc 指定证书

ssl = yes
sslcacertfile = /home/xxxxxxxx/imap.xxxxxx.com.pem

offlineimap 收邮件出错

$ offlineimap
...
 Establishing connection to imap.xxxxxx.com:993
 ERROR: Unknown SSL protocol connecting to host 'imap.xxxxxx.com' for repository 'XxxxxxRemote'. OpenSSL responded:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
...

ssl 证书验证失败。

curl 邮件服务器进行诊断

$ curl https://imap.xxxxxx.com:993/ --cacert /home/xxxxxxxx/imap.xxxxxx.com.pem
curl: (60) SSL certificate problem: certificate has expired

邮件服务器的 ssl 证书已过期。

提取 ssl 证书指纹

$ openssl x509 -noout -in ~/imap.xxxxxx.com.pem -fingerprint -sha1
SHA1 Fingerprint=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX

.offlineimaprc 使用证书指纹(SHA1 Fingerprint= 后的串剔除冒号再转为小写 )

ssl = yes
#sslcacertfile = /home/xxxxxxxx/imap.xxxxxx.com.pem
cert_fingerprint = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

参考 Adding support for multi-fingerprint IMAP servers by Kdecherf · Pull Request #8 · OfflineIMAP/offlineimap

offlineimap 收邮件出错

$ offlineimap
 Establishing connection to imap.xxxxxx.com:993
 ERROR: Unknown SSL protocol connecting to host 'imap.xxxxxx.com' for repository 'XxxxxxRemote'. OpenSSL responded:
[SSL: SSL_NEGATIVE_LENGTH] dh key too small (_ssl.c:590)

邮件服务器的 openssl 可能太老了,生成的 DH KEY 文件只有 768 位不安全,需要重新生成更安全的 KEY 文件。 参考 Ssl error with offlineimap version 6.6.1 (debian package)

使用 ssl 折腾失败,还是邮件服务器配置问题,除非 offlineimap 支持对服务器不进行安全验证,否则服务器端才能解决。