2011-03-08 16 views
5

मैं प्रॉक्सी के माध्यम से ईमेल भेजना चाहता हूं।पायथन smtplib प्रॉक्सी समर्थन

मेरा वर्तमान कार्यान्वयन निम्नानुसार है।

मैं प्रमाणीकरण के साथ smtp सर्वर से कनेक्शन करता हूं। सफलतापूर्वक लॉग इन करने के बाद मैं एक ईमेल भेजता हूं। यह ठीक काम करता है लेकिन जब मैं ईमेल हेडर देखता हूं तो मैं अपना होस्ट नाम देख सकता हूं। मैं इसे प्रॉक्सी के माध्यम से सुरंग करना चाहता हूं।

किसी भी मदद की अत्यधिक सराहना की जाएगी।

उत्तर

4

मुझे कल भी इसी तरह की समस्या थी, यह वह समस्या है जिसे मैंने समस्या हल करने के लिए लिखा था। यह अदृश्य रूप से आपको प्रॉक्सी के माध्यम से सभी 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 
+1

ईमेल भेजना प्रतीत नहीं होता है, यह बस वहां बैठता है और लटकता है। कुछ अलग प्रॉक्सी के साथ भी कोशिश की। – Sinista

+1

जैसा कि @ सिनिस्टा कहता है, आपका कोड काम नहीं करता है, बल्कि यह वहां बस बैठता है और लटकता है। मैंने इसे ठीक करने की स्वतंत्रता ली है, इसलिए अब यह मेरे लिए ठीक काम कर रहा है। [मेरा जवाब देखें] (http://stackoverflow.com/a/31348278/3718878)। – Zenadix

-1

smtplib मॉड्यूल एक HTTP प्रॉक्सी के माध्यम से एक SMTP सर्वर से कनेक्ट करने के लिए कार्यक्षमता शामिल नहीं है। custom class posted by ryoh मेरे लिए काम नहीं किया, जाहिर है क्योंकि मेरे HTTP प्रॉक्सी केवल एन्कोड किए गए संदेश प्राप्त करता है। मैंने रियो के कोड के आधार पर निम्नलिखित कस्टम क्लास लिखा है, और यह ठीक काम कर रहा है।

import smtplib 
import socket 

def recvline(sock): 
    """Receives a line.""" 
    stop = 0 
    line = '' 
    while True: 
     i = sock.recv(1) 
     if i.decode('UTF-8') == '\n': stop = 1 
     line += i.decode('UTF-8') 
     if stop == 1: 
      print('Stop reached.') 
      break 
    print('Received line: %s' % line) 
    return line 

class ProxySMTP(smtplib.SMTP): 
    """Connects to a SMTP server through a HTTP proxy.""" 

    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 IOError(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 to use the SMTP connect code 
     # and just alter the socket connection bit. 
     print('Will connect to:', (host, port)) 
     print('Connect to proxy.') 
     new_socket = socket.create_connection((self.p_address,self.p_port), timeout) 

     s = "CONNECT %s:%s HTTP/1.1\r\n\r\n" % (port,host) 
     s = s.encode('UTF-8') 
     new_socket.sendall(s) 

     print('Sent CONNECT. Receiving lines.') 
     for x in range(2): recvline(new_socket) 

     print('Connected.') 
     return new_socket 

SMTP सर्वर से कनेक्ट करने के लिए, बस smtplib.SMTP के बजाय वर्ग ProxySMTP का उपयोग करें।

proxy_host = YOUR_PROXY_HOST 
proxy_port = YOUR_PROXY_PORT 

# Both port 25 and 587 work for SMTP 
conn = ProxySMTP(host='smtp.gmail.com', port=587, 
       p_address=proxy_host, p_port=proxy_port) 

conn.ehlo() 
conn.starttls() 
conn.ehlo() 

r, d = conn.login(YOUR_EMAIL_ADDRESS, YOUR_PASSWORD) 

print('Login reply: %s' % r) 

sender = '[email protected]' 
receivers = ['[email protected]'] 

message = """From: From Person <[email protected]> 
To: To Person <[email protected]> 
Subject: SMTP e-mail test 

This is a test e-mail message. 
""" 

print('Send email.') 
conn.sendmail(sender, receivers, message) 

print('Success.') 
conn.close() 
+0

त्रुटि 220 क्या है? कोड IOError को बढ़ा रहा है, प्राप्त लाइन: HTTP/1.1 412 प्रीकंडीशन विफल, प्राप्त लाइन: कैश-कंट्रोल: नो-कैश, IOError: [Errno -1] ma: no-cache –

+0

आपका कोड काम नहीं कर रहा है। GIving त्रुटि - विशेषताएँ त्रुटि: ProxySMTP इंस्टेंस में कोई विशेषता नहीं है 'local_hostname' –

0

यह कोड मुझसे अर्जित किया गया है। 1. फ़ाइल का नाम ईमेल नहीं होना चाहिए फ़ाइल नाम का नाम बदलें उदाहरण के लिए ईमेल Send.py 2. Google को अविश्वसनीय स्रोतों से संदेश भेजने की अनुमति देना आवश्यक है।

संबंधित मुद्दे