Python smtplib代理支持

Sin*_*sta 9 python proxy smtp smtplib

我想通过代理发送电子邮件.

我目前的实施如下:

我通过身份验证连接到smtp服务器.我成功登录后,发送电子邮件.它工作正常,但当我看到电子邮件标题时,我可以看到我的主机名.我想通过代理隧道它.

任何帮助将受到高度赞赏.

小智 9

使用SocksiPy:

import smtplib
import socks

#'proxy_port' should be an integer
#'PROXY_TYPE_SOCKS4' can be replaced to HTTP or PROXY_TYPE_SOCKS5
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4, proxy_host, proxy_port)
socks.wrapmodule(smtplib)

smtp = smtplib.SMTP()
...
Run Code Online (Sandbox Code Playgroud)

  • 正式版不适用于此.请改用[this](https://code.google.com/p/socksipy-branch/).同样的事情,只是一个分叉 (3认同)
  • 2019 更新:SocksPy 有点过时,请使用 [PySocks](https://github.com/Anorov/PySocks) 代替。`pip install pysocks` 另请注意,尝试通过 HTTP 代理使用 SMTP 通常是不可能的,必须获得 SOCKS 代理。我个人使用 Tor,您可以在[此处](https://www.sylvaindurand.org/use-tor-with-python/)阅读如何设置 Torocks 代理。PySocks 有一个非常有用的函数,称为“create_connection”,它使得修补 smtplib 以与代理一起使用非常容易。只需查看 [smtplib](https://github.com/python/cpython/blob/3.7/Lib/smtplib.py) 中的 `_get_socket` 即可。 (2认同)
  • 因为我遇到了它并且没有在这里看到它: `socks.warpmodule(smtplib)` 具有其他库也被修补的副作用(例如 `requests`)。更好的方法是不进行猴子补丁,就像@mkerrig所说,查看“SMTP._get_socket”并使用“socks.create_connection”。 (2认同)

ryo*_*yoh 5

我昨天也遇到了类似的问题,这是我为解决问题而编写的代码。它无形地允许您通过代理使用所有 smtp 方法。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#       smtprox.py
#       Shouts to suidrewt
#
# ############################################# #
# This module allows Proxy support in MailFux.  #
# Shouts to Betrayed for telling me about       #
# http CONNECT                                  #
# ############################################# #

import smtplib
import socket

def recvline(sock):
    stop = 0
    line = ''
    while True:
        i = sock.recv(1)
        if i == '\n': stop = 1
        line += i
        if stop == 1:
            break
    return line

class ProxSMTP( smtplib.SMTP ):

    def __init__(self, host='', port=0, p_address='',p_port=0, local_hostname=None,
             timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
        """Initialize a new instance.

        If specified, `host' is the name of the remote host to which to
        connect.  If specified, `port' specifies the port to which to connect.
        By default, smtplib.SMTP_PORT is used.  An SMTPConnectError is raised
        if the specified `host' doesn't respond correctly.  If specified,
        `local_hostname` is used as the FQDN of the local host.  By default,
        the local hostname is found using socket.getfqdn().

        """
        self.p_address = p_address
        self.p_port = p_port

        self.timeout = timeout
        self.esmtp_features = {}
        self.default_port = smtplib.SMTP_PORT
        if host:
            (code, msg) = self.connect(host, port)
            if code != 220:
                raise SMTPConnectError(code, msg)
        if local_hostname is not None:
            self.local_hostname = local_hostname
        else:
            # RFC 2821 says we should use the fqdn in the EHLO/HELO verb, and
            # if that can't be calculated, that we should use a domain literal
            # instead (essentially an encoded IP address like [A.B.C.D]).
            fqdn = socket.getfqdn()
            if '.' in fqdn:
                self.local_hostname = fqdn
            else:
                # We can't find an fqdn hostname, so use a domain literal
                addr = '127.0.0.1'
                try:
                    addr = socket.gethostbyname(socket.gethostname())
                except socket.gaierror:
                    pass
                self.local_hostname = '[%s]' % addr
        smtplib.SMTP.__init__(self)

    def _get_socket(self, port, host, timeout):
        # This makes it simpler for SMTP_SSL to use the SMTP connect code
        # and just alter the socket connection bit.
        if self.debuglevel > 0: print>>stderr, 'connect:', (host, port)
        new_socket = socket.create_connection((self.p_address,self.p_port), timeout)
        new_socket.sendall("CONNECT {0}:{1} HTTP/1.1\r\n\r\n".format(port,host))
        for x in xrange(2): recvline(new_socket)
        return new_socket
Run Code Online (Sandbox Code Playgroud)

  • 正如@Sinista 所说,你的代码不起作用,它只是坐在那里挂起。我已经自行修复了它,所以现在它对我来说工作得很好。[查看我的答案](http://stackoverflow.com/a/31348278/3718878)。 (2认同)