# Path: aiosmtplib/compat.py
# async def start_tls(
#     loop: asyncio.AbstractEventLoop,
#     transport: asyncio.Transport,
#     protocol: asyncio.Protocol,
#     sslcontext: ssl.SSLContext,
#     server_side: bool = False,
#     server_hostname: Optional[str] = None,
#     ssl_handshake_timeout: Optional[Union[float, int]] = None,
# ) -> asyncio.Transport:
#     # We use hasattr here, as uvloop also supports start_tls.
#     if hasattr(loop, "start_tls"):
#         return await loop.start_tls(  # type: ignore
#             transport,
#             protocol,
#             sslcontext,
#             server_side=server_side,
#             server_hostname=server_hostname,
#             ssl_handshake_timeout=ssl_handshake_timeout,
#         )
# 
#     waiter = loop.create_future()
#     ssl_protocol = SSLProtocol(
#         loop, protocol, sslcontext, waiter, server_side, server_hostname
#     )
# 
#     # Pause early so that "ssl_protocol.data_received()" doesn't
#     # have a chance to get called before "ssl_protocol.connection_made()".
#     transport.pause_reading()
# 
#     # Use set_protocol if we can
#     if hasattr(transport, "set_protocol"):
#         transport.set_protocol(ssl_protocol)
#     else:
#         transport._protocol = ssl_protocol  # type: ignore
# 
#     conmade_cb = loop.call_soon(ssl_protocol.connection_made, transport)
#     resume_cb = loop.call_soon(transport.resume_reading)
# 
#     try:
#         await asyncio.wait_for(waiter, timeout=ssl_handshake_timeout)
#     except Exception:
#         transport.close()
#         conmade_cb.cancel()
#         resume_cb.cancel()
#         raise
# 
#     return ssl_protocol._app_transport
# 
# Path: aiosmtplib/errors.py
# class SMTPDataError(SMTPResponseException):
#     """
#     Server refused DATA content.
#     """
# 
# class SMTPReadTimeoutError(SMTPTimeoutError):
#     """
#     A timeout occurred while waiting for a response from the SMTP server.
#     """
# 
# class SMTPResponseException(SMTPException):
#     """
#     Base class for all server responses with error codes.
#     """
# 
#     def __init__(self, code: int, message: str) -> None:
#         self.code = code
#         self.message = message
#         self.args = (code, message)
# 
# class SMTPServerDisconnected(SMTPException, ConnectionError):
#     """
#     The connection was lost unexpectedly, or a command was run that requires
#     a connection.
#     """
# 
# class SMTPTimeoutError(SMTPException, TimeoutError):
#     """
#     A timeout occurred while performing a network operation.
#     """
# 
# Path: aiosmtplib/response.py
# class SMTPResponse(BaseResponse):
#     """
#     NamedTuple of server response code and server response message.
# 
#     ``code`` and ``message`` can be accessed via attributes or indexes:
# 
#         >>> response = SMTPResponse(200, "OK")
#         >>> response.message
#         'OK'
#         >>> response[0]
#         200
#         >>> response.code
#         200
# 
#     """
# 
#     __slots__ = ()
# 
#     def __repr__(self) -> str:
#         return "({self.code}, {self.message})".format(self=self)
# 
#     def __str__(self) -> str:
#         return "{self.code} {self.message}".format(self=self)
# 
# Path: aiosmtplib/status.py
# class SMTPStatus(enum.IntEnum):
#     """
#     Defines SMTP statuses for code readability.
# 
#     See also: http://www.greenend.org.uk/rjk/tech/smtpreplies.html
#     """
# 
#     invalid_response = -1
#     system_status_ok = 211
#     help_message = 214
#     ready = 220
#     closing = 221
#     auth_successful = 235
#     completed = 250
#     will_forward = 251
#     cannot_vrfy = 252
#     auth_continue = 334
#     start_input = 354
#     domain_unavailable = 421
#     mailbox_unavailable = 450
#     error_processing = 451
#     insufficient_storage = 452
#     tls_not_available = 454
#     unrecognized_command = 500
#     unrecognized_parameters = 501
#     command_not_implemented = 502
#     bad_command_sequence = 503
#     parameter_not_implemented = 504
#     domain_does_not_accept_mail = 521
#     access_denied = 530  # Sendmail specific
#     auth_failed = 535
#     mailbox_does_not_exist = 550
#     user_not_local = 551
#     storage_exceeded = 552
#     mailbox_name_invalid = 553
#     transaction_failed = 554
#     syntax_error = 555


import asyncio
import re
import ssl
from typing import Callable, Optional, cast
from .compat import start_tls
from .errors import (
    SMTPDataError,
    SMTPReadTimeoutError,
    SMTPResponseException,
    SMTPServerDisconnected,
    SMTPTimeoutError,
)
from .response import SMTPResponse
from .status import SMTPStatus
        return response

    async def execute_data_command(
        self, message: bytes, timeout: Optional[float] = None
    ) -> SMTPResponse:
        """
        Sends an SMTP DATA command to the server, followed by encoded message content.

        Automatically quotes lines beginning with a period per RFC821.
        Lone \\\\r and \\\\n characters are converted to \\\\r\\\\n
        characters.
        """
        if self._command_lock is None:
            raise SMTPServerDisconnected("Server not connected")

        message = LINE_ENDINGS_REGEX.sub(b"\r\n", message)
        message = PERIOD_REGEX.sub(b"..", message)
        if not message.endswith(b"\r\n"):
            message += b"\r\n"
        message += b".\r\n"

        async with self._command_lock:
            self.write(b"DATA\r\n")
            start_response = await self.read_response(timeout=timeout)
            if start_response.code != SMTPStatus.start_input:
                raise SMTPDataError(start_response.code, start_response.message)

            self.write(message)
            response = await self.read_response(timeout=timeout)
            if response.code != SMTPStatus.completed:

# Path: aiosmtplib/compat.py
# async def start_tls(
#     loop: asyncio.AbstractEventLoop,
#     transport: asyncio.Transport,
#     protocol: asyncio.Protocol,
#     sslcontext: ssl.SSLContext,
#     server_side: bool = False,
#     server_hostname: Optional[str] = None,
#     ssl_handshake_timeout: Optional[Union[float, int]] = None,
# ) -> asyncio.Transport:
#     # We use hasattr here, as uvloop also supports start_tls.
#     if hasattr(loop, "start_tls"):
#         return await loop.start_tls(  # type: ignore
#             transport,
#             protocol,
#             sslcontext,
#             server_side=server_side,
#             server_hostname=server_hostname,
#             ssl_handshake_timeout=ssl_handshake_timeout,
#         )
# 
#     waiter = loop.create_future()
#     ssl_protocol = SSLProtocol(
#         loop, protocol, sslcontext, waiter, server_side, server_hostname
#     )
# 
#     # Pause early so that "ssl_protocol.data_received()" doesn't
#     # have a chance to get called before "ssl_protocol.connection_made()".
#     transport.pause_reading()
# 
#     # Use set_protocol if we can
#     if hasattr(transport, "set_protocol"):
#         transport.set_protocol(ssl_protocol)
#     else:
#         transport._protocol = ssl_protocol  # type: ignore
# 
#     conmade_cb = loop.call_soon(ssl_protocol.connection_made, transport)
#     resume_cb = loop.call_soon(transport.resume_reading)
# 
#     try:
#         await asyncio.wait_for(waiter, timeout=ssl_handshake_timeout)
#     except Exception:
#         transport.close()
#         conmade_cb.cancel()
#         resume_cb.cancel()
#         raise
# 
#     return ssl_protocol._app_transport
# 
# Path: aiosmtplib/errors.py
# class SMTPDataError(SMTPResponseException):
#     """
#     Server refused DATA content.
#     """
# 
# class SMTPReadTimeoutError(SMTPTimeoutError):
#     """
#     A timeout occurred while waiting for a response from the SMTP server.
#     """
# 
# class SMTPResponseException(SMTPException):
#     """
#     Base class for all server responses with error codes.
#     """
# 
#     def __init__(self, code: int, message: str) -> None:
#         self.code = code
#         self.message = message
#         self.args = (code, message)
# 
# class SMTPServerDisconnected(SMTPException, ConnectionError):
#     """
#     The connection was lost unexpectedly, or a command was run that requires
#     a connection.
#     """
# 
# class SMTPTimeoutError(SMTPException, TimeoutError):
#     """
#     A timeout occurred while performing a network operation.
#     """
# 
# Path: aiosmtplib/response.py
# class SMTPResponse(BaseResponse):
#     """
#     NamedTuple of server response code and server response message.
# 
#     ``code`` and ``message`` can be accessed via attributes or indexes:
# 
#         >>> response = SMTPResponse(200, "OK")
#         >>> response.message
#         'OK'
#         >>> response[0]
#         200
#         >>> response.code
#         200
# 
#     """
# 
#     __slots__ = ()
# 
#     def __repr__(self) -> str:
#         return "({self.code}, {self.message})".format(self=self)
# 
#     def __str__(self) -> str:
#         return "{self.code} {self.message}".format(self=self)
# 
# Path: aiosmtplib/status.py
# class SMTPStatus(enum.IntEnum):
#     """
#     Defines SMTP statuses for code readability.
# 
#     See also: http://www.greenend.org.uk/rjk/tech/smtpreplies.html
#     """
# 
#     invalid_response = -1
#     system_status_ok = 211
#     help_message = 214
#     ready = 220
#     closing = 221
#     auth_successful = 235
#     completed = 250
#     will_forward = 251
#     cannot_vrfy = 252
#     auth_continue = 334
#     start_input = 354
#     domain_unavailable = 421
#     mailbox_unavailable = 450
#     error_processing = 451
#     insufficient_storage = 452
#     tls_not_available = 454
#     unrecognized_command = 500
#     unrecognized_parameters = 501
#     command_not_implemented = 502
#     bad_command_sequence = 503
#     parameter_not_implemented = 504
#     domain_does_not_accept_mail = 521
#     access_denied = 530  # Sendmail specific
#     auth_failed = 535
#     mailbox_does_not_exist = 550
#     user_not_local = 551
#     storage_exceeded = 552
#     mailbox_name_invalid = 553
#     transaction_failed = 554
#     syntax_error = 555


# Path: aiosmtplib/protocol.py
import asyncio
import re
import ssl
from typing import Callable, Optional, cast
from .compat import start_tls
from .errors import (
    SMTPDataError,
    SMTPReadTimeoutError,
    SMTPResponseException,
    SMTPServerDisconnected,
    SMTPTimeoutError,
)
from .response import SMTPResponse
from .status import SMTPStatus

        return response

    async def execute_data_command(
        self, message: bytes, timeout: Optional[float] = None
    ) -> SMTPResponse:
        """
        Sends an SMTP DATA command to the server, followed by encoded message content.

        Automatically quotes lines beginning with a period per RFC821.
        Lone \\\\r and \\\\n characters are converted to \\\\r\\\\n
        characters.
        """
        if self._command_lock is None:
            raise SMTPServerDisconnected("Server not connected")

        message = LINE_ENDINGS_REGEX.sub(b"\r\n", message)
        message = PERIOD_REGEX.sub(b"..", message)
        if not message.endswith(b"\r\n"):
            message += b"\r\n"
        message += b".\r\n"

        async with self._command_lock:
            self.write(b"DATA\r\n")
            start_response = await self.read_response(timeout=timeout)
            if start_response.code != SMTPStatus.start_input:
                raise SMTPDataError(start_response.code, start_response.message)

            self.write(message)
            response = await self.read_response(timeout=timeout)
            if response.code != SMTPStatus.completed:

                raise SMTPDataError(response.code, response.message)