Skip to content

Use aiosmtpd for the smtp.Server class #30

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 4 commits into from
Apr 23, 2022
Merged

Conversation

diazona
Copy link
Contributor

@diazona diazona commented Apr 6, 2022

I made these changes to switch from using Python's standard smtpd module, which is deprecated, to the external aiosmtpd package. The changes are somewhat substantial, but most of them are just meant to keep the Server class interface backward compatible and to support old versions of Python and smtpd. Once we drop support for older versions, it will simplify the implementation quite a bit.

One thing to note: it's not entirely clear how actively aiosmtpd is maintained, since the last commit on Github was over a year ago and there's a featured issue asking for help with the package. So I can imagine a future where the suggested replacement for smtpd changes to something other than aiosmtpd. It's possible we might want to defer this merge request until the status of aiosmtpd as a replacement for smtpd becomes more clear.

Closes #12

diazona added 2 commits April 6, 2022 15:09
This change should make it a bit more explicit what form the message
details are supposed to take.
In this commit I've completely rewritten the smtp.Server class using
aiosmtpd instead of Python's standard smtpd module, which is deprecated
and scheduled for removal in Python 3.12.

Migrating the main functionality to aiosmtpd is intrinsically not hard;
it just required creating the Handler class, which is about ten lines
and can be used as-is with aiosmtpd.controller.Controller. The rest of
the changes here are to reproduce the interface of the existing Server
class well enough to pass the tests. We've been testing some features of
the Server class which don't exactly have equivalents in aiosmtpd, so I
had to use some wrappers and hacks to offer the same interface: for
example, I reimplemented the Server.stop() method to make it idempotent
and accept a timeout argument, and I had to use some private attributes
of Controller to make Server.is_alive() and Server.accepting behave
the way they used to.

I also added some additional hacks to support older versions of aiosmtpd
that work with Python 3.5. In retrospect, that probably wasn't worth it,
but I started trying to do it without realizing how much work it'd be,
and once the work was done, I figured I might as well keep it. We should
definitely drop support for Python 3.5 soon, though, and that will
simplify the implementation.
@diazona diazona added this to the 0.6.0 milestone Apr 6, 2022
@diazona diazona requested review from coordt and redtoad April 6, 2022 22:17
diazona added 2 commits April 12, 2022 00:31
The address of an IPv6 socket as returned by getsockname() is
a four-element tuple, rather than a two-element tuple as expected by
the existing pytest_localserver.smtp module code. In this commit I'm
extracting the first two elements of the tuple so that a Server's addr
attribute will be a 2-tuple of (host, port) regardless of whether
the underlying socket is an IPv4 or IPv6 socket.
In this commit I'm adding a test which ensures that the Server address
is a 2-tuple of (host, port), with the host being a string and the port
being a positive integer. This format is expected by existing code.
@diazona
Copy link
Contributor Author

diazona commented Apr 15, 2022

@redtoad @coordt any input on this?

@diazona diazona requested a review from nicoddemus April 17, 2022 03:00
@diazona
Copy link
Contributor Author

diazona commented Apr 17, 2022

@nicoddemus if you don't mind, I'd appreciate your thoughts about introducing a dependency on aiosmtpd given its unclear maintenance status. Maybe you know more than I do about what the future of that package looks like 🤷 (Of course any other feedback on the PR is welcome too!)

@nicoddemus
Copy link
Member

Hi @diazona,

Thanks a lot for the work on this! I didn't review it in depth, but the code looks good and well documented.

Maybe you know more than I do about what the future of that package looks like

Unfortunately I don't, AFAIK @coordt and @redtoad are still the maintainers, might have been lack of time to go over the PR yet.

If you are willing to maintain a plugin, and given that it is possible to have a different/incompatible API that fits the async model better, to have this as a separate plugin altogether: if users need to port the code, might make sense to migrate the plugin as well.

@diazona
Copy link
Contributor Author

diazona commented Apr 20, 2022

@nicoddemus Thanks for the review!

Sorry if I'm misunderstanding what you meant, but it sounds like you might have missed that I'm also a maintainer of this package (pytest-localserver), so I'll be able to merge the PR myself. I just really wanted to get at least one extra set of eyes on this before merging it, and since it's been two weeks without hearing from @coordt or @redtoad, I asked you.

The main thing I wanted a second opinion on is whether it makes sense to introduce this dependency on aiosmtpd, given that its maintenance status is unclear. I guess if you don't have any special insight on that, I'll try reaching out to the community around that package directly and see what they say.

@nicoddemus
Copy link
Member

but it sounds like you might have missed that I'm also a maintainer of this package (pytest-localserver), so I'll be able to merge the PR myself.

Ahh indeed I missed that, sorry about that!

The main thing I wanted a second opinion on is whether it makes sense to introduce this dependency on aiosmtpd, given that its maintenance status is unclear.

Ahh sorry I don't have any insight on that. Reaching them sounds good. 👍

Sorry about the confusion on my part!

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.

Module smtpd marked deprecated in Python 3.10
3 participants