python / cpython

The Python programming language
https://www.python.org
Other
63.51k stars 30.42k forks source link

smtplib doesn't clear helo/ehlo flags on quit #48392

Open d5a4790b-8790-42c5-8a9a-57030e4205b0 opened 16 years ago

d5a4790b-8790-42c5-8a9a-57030e4205b0 commented 16 years ago
BPO 4142
Nosy @loewis, @jcea, @giampaolo, @bitdancer, @sandrotosi
Files
  • helo.patch: Patch against /trunk, can probably be applied for 2.4.x, 2.5.x and 2.6.x also
  • flag_reset_4142.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields: ```python assignee = None closed_at = None created_at = labels = ['type-bug', 'library'] title = "smtplib doesn't clear helo/ehlo flags on quit" updated_at = user = 'https://bugs.python.org/dwig' ``` bugs.python.org fields: ```python activity = actor = 'berker.peksag' assignee = 'none' closed = False closed_date = None closer = None components = ['Library (Lib)'] creation = creator = 'dwig' dependencies = [] files = ['13100', '34316'] hgrepos = [] issue_num = 4142 keywords = ['patch'] message_count = 10.0 messages = ['74935', '82158', '82165', '82287', '82290', '101631', '128157', '128181', '212985', '213050'] nosy_count = 8.0 nosy_names = ['loewis', 'jcea', 'giampaolo.rodola', 'dwig', 'r.david.murray', 'sandro.tosi', 'alfmel', 'varun'] pr_nums = [] priority = 'normal' resolution = None stage = 'patch review' status = 'open' superseder = None type = 'behavior' url = 'https://bugs.python.org/issue4142' versions = ['Python 2.7', 'Python 3.3', 'Python 3.4'] ```

    d5a4790b-8790-42c5-8a9a-57030e4205b0 commented 16 years ago

    Found on Windows, running Python 2.4.3.

    SMTP.login() and SMTP.sendmail set one of the attributes ehlo_resp or helo_resp to whatever the server responded (only if they're not already set).

    SMTP.quit() doesn't clear these attributes, so on the next connection, the HELO/EHLO commands won't be sent; this will cause problems with some servers (MDaemon in my case). The fix is obvious, and a workaround would be to clear the attributes in the instance before calling login (or sendmail where authentication isn't needed).

    9a26fce5-457c-4298-801e-7dd76170f433 commented 15 years ago

    I can confirm that this issue is still present in Python 2.5.2, 2.6.1 and 3.0.1.

    The current behavior of smtplib is a clear violation of the SMTP specification. The problem can be reproduced with code like that (stub, pseudo code-like): smtp = smtplib.SMTP() smtp.sendmail('from@example.com', 'foo@example.com', msg) smtp.quit() smtp.connect() # This command does not send EHLO/HELO again, violating the spec! smtp.sendmail('from@example.com', 'foo@example.com', msg)

    Real world bug reports due to this behavior were mostly visible with Exim because this MTA rejects the 'MAIL FROM' if SMTP extension verbs are used without EHLO: * http://groups.google.com/group/turbomail-devel/browse_thread/thread/a25c89a94b42724f

    61337411-43fc-4a9c-b8d5-4060aede66d0 commented 15 years ago

    IIUC, the bug only occurs if you use the same SMTP object for multiple connections. I would claim that this is a bug in the application: SMTP objects are not designed to be used for multiple connections. You need to create a new one for each connection.

    If you want to extend the SMTP class to work for multiple connections, the provided patch is incorrect. Resetting the attributes should not be done in .connect() (i.e. for the new connection), but in .close() (i.e. when shutting down the previous connection). Furthermore, it should not only reset the two response attributes, but all per-connection attributes (which includes e.g. esmtp_features), and a test should be provided that, after close, only known "good" attributes remain set on the object (e.g. debuglevel).

    d5a4790b-8790-42c5-8a9a-57030e4205b0 commented 15 years ago

    Re: "SMTP objects are not designed to be used for multiple connections" ... "If you want to extend the SMTP class to work for multiple connections".

    Carefully parsing the library reference documentation, I can see that it could be interpreted that way: "A SMTP instance encapsulates _an_ SMTP connection" (emphasis added). I'd recommend making the documentation clearer in this regard, whether the implementation is extended or not. (And if non-reusability is intended, it'd be even more helpful if the connect() method were to throw a clear exception if called again.)

    61337411-43fc-4a9c-b8d5-4060aede66d0 commented 15 years ago

    It's neither deliberately designed to work for a single connection only, nor designed to support multiple of them. I guess (and only guess) that the authors of the module never considered your usage.

    So if you want to see something done, please contribute patches. I'm personally neutral which way they should go (and don't feel motivated to write patches myself - I can live with the status quo).

    Of course, any patch would set a precedent, and httplib and ftplib would then probably need to follow (requiring contributors then also).

    jcea commented 14 years ago

    Support for smtpd too? (a stdlib addition in 2.7/3.2)

    sandrotosi commented 13 years ago

    Hello Felix/Don, are you still interested in seeing this fixed in smtplib? If so, what about incorporating Martin's suggestions and propose a new patch for review?

    d5a4790b-8790-42c5-8a9a-57030e4205b0 commented 13 years ago

    I have no pressing need for it. I'm happy enough with Martin's idea of single-use instances, as long as they're clearly documented as such, and don't "pretend" to work for a subsequent connect. I'd also be happy with instances that could be used for multiple connections, as long as that didn't increase the complexity of the code too much.

    Martin's also right that the similar clients for http and ftp, as well as smtp, should all work the same.

    d10895aa-cab4-45cb-b5b3-173702eb4254 commented 10 years ago

    I have added a patch and it's test case as per martin's suggestions. Now function close() resets the attributes :sock, default_port, ehlo_msg, ehlo_resp, helo_resp, source_address

    But it does *not* reset : debuglevel, does_esmtp,esmtp_features, file, local_hostname

    I think the attributes does_esmtp, esmtp_features and local_hostname are most probably not going to be changed even if someone uses the same object more than once.

    d5a4790b-8790-42c5-8a9a-57030e4205b0 commented 10 years ago

    Varun, thanks for the patch; sounds like the right way to go, in that it should work whether the usage is single-connection or multiple-connection. Ideally, the documentation would be expanded a bit to clarify just which attributes get reset on close().