From 8e579681bb84361324667fe14bd44f6f1def2122 Mon Sep 17 00:00:00 2001 From: Savage Mechanic Date: Thu, 1 Oct 2026 16:00:34 +0100 Subject: [PATCH] Doc: Clarify smtplib server reply values --- Doc/library/smtplib.rst | 28 +++++++++++++++++----------- Lib/smtplib.py | 37 +++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 5c97199bc453e85..ef9d440c0254f4f 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -164,11 +164,11 @@ A nice selection of exceptions is defined as well: .. attribute:: smtp_code - The error code. + The error code as an integer. .. attribute:: smtp_error - The error message. + The error message as a :class:`bytes` object. .. exception:: SMTPSenderRefused @@ -251,8 +251,10 @@ An :class:`SMTP` instance has the following methods: Send a command *cmd* to the server. The optional argument *args* is simply concatenated to the command, separated by a space. - This returns a 2-tuple composed of a numeric response code and the actual - response line (multiline responses are joined into one long line.) + This returns a ``(code, message)`` tuple, where *code* is the server + response code as an integer and *message* is the server response as a + :class:`bytes` object. Multiline responses are joined into a single + response. In normal operation it should not be necessary to call this method explicitly. It is used to implement other methods and may be useful for testing private @@ -269,8 +271,8 @@ An :class:`SMTP` instance has the following methods: followed by a number, that suffix will be stripped off and the number interpreted as the port number to use. This method is automatically invoked by the constructor if a host is specified during instantiation. Returns a - 2-tuple of the response code and message sent by the server in its - connection response. + ``(code, message)`` tuple, where *code* is the server response code as an + integer and *message* is the server response as a :class:`bytes` object. If port is not changed from its default value of 0, the value of the :attr:`default_port` attribute is used. @@ -323,9 +325,11 @@ An :class:`SMTP` instance has the following methods: .. method:: SMTP.verify(address) Check the validity of an address on this server using SMTP ``VRFY``. Returns a - tuple consisting of code 250 and a full :rfc:`822` address (including human - name) if the user address is valid. Otherwise returns an SMTP error code of 400 - or greater and an error string. + ``(code, message)`` tuple, where *code* is the server response code as an + integer and *message* is the server response as a :class:`bytes` object. + If the user address is valid, *code* is 250 and *message* contains a full + :rfc:`822` address (including human name). Otherwise *code* is an SMTP error + code of 400 or greater and *message* contains the error response. .. note:: @@ -485,8 +489,10 @@ An :class:`SMTP` instance has the following methods: recipient. Otherwise it will raise an exception. That is, if this method does not raise an exception, then someone should get your mail. If this method does not raise an exception, it returns a dictionary, with one entry for each - recipient that was refused. Each entry contains a tuple of the SMTP error code - and the accompanying error message sent by the server. + recipient that was refused. Each entry contains a + ``(code, response)`` tuple, where *code* is the SMTP error code as an + integer and *response* is the accompanying server error response as a + :class:`bytes` object. If ``SMTPUTF8`` is included in *mail_options*, and the server supports it, *from_addr* and *to_addrs* may contain non-ASCII characters. diff --git a/Lib/smtplib.py b/Lib/smtplib.py index 4cfc2338d99c67e..a81f5530029f827 100644 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -26,7 +26,7 @@ End of HELP info >>> s.putcmd("vrfy","someone@here") >>> s.getreply() - (250, "Somebody OverHere ") + (250, b"Somebody OverHere ") >>> s.quit() ''' @@ -89,9 +89,9 @@ class SMTPResponseException(SMTPException): """Base class for all exceptions that include an SMTP error code. These exceptions are generated in some instances when the SMTP - server returns an error code. The error code is stored in the - `smtp_code' attribute of the error, and the `smtp_error' attribute - is set to the error message. + server returns an error code. The error code is stored as an integer + in the `smtp_code' attribute, and the `smtp_error' attribute is set + to the error message as bytes. """ def __init__(self, code, msg): @@ -328,6 +328,9 @@ def connect(self, host='localhost', port=0, source_address=None): Note: This method is automatically invoked by __init__, if a host is specified during instantiation. + Returns a (code, message) tuple, where code is the server response + code as an integer and message is the server response as bytes. + """ if source_address: @@ -389,11 +392,11 @@ def getreply(self): Returns a tuple consisting of: - - server response code (e.g. '250', or such, if all goes well) - Note: returns -1 if it can't read response code. + - server response code as an integer (e.g. 250 if all goes well). + Returns -1 if it can't read the response code. - - server response string corresponding to response code (multiline - responses are converted to a single, multiline string). + - server response as bytes corresponding to the response code. + Multiline responses are joined with newline bytes. Raises SMTPServerDisconnected if end-of-file is reached. """ @@ -434,7 +437,7 @@ def getreply(self): return errcode, errmsg def docmd(self, cmd, args=""): - """Send a command, and return its response code.""" + """Send a command and return its (code, message) response tuple.""" self.putcmd(cmd, args) return self.getreply() @@ -565,10 +568,11 @@ def data(self, msg): Automatically quotes lines beginning with a period per rfc821. Raises SMTPDataError if there is an unexpected reply to the - DATA command; the return value from this method is the final - response code received when the all data is sent. If msg - is a string, lone '\\r' and '\\n' characters are converted to - '\\r\\n' characters. If msg is bytes, it is transmitted as is. + DATA command. Returns a (code, message) tuple, where code is the + final response code as an integer and message is the server response + as bytes. If msg is a string, lone '\\r' and '\\n' characters are + converted to '\\r\\n' characters. If msg is bytes, it is transmitted + as is. """ self.putcmd("data") (code, repl) = self.getreply() @@ -831,8 +835,9 @@ def sendmail(self, from_addr, to_addrs, msg, mail_options=(), This method will return normally if the mail is accepted for at least one recipient. It returns a dictionary, with one entry for each - recipient that was refused. Each entry contains a tuple of the SMTP - error code and the accompanying error message sent by the server. + recipient that was refused. Each entry contains a (code, response) + tuple, where code is the SMTP error code as an integer and response is + the accompanying server error response as bytes. This method may raise the following exceptions: @@ -861,7 +866,7 @@ def sendmail(self, from_addr, to_addrs, msg, mail_options=(), ... ... This is a test ''' >>> s.sendmail("me@my.org",tolist,msg) - { "three@three.org" : ( 550 ,"User unknown" ) } + { "three@three.org" : ( 550 ,b"User unknown" ) } >>> s.quit() In the above example, the message was accepted for delivery to three