PySocks
PySocks copied to clipboard
wrapmodule affects not just the wrapped module
wrapmodule is defined simply as:
https://github.com/Anorov/PySocks/blob/c2fa43cbe1091e799e248e8e4433978916791a8b/socks.py#L146
However, that will affect not just the socket function as it is visible from the module, but from everywhele else as well. Therefore, e.g. socks.wrapmodule(smtplib) will affect the entire application.
Same issue here. Is there any other method to wrap a single module ?
I've figured out something :
class PatchedSocketModule:
def __init__(self, proxy_type, proxy_host, proxy_port, proxy_user, proxy_password):
"""
Initialize an SMTP proxy configuration container.
Args:
proxy_type (str): Type of proxy (e.g., 'http', 'socks4', 'socks5')
proxy_host (str): Hostname or IP address of the proxy server
proxy_port (int): Port number for the proxy server
proxy_user (str): Username for proxy authentication (optional)
proxy_password (str): Password for proxy authentication (optional)
"""
self.proxy_type = proxy_type
self.proxy_host = proxy_host
self.proxy_port = proxy_port
self.proxy_user = proxy_user
self.proxy_password = proxy_password
def create_connection_patched(self, *args, **kwargs):
"""Patched version of socket.create_connection that routes through proxy."""
return socks.create_connection(
*args, **kwargs,
proxy_type=self.proxy_type,
proxy_addr=self.proxy_host,
proxy_port=self.proxy_port,
proxy_username=self.proxy_user,
proxy_password=self.proxy_password,
)
def __getattr__(self, name):
if name == 'socket':
return socks.socksocket
if name == 'create_connection':
return self.create_connection_patched
return getattr(socket, name)
def configure_smtp_proxy(proxy_type, proxy_host, proxy_port, proxy_user, proxy_password):
"""Configures the global SMTP proxy settings."""
if not hasattr(configure_smtp_proxy, 'configured'):
socks.setdefaultproxy(proxy_type, proxy_host, proxy_port, username=proxy_user, password=proxy_password)
p = patch('smtplib.socket', PatchedSocketModule(proxy_type, proxy_host, proxy_port, proxy_user, proxy_password))
p.start()
configure_smtp_proxy.configured = True
It's not pretty but it works