Skip to content

gh-127712: Fix secure argument of logging.handlers.SMTPHandler #127726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 10, 2025
Merged

gh-127712: Fix secure argument of logging.handlers.SMTPHandler #127726

merged 1 commit into from
Feb 10, 2025

Conversation

s-hamann
Copy link
Contributor

@s-hamann s-hamann commented Dec 7, 2024

Python 3.12 removed support for the keyfile and certfile parameters in smtplib.SMTP.starttls(), requiring a ssl.SSLContext instead. SMTPHandler now creates a context from the secure tuple and passes that to starttls.

This PR basically restores SMTPHandler functionality as it was in Python 3.11.
It is to note that, contrary to the documentation, using a single-value tuple for secure does not work. Instead, ssl._create_unverified_context raises ValueError: certfile must be specified.
However, this also happened with Python 3.11, so I did not change it. The only difference is, with Python 3.11 the target SMTP server needed to actually support STARTTLS to encounter the exception. Now it is raised before checking the server for STARTTLS support.
This is simply because the ssl.SSLContext is created earlier.

Off topic: Personally, I believe the secure argument to SMTPHandler is confusing and somewhat limiting. I suggest deprecating it in favour of something more versatile. Allow passing a context, maybe?

@s-hamann s-hamann requested a review from vsajip as a code owner December 7, 2024 20:03
@ghost
Copy link

ghost commented Dec 7, 2024

All commit authors signed the Contributor License Agreement.
CLA signed

Copy link
Member

@ZeroIntensity ZeroIntensity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for contributing! Happy to see new people 😄
(FWIW, you don't need to force-push, everything gets squash merged.)

In general, the fix itself looks good. I just have a few nitpicks related to formatting and performance.

@ZeroIntensity ZeroIntensity added needs backport to 3.12 only security fixes needs backport to 3.13 bugs and security fixes labels Dec 10, 2024
Python 3.12 removed support for the `keyfile` and `certfile` parameters
in `smtplib.SMTP.starttls()`, requiring a `ssl.SSLContext` instead.
`SMTPHandler` now creates a context from the `secure` tuple and passes
that to `starttls`.
Copy link
Member

@picnixz picnixz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never used this interface but it looks fine. Can we however have additional tests for this please? the regression should have been detected but apparently not.

Copy link
Member

@ZeroIntensity ZeroIntensity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix makes sense to me. (We need tests, but I'll just wait for @picnixz's approval before I ping a core dev.)

@s-hamann
Copy link
Contributor Author

Can we however have additional tests for this please? the regression should have been detected but apparently not.

Does that mean me? I'm all for tests, but I'm not familiar with Python's test infrastructure and I believe the mock SMTP server does not currently handle STARTTLS. So, I'm at at bit of a loss on how to test this properly.

@ZeroIntensity
Copy link
Member

You'll probably want to add the test to SMTPHandlerTest. You can find most of the things that you need to know about testing in the devguide.

@s-hamann
Copy link
Contributor Author

Thanks for the hints. The test case itself seems rather straightforward. Making TestSMTPServer support STARTTLS looks more complex. I'll try to implement that, but I don't think I'll get around to it this year. If anyone else wants to tackle this, I'd be grateful. This is somewhat more involved than the quick and easy bug fix I had in mind ;)

@ZeroIntensity
Copy link
Member

Ah yeah, that's why there wasn't a test before. I'm OK with merging this as-is, and then letting someone with a bit more knowledge of the codebase deal with getting support for SSL in the tests. @picnixz WDYT?

@picnixz
Copy link
Member

picnixz commented Dec 13, 2024

I prefer having tests and this PR close to each other in the commit history. I've never used that parameter so I'll have a look tomorrow at the internals just to check and I'll tell you my conclusions (we are backporting this bugfix to a stable version so I'd prefer having tests just in case, but if they're too hard to write, I'll see if I can write them myself).

Copy link
Member

@vsajip vsajip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think writing a full-blown test (updating the TestSMTPServer to support starttls meaningfully) will be too much work for the benefit that it confers. ISTM this change just moves converting a ('private_key_file, cert_file) tuple to an SSL context into the handler, rather than it being done in the starttls` method in Python 3.11 and earlier. This is the code in 3.11:

cpython/Lib/smtplib.py

Lines 787 to 789 in 45db419

if context is None:
context = ssl._create_stdlib_context(certfile=certfile,
keyfile=keyfile)

So. I'm OK to merge this as is, without tests.

@vsajip vsajip merged commit d7672e5 into python:main Feb 10, 2025
46 checks passed
@miss-islington-app
Copy link

Thanks @s-hamann for the PR, and @vsajip for merging it 🌮🎉.. I'm working now to backport this PR to: 3.12, 3.13.
🐍🍒⛏🤖 I'm not a witch! I'm not a witch!

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Feb 10, 2025
…er` (pythonGH-127726)

pythonGH-127712: Fix `secure` argument of `logging.handlers.SMTPHandler`

Python 3.12 removed support for the `keyfile` and `certfile` parameters
in `smtplib.SMTP.starttls()`, requiring a `ssl.SSLContext` instead.
`SMTPHandler` now creates a context from the `secure` tuple and passes
that to `starttls`.
(cherry picked from commit d7672e5)

Co-authored-by: s-hamann <10639154+s-hamann@users.noreply.github.com>
@bedevere-app
Copy link

bedevere-app bot commented Feb 10, 2025

GH-129955 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.13 bugs and security fixes label Feb 10, 2025
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Feb 10, 2025
…er` (pythonGH-127726)

pythonGH-127712: Fix `secure` argument of `logging.handlers.SMTPHandler`

Python 3.12 removed support for the `keyfile` and `certfile` parameters
in `smtplib.SMTP.starttls()`, requiring a `ssl.SSLContext` instead.
`SMTPHandler` now creates a context from the `secure` tuple and passes
that to `starttls`.
(cherry picked from commit d7672e5)

Co-authored-by: s-hamann <10639154+s-hamann@users.noreply.github.com>
@bedevere-app
Copy link

bedevere-app bot commented Feb 10, 2025

GH-129956 is a backport of this pull request to the 3.12 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.12 only security fixes label Feb 10, 2025
vsajip pushed a commit that referenced this pull request Feb 10, 2025
vsajip pushed a commit that referenced this pull request Feb 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants