Exemple #1
0
    async def open_uds_stream(
        self,
        path: str,
        hostname: bytes,
        ssl_context: Optional[SSLContext],
        timeout: TimeoutDict,
    ) -> AsyncSocketStream:
        connect_timeout = timeout.get("connect")
        unicode_host = hostname.decode("utf-8")
        exc_map = {
            TimeoutError: ConnectTimeout,
            OSError: ConnectError,
            BrokenResourceError: ConnectError,
        }

        with map_exceptions(exc_map):
            async with maybe_async_cm(anyio.fail_after(connect_timeout)):
                stream: anyio.abc.ByteStream = await anyio.connect_unix(path)
                if ssl_context:
                    stream = await TLSStream.wrap(
                        stream,
                        hostname=unicode_host,
                        ssl_context=ssl_context,
                        standard_compatible=False,
                    )

        return SocketStream(stream=stream)
Exemple #2
0
 async def read(self, n: int, timeout: TimeoutDict) -> bytes:
     read_timeout = timeout.get("read")
     async with self.read_lock:
         try:
             async with maybe_async_cm(anyio.fail_after(read_timeout)):
                 return await self.stream.receive(n)
         except TimeoutError:
             raise ReadTimeout from None
         except BrokenResourceError as exc:
             raise ReadError from exc
         except EndOfStream:
             raise ReadError("Server disconnected while attempting read") from None
Exemple #3
0
    async def write(self, data: bytes, timeout: TimeoutDict) -> None:
        if not data:
            return

        write_timeout = timeout.get("write")
        async with self.write_lock:
            try:
                async with maybe_async_cm(anyio.fail_after(write_timeout)):
                    return await self.stream.send(data)
            except TimeoutError:
                raise WriteTimeout from None
            except BrokenResourceError as exc:
                raise WriteError from exc
Exemple #4
0
    async def _flush_output(self) -> None:
        if not self._stream:
            raise SMTPException('Not connected')

        data = self._protocol.get_outgoing_data()
        if data:
            logger.debug('Sent: %s', data)
            try:
                async with maybe_async_cm(fail_after(self.timeout)):
                    await self._stream.send(data)
            except (BrokenResourceError, TimeoutError):
                await aclose_forcefully(self._stream)
                self._stream = None
                raise
Exemple #5
0
    async def start_tls(
        self,
        hostname: bytes,
        ssl_context: SSLContext,
        timeout: TimeoutDict,
    ) -> "SocketStream":
        connect_timeout = timeout.get("connect")
        try:
            async with maybe_async_cm(anyio.fail_after(connect_timeout)):
                ssl_stream = await TLSStream.wrap(
                    self.stream,
                    ssl_context=ssl_context,
                    hostname=hostname.decode("ascii"),
                )
        except TimeoutError:
            raise ConnectTimeout from None
        except BrokenResourceError as exc:
            raise ConnectError from exc

        return SocketStream(ssl_stream)
Exemple #6
0
    async def connect(self) -> None:
        """Connect to the SMTP server."""
        if not self._stream:
            async with maybe_async_cm(fail_after(self.connect_timeout)):
                self._stream = await connect_tcp(self.host, self.port)

            try:
                await self._wait_response()
                await self._send_command(self._protocol.send_greeting, self.domain)

                # Do the TLS handshake if supported by the server
                if 'STARTTLS' in self._protocol.extensions:
                    await self._send_command(self._protocol.start_tls)
                    self._stream = await TLSStream.wrap(self._stream, hostname=self.host,
                                                        ssl_context=self.ssl_context,
                                                        standard_compatible=False)

                    # Send a new EHLO command to determine new capabilities
                    await self._send_command(self._protocol.send_greeting, self.domain)

                # Use the authenticator if one was provided
                if self.authenticator:
                    auth_gen = self.authenticator.authenticate()
                    try:
                        auth_data = await auth_gen.__anext__()
                        response = await self._send_command(
                            self._protocol.authenticate, self.authenticator.mechanism, auth_data)
                        while self._protocol.state is ClientState.authenticating:
                            auth_data = await auth_gen.asend(response.message)
                            self._protocol.send_authentication_data(auth_data)
                            await self._flush_output()
                    except StopAsyncIteration:
                        pass
                    finally:
                        await auth_gen.aclose()
            except BaseException:
                await aclose_forcefully(self)
                self._stream = None
                raise
Exemple #7
0
    async def _wait_response(self) -> SMTPResponse:
        while True:
            if not self._stream:
                raise SMTPException('Not connected')

            if self._protocol.needs_incoming_data:
                try:
                    async with maybe_async_cm(fail_after(self.timeout)):
                        data = await self._stream.receive()
                except (BrokenResourceError, TimeoutError):
                    await aclose_forcefully(self._stream)
                    self._stream = None
                    raise

                logger.debug('Received: %s', data)
                response = self._protocol.feed_bytes(data)
                if response:
                    if response.is_error():
                        response.raise_as_exception()
                    else:
                        return response

                await self._flush_output()
Exemple #8
0
async def test_maybe_async_cm() -> None:
    async with maybe_async_cm(CancelScope()):
        pass
Exemple #9
0
    async def acquire(self, timeout: float = None) -> None:
        async with maybe_async_cm(anyio.move_on_after(timeout)):
            await self.semaphore.acquire()
            return

        raise self.exc_class()
Exemple #10
0
async def test_maybe_async_cm():
    async with maybe_async_cm(open_cancel_scope()):
        pass