We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Some people asked how to connect to IMAP via proxy. I suggest to use python-socks package for this purpose. Thanks to the author for helping with it.
import asyncio from dataclasses import dataclass import ssl from typing import Callable, Literal from aioimaplib.aioimaplib import ( IMAP4, IMAP4ClientProtocol, ) from python_socks.async_.asyncio import Proxy from python_socks._errors import ProxyConnectionError, ProxyError, ProxyTimeoutError from python_socks._types import ProxyType class EmailError(Exception): pass class EmailProxyError(EmailError): def __init__(self) -> None: super().__init__(f'IMAP proxy error') @dataclass(kw_only=True) class ProxySchema: proto: Literal['http', 'socks4', 'socks5'] host: str port: int username: str | None password: str | None class ImapProxyClient(IMAP4): def __init__( self, *, host: str, port: int, loop: asyncio.AbstractEventLoop | None = None, timeout: float = 30, proxy: ProxySchema | None = None ): self._proxy = proxy self._loop = loop or asyncio.get_running_loop() super().__init__(host, port, self._loop, timeout) @property def sock_type(self) -> ProxyType | None: if not hasattr(self, '_sock_type'): if self._proxy is None: self._sock_type = None else: protos = { 'http': ProxyType.HTTP, 'socks4': ProxyType.SOCKS4, 'socks5': ProxyType.SOCKS5 } self._sock_type = protos.get(self._proxy.proto.lower()) return self._sock_type def create_client( self, host: str, port: int, loop: asyncio.AbstractEventLoop | None = None, conn_lost_cb: Callable[[Exception | None], None] = None, # type: ignore ssl_context: ssl.SSLContext | None = None ) -> None: self.protocol = IMAP4ClientProtocol(self._loop, conn_lost_cb) if self._proxy and self.sock_type: self._loop.create_task(self._proxy_connect(loop or self._loop, lambda: self.protocol, ssl_context)) else: self._loop.create_task(self._loop.create_connection( lambda: self.protocol, host, port, ssl=ssl_context )) async def _proxy_connect( self, loop: asyncio.AbstractEventLoop, protocol_factory, ssl_context: ssl.SSLContext | None = None ): if self._proxy and self.sock_type: proxy = Proxy.create( proxy_type=self.sock_type, host=self._proxy.host, port=self._proxy.port, username=self._proxy.username, password=self._proxy.password, loop=loop ) try: sock = await proxy.connect(self.host, self.port, timeout=self.timeout) except (ProxyError, ProxyConnectionError, ProxyTimeoutError): raise EmailProxyError() await loop.create_connection( protocol_factory, sock=sock, ssl=ssl_context, server_hostname=self.host if ssl_context else None ) class ImapSslProxyClient(ImapProxyClient): def __init__( self, *, host: str, port: int, timeout: float = 30, proxy: ProxySchema | None = None ): super().__init__( host=host, port=port, timeout=timeout, proxy=proxy ) def create_client( self, host: str, port: int, loop: asyncio.AbstractEventLoop | None = None, conn_lost_cb: Callable[[Exception | None], None] = None, # type: ignore ssl_context: ssl.SSLContext | None = None ) -> None: if ssl_context is None: ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) super().create_client(host, port, loop or self._loop, conn_lost_cb, ssl_context) async def test(): proxy = ProxySchema(proto='socks5', host='127.0.0.1', port=123, username=None, password=None) client = ImapSslProxyClient(host='host.imap.com', port=993, timeout=10, proxy=proxy) await client.wait_hello_from_server() await client.login('user', 'password') await client.select() res = await client.search('(ALL)') print(res) asyncio.run(test())
The text was updated successfully, but these errors were encountered:
No branches or pull requests
Some people asked how to connect to IMAP via proxy. I suggest to use python-socks package for this purpose. Thanks to the author for helping with it.
The text was updated successfully, but these errors were encountered: