from email.message import Message as _Message
from typing import (
    Any, AnyStr, Dict, Generic, List, Optional, Sequence, Tuple, Union,
    Pattern)

_Reply = Tuple[int, bytes]
_SendErrs = Dict[str, _Reply]

SMTP_PORT: int
SMTP_SSL_PORT: int
CRLF: str
bCRLF: bytes

OLDSTYLE_AUTH: Pattern[str]

class SMTPException(OSError): ...
class SMTPServerDisconnected(SMTPException): ...

class SMTPResponseException(SMTPException):
    smtp_code = ...  # type: int
    smtp_error = ...  # type: Union[bytes, str]
    args = ...  # type: Union[Tuple[int, Union[bytes, str]], Tuple[int, bytes, str]]
    def __init__(self, code: int, msg: Union[bytes, str]) -> None: ...

class SMTPSenderRefused(SMTPResponseException):
    smtp_code = ...  # type: int
    smtp_error = ...  # type: bytes
    sender = ...  # type: str
    args = ...  # type: Tuple[int, bytes, str]
    def __init__(self, code: int, msg: bytes, sender: str) -> None: ...

class SMTPRecipientsRefused(SMTPException):
    recipients = ...  # type: _SendErrs
    args = ...  # type: Tuple[_SendErrs]
    def __init__(self, recipients: _SendErrs) -> None: ...

class SMTPDataError(SMTPResponseException): ...
class SMTPConnectError(SMTPResponseException): ...
class SMTPHeloError(SMTPResponseException): ...
class SMTPAuthenticationError(SMTPResponseException): ...

def quoteaddr(addrstring): ...
def quotedata(data): ...

class SMTP:
    debuglevel = ...  # type: int
    file = ...  # type: Any
    helo_resp = ...  # type: Any
    ehlo_msg = ...  # type: Any
    ehlo_resp = ...  # type: Any
    does_esmtp = ...  # type: Any
    default_port = ...  # type: Any
    timeout = ...  # type: float
    esmtp_features = ...  # type: Any
    source_address = ...  # type: Any
    local_hostname = ...  # type: Any
    def __init__(self, host: str = ..., port: int = ...,
                 local_hostname: Optional[str] = ..., timeout: float = ...,
                 source_address: Tuple[str, int] = ...) -> None: ...
    def __enter__(self): ...
    def __exit__(self, *args): ...
    def set_debuglevel(self, debuglevel: int) -> None: ...
    sock = ...  # type: Any
    def connect(self, host=..., port=..., source_address=...): ...
    def send(self, s): ...
    def putcmd(self, cmd, args=...): ...
    def getreply(self) -> _Reply: ...
    def docmd(self, cmd, args=...): ...
    def helo(self, name=...): ...
    def ehlo(self, name=...): ...
    def has_extn(self, opt): ...
    def help(self, args=...): ...
    def rset(self) -> _Reply: ...
    def noop(self) -> _Reply: ...
    def mail(self, sender: str, options: Sequence[str] = ...) -> _Reply: ...
    def rcpt(self, recip: str, options: Sequence[str] = ...) -> _Reply: ...
    def data(self, msg): ...
    def verify(self, address): ...
    vrfy = ...  # type: Any
    def expn(self, address): ...
    def ehlo_or_helo_if_needed(self): ...
    def login(self, user, password): ...
    def starttls(self, keyfile=..., certfile=..., context=...): ...
    def sendmail(self, from_addr: str, to_addrs: Union[str, Sequence[str]],
                 msg: Union[bytes, str], mail_options: Sequence[str] = ...,
                 rcpt_options: List[str] = ...) -> _SendErrs: ...
    def send_message(self, msg: _Message, from_addr: Optional[str] = ...,
                     to_addrs: Optional[Union[str, Sequence[str]]] = ...,
                     mail_options: List[str] = ...,
                     rcpt_options: Sequence[str] = ...) -> _SendErrs: ...
    def close(self): ...
    def quit(self) -> _Reply: ...

class SMTP_SSL(SMTP):
    default_port = ...  # type: Any
    keyfile = ...  # type: Any
    certfile = ...  # type: Any
    context = ...  # type: Any
    def __init__(self, host=..., port=..., local_hostname=..., keyfile=..., certfile=...,
                 timeout=..., source_address=..., context=...): ...

class LMTP(SMTP):
    ehlo_msg = ...  # type: Any
    def __init__(self, host: str = ..., port: int = ...,
                 local_hostname: Optional[str] = ...,
                 source_address: Optional[Tuple[str, int]] = ...) -> None: ...
    sock = ...  # type: Any
    file = ...  # type: Any
    def connect(self, host=..., port=..., source_address=...): ...
