Skip to content

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

Description

@dwig
mannequin
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:

    assignee = None
    closed_at = None
    created_at = <Date 2008-10-17.20:02:42.197>
    labels = ['type-bug', 'library']
    title = "smtplib doesn't clear helo/ehlo flags on quit"
    updated_at = <Date 2014-03-16.09:35:13.017>
    user = 'https://bugs.python.org/dwig'

    bugs.python.org fields:

    activity = <Date 2014-03-16.09:35:13.017>
    actor = 'berker.peksag'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2008-10-17.20:02:42.197>
    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']

    Linked PRs

    Activity

    1. dwig commented on Oct 17, 2008

      dwigmannequin
      MannequinAuthor

      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).

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-bugAn unexpected behavior, bug, or error
      on Oct 17, 2008
    3. FelixSchwarz commented on Feb 15, 2009

      FelixSchwarzmannequin
      Mannequin

      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

    4. loewis commented on Feb 15, 2009

      loewismannequin
      Mannequin

      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).

    5. dwig commented on Feb 17, 2009

      dwigmannequin
      MannequinAuthor

      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.)

    6. loewis commented on Feb 17, 2009

      loewismannequin
      Mannequin

      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).

    7. jcea commented on Mar 24, 2010

      @jcea
      Member

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

    8. sandrotosi commented on Feb 7, 2011

      @sandrotosi
      Contributor

      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?

    9. dwig commented on Feb 8, 2011

      dwigmannequin
      MannequinAuthor

      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.

    10. varun commented on Mar 9, 2014

      varunmannequin
      Mannequin

      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.

    11. dwig commented on Mar 10, 2014

      dwigmannequin
      MannequinAuthor

      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().

    12. transferred this issue fromon Apr 10, 2022
    13. vasiliyk commented on Oct 29, 2026

      @vasiliyk
      Contributor

      The reported case (quit, connect, then sendmail with no new EHLO) was fixed in 3.4.2 by gh-66412.
      test_quit_resets_greeting in test_smtplib covers it.

      The state still survives when quit() raises, or when the session ends in close().
      I will open a separate issue for that, with a PR once I am under the PR limit.

    14. vasiliyk commented on Nov 3, 2026

      @vasiliyk
      Contributor

      I fixed it in #161267 instead of a separate issue.

      The reset moves from quit() into close(), which quit(), the with statement and the disconnect paths all call, so a an SMTP object sends EHLO again on reconnect.

    15. added a commit that references this issue on Nov 3, 2026
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      stdlibStandard Library Python modules in the Lib/ directorytopic-emailtype-bugAn unexpected behavior, bug, or error

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions