-
Couldn't load subscription status.
- Fork 0
smtplib #1
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
base: master
Are you sure you want to change the base?
smtplib #1
Conversation
|
Note that when I say "Commits 'x' through 'y', I mean topologically, as shown by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Seems like a simple enough port.
Lib/smtplib.py taken from CPython v3.3.6 (https://github.com/python/cpython/blob/v3.3.6/Lib/smtplib.py)
From CPython 3.6, to prevent leaking resources
From CPython 3.6. Also, socket.error is not always available in MicroPython.
From CPython 3.6
From CPython 3.6
From CPython 3.6
From CPython 3.6
From CPython 3.6
From CPython 3.6
MicroPython doesn't have socket.getfqdn or socket.gethostname.
These modules will not be needed unless send_message is called. This is particularly useful given that email.generator is not yet in micropython-lib.
On MicroPython, calling sys.stdout.flush() raises EINVAL.
All uses of the re module have been removed.
This eliminates the dependencies on the base64 and email.base64mime modules.
str.partition is not available by default on all ports.
As discussed in micropython/micropython#1375, the Unix port's usocket.connect method takes a bytes object that represents a struct sockaddr. In the case of Unix domain sockets, it's a struct sockaddr_un. There's no portable way to pack that struct (since it can be defined differently on different platforms), so we'll let the caller handle it. On many Linux platforms, this can be achieved with something like ustruct.pack('H108s', usocket.AF_UNIX, '/path/to/sock').
Done by reimplementing _GLOBAL_DEFAULT_TIMEOUT and create_connection.
According to the documentation, usocket.socket.sendall has undefined behavior on non-blocking sockets. Furthermore, the method does not even appear to exist in the Unix port (documentation notwithstanding). Instead, we'll wrap send in a loop.
The result of MicroPython's ussl.wrap_socket does not have the send or makefile methods, unlike CPython. Because of the possibility that starttls has been called (not to mention the possibility that SSL was used from the outset, as in the SMTP_SSL class), it is not generally known whether self.sock is an SSL-wrapped socket or not. As such, we cannot, in general, call self.sock.makefile or self.sock.send. Instead of potentially calling self.sock.makefile in getreply (as is done upstream), I've opted to create self.file exactly when creating self.sock (no more or less). This works because, when creating self.sock, it is always known whether self.sock is SSL-wrapped or not, and thus it is known how to get a self.file. An alternative solution (for MicroPython) would be to never call self.sock.makefile, and take advantage of the fact that MicroPython sockets have read and write methods already (using write instead of send). That seemed less desirable though, since it would potentially make merging of upstream patches difficult, while providing no clear benefit. (The two options seemed like a wash in terms of minimizing the size of the diff from upstream.)
This pull request is for internal review by coworkers. It is a precursor to an upstream pull request.
Caveats with this branch currently:
Note that I will force push this branch, because that's how upstream wants to do it (in accordance with their contributor guidlines). When I do, I'll leave a message here saying so. If this makes anyone uncomfortable, let me know.
This pull request adds an implementation of the smtplib module for micropython-smtplib.
Following the recommendations of the contributor guidelines, I took the original source from CPython 3.3.6, as linked to in the first commit's message. I then looked at the diff between that and CPython 3.6, and backported the changes that didn't appear to add bloat (mostly bug fixes). This is not expressly called for by the contributor guidelines, and could be considered to go against the directive to minimize the size of the diff from upstream. However, it reduces the diff from CPython 3.6, and also includes several bug fixes. It didn't seem wise to ignore existing fixes for bugs that come without substantial increase in the size of the code. These commits are "Close before raising" through "Defer SMTPServerDisconnected during RSET". If you really want to stay close to 3.3 and ignore those bugs, we can drop these commits.
I also removed a lot of dependencies, for example by:
ubinasciidirectly instead of pulling in thebase64andemail.base64mimemodules and everything that comes with them, andsend_messagefunction, so that the rest of the library can be used without them.Other changes should have an obvious reason for being there, or should be justified in the commit message. Let me know if anything requires further explanation.
I didn't write any automated tests because it is not obvious to me how to involve external stuff like the SMTP server. The code from upstream that shows example usage if
__name__ == '__main__'can still be used.This code has been tested on Unix and the ESP8266 (mine didn't have enough memory to compile; this and a couple dependencies needed to be frozen in). Fun fact: It actually remains compatible with CPython if you revert "Prefer self.file over self.sock" and remove the u-prefixes from module names.
Thanks,
Alex