如何通过代理获取POP或IMAP电子邮件?

12

无论是poplib还是imaplib似乎都不支持代理,并且尽管我尝试了谷歌搜索,但找不到太多关于它的信息。

我正在使用Python从各种启用了IMAP / POP的服务器中获取电子邮件,并需要能够通过代理执行此操作。

理想情况下,我希望能够直接在Python中完成,但如果找不到更好的解决方法,则使用一个包装器(基于OSX的外部程序/脚本)来强制所有流量经过代理可能已足够。

有人能帮帮我吗? 我想象不出我是唯一需要在Python中通过代理获取电子邮件的人...

**编辑标题以去除HTTP,因为我累时不应该输入得那么快,对此感到抱歉**

我计划使用的代理允许socks代理,除了http之外还可以。

通过http工作的Pop或Imap并没有太多意义(有状态vs无状态),但我的理解是socks将允许我做我想做的事情。

到目前为止,实现我想要的唯一方法似乎是肮脏地黑进imaplib... 如果可以避免最好不要这样做。


1
我很好奇:即使没有Python,你如何通过HTTP代理隧道IMAP? - user3850
从标题中删除了Http,我的错误,应该是socks... - Vermillon
3个回答

14

你不需要通过肮脏的hack imaplib。你可以尝试使用SocksiPy包,该包支持socks4、socks5和http代理(connect):

像这样,显然你想通过额外的参数来更好地处理setproxy选项,例如自定义__init__方法等。

from imaplib import IMAP4, IMAP4_SSL, IMAP4_PORT, IMAP4_SSL_PORT
from socks import sockssocket, PROXY_TYPE_SOCKS4, PROXY_TYPE_SOCKS5, PROXY_TYPE_HTTP

class SocksIMAP4(IMAP4):
    def open(self,host,port=IMAP4_PORT):
        self.host = host
        self.port = port
        self.sock = sockssocket()
        self.sock.setproxy(PROXY_TYPE_SOCKS5,'socks.example.com')
        self.sock.connect((host,port))
        self.file = self.sock.makefile('rb')

你可以使用IMAP4_SSL进行类似操作。只需注意将其包装到SSL套接字中即可。

import ssl

class SocksIMAP4SSL(IMAP4_SSL):
    def open(self, host, port=IMAP4_SSL_PORT):
        self.host = host
        self.port = port
        #actual privoxy default setting, but as said, you may want to parameterize it
        self.sock = create_connection((host, port), PROXY_TYPE_HTTP, "127.0.0.1", 8118)
        self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile)
        self.file = self.sslobj.makefile('rb')

很好的发现,MattH,这正是我在寻找的东西(不知道SocksiPy)。我会试一试。谢谢。 - Vermillon
@rafael-t,请问你的代码中create_connection()方法是什么?它实现在哪里了? - Vsevolod Timchenko
1
@ВсеволодТимченко:那个完善的 SSL 实现是由 Rafael T 添加的,我不确定他所暗示的“create_connection”来自哪里。 - MattH
1
@MattH 是的,我试图与 Rafael 联系,但 SOF 引擎显然不支持寻址已进行编辑的人。我想这个问题来自 PySocks(第150行)。这个方法应该是 socks.create_connection。谢谢回复。还有一个问题是,在包装后,self.sock 会关闭。 - Vsevolod Timchenko
在Socks中没有SocksSocket。 - Jimmy Engelbrecht
create_connection函数的参数与socks中的create_connection函数不匹配。 - Jimmy Engelbrecht

7

回答我的问题...... 有一个快速而简单的方法,可以在不费力的情况下使用Socksipy强制将Python脚本中的流量通过代理传输(感谢MattH指出这一点)。

import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4,proxy_ip,port,True)
socket.socket = socks.socksocket

那个全局套接字覆盖显然有点粗暴,但是作为一个快速解决方案,可以在我找到时间适当地子类化IMAP4和IMAP4_SSL之前使用。


对我没用,我得到了“IOError:[Errno socket error]('timed out',)”,有什么建议吗? - ImadOS

2
如果我理解正确的话,您试图把方形钉子放进圆孔里。
HTTP代理只知道如何“说”HTTP,因此无法直接连接到POP或IMAP服务器。
如果您想这样做,您需要在某个地方实现自己的服务器来与邮件服务器进行通信。它将接收HTTP请求,然后进行适当的调用以与邮件服务器通信。例如:

这会有多实用我不知道,因为你需要将一个有状态的协议转换成一个无状态的协议。

你是完全正确的,我忘了提到socks的能力。我已经从标题中去掉了HTTP,对此我很抱歉,我有点累了 ;p - Vermillon
3
HTTP代理的“CONNECT”方法能让你运行任何TCP客户端->服务器协议。 如果 HTTP代理允许,大多数默认配置将“CONNECT”请求限制在443端口上。 - MattH
我理解你的意思,但是Thunderbird如何通过HTTP代理连接呢? - user1181004

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接