Issue 8739: Update to smtpd.py to RFC 5321 (original) (raw)

Created on 2010-05-17 13:34 by alfmel, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (38)

msg105902 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-05-17 13:34

This patch updates smtpd.py to be more RFC 5321 compliant. It contains:

The patch is specific to Python 3.1. I have not tried to backport the changes to 2.x. If possible, I would like the patch to be considered for inclusion to 3.2.

msg105938 - (view)

Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer)

Date: 2010-05-17 21:12

Some comments:

-# This file implements the minimal SMTP protocol as defined in RFC 821. It +# This file implements the minimal SMTP protocol as defined in RFC 5321. It

Is RFC 5321 completely implemented? Otherwise I would turn this in "as defined in RFC 821 and part of RFC 5321".

I couldn't find any reference to this in RFC 5321. Is it recommended somewhere else maybe? Also, issue 2518 and issue 1745035 are somewhat related with this specific problem.

Since you implemented HELP command in the first place it would be good to do it completely (I guess this means HELP should be able to accept arguments, as in FTP protocol).

Too bad smtpd currently lacks a test suite. Before going any further with this issue I would recommend to write tests first. I have a patch for adding a basic test suite for smtpd module I hope I'll be able to submit within this week.

msg105941 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-05-17 21:48

Giampaolo Rodola' <g.rodola@gmail.com> added the comment:

Some comments:

Is RFC 5321 completely implemented? Otherwise I would turn this in "as defined in RFC 821 and part of RFC 5321".

RFC 5321 obsoletes RFCs 821, 974, 1869 and 2821. I don't think we should make reference to them anymore. Perhaps say something like "implements RFC 5321 which supersedes RFC 821."

As to how complete the implementation is, section 4.5.1 of RFC 5321 specifies the following as the minimum set of commands that should be supported in a conforming specification: EHLO, HELO, MAIL, RCPT, DATA, RSET, NOOP, QUIT, VRFY. The only gray area is VRFY which is supposed to see if a mailbox exists for a particular user. Since that function cannot be easily performed in this proxy smtpd server, section 3.5.3 states a 252 reply code should be returned. My patch returns code 252 if self.__getaddr returns true, or 502 if it returns false.

  • Implement DATA size limit (32 MiB by default) I couldn't find any reference to this in RFC 5321. Is it recommended somewhere else maybe? Also, issue 2518 and issue 1745035 are somewhat related with this specific problem.

It is not, but just seemed like good practice to advertise the limit in EHLO and enforce it. My patch doesn't do a good job of enforcing it since it enforces it before doing process_message. The problems with 2518 and 1745035 are still there.

Since you implemented HELP command in the first place it would be good to do it completely.

RFC 5321 doesn't specify it must accept arguments, but I agree it is a good idea. I'll work on that and submit a new patch.

Too bad smtpd currently lacks a test suite. Before going any further with this issue I would recommend to write tests first. I have a patch for adding a basic test suite for smtpd module I hope I'll be able to submit within this week.

It would be great if you could implement a test suite.

msg105943 - (view)

Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer)

Date: 2010-05-17 23:06

It is not, but just seemed like good practice to advertise the limit in EHLO and enforce it. My patch doesn't do a good job of enforcing it since it enforces it before doing process_message. The problems with 2518 and 1745035 are still there.

Then I doubt it would be a good idea, also because the following comment added in issue 1745035 should still stand:

The patch does not work as Giampaolo intends. If the patch were applied as-is, no emails longer than 998 bytes could be sent.

Personally I think there's no other way to gracefully solve this other than using a tempfile to store the data, but since I'm not a user of the module I'm going to let someone else comment about this.

RFC 5321 doesn't specify it must accept arguments, but I agree it is a good idea. I'll work on that and submit a new patch.

If there's no RFC which states that, then I would provide arguments for HELP only if that is a common practice amongst smtp servers.

msg106152 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-05-20 13:46

I have attached a version 2 of the patch. This patch includes everything in the first version, and adds the following:

This last feature adds the -s or --size option to the command line. It allows the user to specify the maximum size for the message. It is set to 0 for the default, meaning no limit. This mimics the original behavior of module. If you specify a size (like --size 32768), it will reject messages larger than the specified number of bytes (32KiB in this case). If you don't specify the size, the response of EHLP won't list SIZE as one of the extensions. But, if a size is specified, then it will show it on EHLP.

Hopefully these two changes will address some of the concerns that have been brought up.

msg106284 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-05-22 04:08

On Thursday 20 May 2010 07:46:43 am you wrote:

If you don't specify the size, the response of EHLP won't list SIZE as one of the extensions. But, if a size is specified, then it will show it on EHLP.

Sorry, the EHLP above should be EHLO. Fat fingers, little sleep, talk about help... you get the idea.

msg109337 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-07-05 16:25

What is the status of this patch? Is there anything else I need to do? Any remaining concerns that would stop this patch from being merged?

msg109338 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2010-07-05 16:41

Yes, the fact that there are no unit tests for the new functionality. As far as I can see the existing smtpd tests (which don't appear to be too extensive...but this module probably dates from before we had a firm unit test policy), are in test_smtplib.

msg112553 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-08-02 21:29

On Monday, July 05, 2010 10:41:28 am you wrote:

Yes, the fact that there are no unit tests for the new functionality.

Sorry to take so long to reply. I have attached the latest version of the patch which does everything in rev. 2 of the patch, patches the setuid problem discussed in issue 9168, updates to the unit test to account for the changes and to test the new functionality, plus some little changes here and there.

Please review and advise.

msg112557 - (view)

Author: Richard Jones (richard) * (Python committer)

Date: 2010-08-03 06:43

The smtpd module now has a test suite. Please add your unit tests to test_smtpd.py

msg112947 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-08-05 06:28

Sorry. This is my first submission to Python, so I'm learning the process as I go.

This latest patch is done against today's SVN snapshot. Just to summarize, it does the following:

Again, please review and comment as necessary.

msg113939 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-08-15 04:07

Any more work I need to do on this patch?

msg113968 - (view)

Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer)

Date: 2010-08-15 15:19

Patch no longer applies cleanly because smtpd.py changed in the meantime. A further comment:

This change breaks backward compatibility. I think it would be better to provide this as a SMTPChannel.size_limit class attribute.

msg114050 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-08-16 15:53

On Sunday, August 15, 2010 09:19:27 am Giampaolo Rodola' wrote:

Patch no longer applies cleanly because smtpd.py changed in the meantime.

Is someone going to fix that or I am expected to play daily catch-up until this gets merged?

A further comment:

This change breaks backward compatibility. I think it would be better to provide this as a SMTPChannel.size_limit class attribute.

Unfortunately, I don't have the time in the next few weeks to make that change. Can someone else make it?

msg114057 - (view)

Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer)

Date: 2010-08-16 17:42

Re-adapted patch including size_limit change as described in my previous message is in attachment. Barry and Alberto, could you take a final look at it before committing?

msg114060 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-08-16 18:11

On Monday, August 16, 2010 11:42:51 am you wrote:

Re-adapted patch including size_limit change as described in my previous message is in attachment. Barry and Alberto, could you take a final look at it before committing?

Looks good to me. If the tests pass, then I'm good to go.

msg114063 - (view)

Author: Barry A. Warsaw (barry) * (Python committer)

Date: 2010-08-16 18:58

The one thing that looks weird to me is VRFY. Since it never actually does verify the user, should we even claim to support the command? Why not let subclasses claim support if they want to add it?

msg114071 - (view)

Author: Alberto Trevino (alfmel)

Date: 2010-08-16 19:50

On Monday, August 16, 2010 12:58:07 pm Barry A. Warsaw wrote:

The one thing that looks weird to me is VRFY. Since it never actually does verify the user, should we even claim to support the command? Why not let subclasses claim support if they want to add it?

RFC 5321 section 4.5.1 states VRFY should be implemented in order to be considered an RFC 5321-compliant implementation. But, in section 3.5.3 paragraph 2 it states that if the actual verification was not performed but syntax was checked similar to RCPT, then the response code should be 252.

So my purposes for providing the plumbing for VRFY are:

  1. Provide a basic, valid implementation to be as RFC 5321-compliant as possible.

  2. Let users know the command is there so that it can be reimplemented as they build their solutions.

msg153244 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-02-13 03:36

Alberto, might you still interested in working on this? I thought I'd do a quick update to current trunk and check it in, but in the process of doing that I found some issues. I suspect it has been frustrating for you that nothing happened with this for 3.2, but it is a non-trivial patch since it involves RFC conformance.

I'm uploading what I got done of the update. I've restored your introduction of a size argument to the smtp and channel classes (I don't know why Giampaolo objected, adding keyword arguments is not backward incompatible). A max data size was introduced to deal with a DOS attack on the SMTPD server, called data_size_limit. I changed that to be 'max_message_size' (rather than your size_limit) because this patch will make it be used for implementing that extended SMTP feature (as well as continuing to provide the DOS-preventing-limit by default).

There are still not enough tests. In particular there are no tests for the smtpd command line functionality, and there was a bug in that in the last patch (it was still using the class argument you had eliminated at Giampaolo's request). Writing those tests is of course a bit of a pain, but by combining the stuff from script_helpers with smtplib, it ought to be possible. (But I wouldn't let a lack of command line tests prevent me from committing a completed patch.)

The more important problem is that your implementation of RFC 5321 left out a critical piece: parameters on the MAIL FROM and RCPT TO commands, and in particular the SIZE parameter to MAIL FROM. Without that you aren't actually implementing RFC 1870 (or, for that matter, 5321 since a compliant server should reject unknown parameters as a syntax error).

I know it has been a long time, but are you still interested in working on this? I haven't had much time to review stuff lately, much less do coding for the stdlib, but I'd really like to see this in 3.3, so if you are willing to work on it I'll commit to reviewing it in a timely fashion.

msg153264 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-02-13 12:31

Gah, that's what I get for trying to do something quick. By changing the name of that variable I introduced a backward incompatibility, since that change was released in 3.2.

msg153282 - (view)

Author: Alberto Trevino (alfmel)

Date: 2012-02-13 17:21

David, I'd be happy to help, but I'm pretty busy for the next month. I read the description of your patch, and it sounds good to me. Anything that moves the project forward is always welcomed. Thanks for your work on this.

msg153283 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-02-13 17:30

OK. Maybe someone else will want to work on it, too. I'll see if I can get it taken care of one way or another during the PyCon sprints.

I'm going to mark this as easy, because really other than expanding test coverage I think the only thing that needs done is to fix MAIL FROM/RCPT TO. Another pair of eyes going through the RFC would be good too, of course. Maybe someone from the core-mentorship list will be interested.

msg155378 - (view)

Author: Juhana Jauhiainen (Juhana.Jauhiainen) *

Date: 2012-03-11 09:44

The patch I've attached adds minimal support for the SIZE parameter of MAIL command.

If the given message size exceeds the servers maximum size the server responds with error 552.

msg155385 - (view)

Author: Michele Orrù (maker) *

Date: 2012-03-11 14:51

I'm currently working on this issue. A little cleanup would be appreciated, or it would be better to split that on another issue? For what I saw, tests are in the form FooTest instead of TestFoo, smtpd imports modules used only in main, warnings can be handled the appropriate module, import shall not be used.

msg155386 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-03-11 15:30

Yes, cleanups would be better as a separate issue.

msg155390 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-03-11 15:58

Juhana: thanks for the patch. I see an issue with it, though. What if the email address is something like JOHN.SIZER@example.com?

My thought is that there are two ways to handle this. Either we do a full RFC address parse in __getaddr and have it return the remainder of the line, or we parse from the right hand side looking for keword=value elements (which if I remember the RFC right have a pretty constrained syntax).

Ideally I'd like to see a general parsing solution so we can handle other parameters in the future easily. So perhaps a function like

_getkeywords(arg) -> (arg, kwdict)

that parses the keywords off from the right and returns them in a dict, along with whatever non-keyword argument text is left.

The other path, parsing the address fully, could theoretically use the parseaddr utility from the email package, but I'm not sure if it will return the endpoint of an address embedded in a longer string.

msg155444 - (view)

Author: Juhana Jauhiainen (Juhana.Jauhiainen) *

Date: 2012-03-12 08:42

Since Michele has been already working on this I could help with the cleanup once it's separated as a new issue.

David: Thanks for your comments. I wasn't sure if I should make a general solution or not and ended up making this one.

msg155446 - (view)

Author: Michele Orrù (maker) *

Date: 2012-03-12 11:19

Patch attached. A few considerations: in case of syntax error, the server responds with " MAIL FROM:

[SP ] " according to http://tools.ietf.org/html/rfc5321#section-3.3 (instead of "MAIL FROM:
"). Note that this could break something, as far as backwards compatibility is concerned. Looking at http://tools.ietf.org/html/rfc3030#section-4.2 , I was wondering whether the size parameter on MAIL FROM should have implications on the RCPT TO command (i.e., we should check that the foreign email accepts that size). Finally, right now the size parameter is not considered until greater than max_message_size. This could let the user push an email with a size greater than the on declared (but smaller than max_message_size).

Tests for command line and cleanup will be on another issue.

Waiting for directives :) ,

ù

msg155565 - (view)

Author: Dan Boswell (fruitnuke)

Date: 2012-03-13 03:26

I built on Michele's patch during the pycon sprint, addressing some of the concerns rightly raised in previous comment:

  1. Turn off the SIZE extension if client uses HELO (though limits are still used internally to limit message size for DoS protection), and report syntax of MAIL/RCPT correctly depending on whether HELO is issued.
  2. Extend max command size by 26 chars when SIZE extension is enabled, as required by RFC 1870.
  3. First cut at adding parameters to RCPT command for SMTP extensions as required by RFC 1869/5321.
  4. Return 555 for MAIL/RCPT parameters that are valid but not implemented.

and some other issues:

  1. Fix typo 'maximium' -> 'maximum'
  2. Add test to show failure to parse localpart of email address (left as expected failure as a correct parse will require version 6 of the email package).
  3. Fix up command line arg for specifying SIZE extension.

Still some issues to resolve, I already came up with a couple in testing, and some of the (new) code can be cleaned up.

So far this server implements the SIZE and 8BITMIME extensions in a tightly-coupled manner, and does not make it easy for subclasses to implement additional smtp extensions. Ideally we would make SMTPChannel extensible in this way but that may require extensive refactoring and would be better raised and addressed as another issue.

msg155786 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-03-14 20:13

By the way, Alberto, if you haven't already submitted a contributor agreement, could you do so please? We have one from Dan from the sprints. Michele, you aren't marked in the tracker as having submitted an agreement but you've been active long enough I would think you would have. Have you and it just isn't reflected in the tracker?

msg155850 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-03-15 03:49

OK, I've gone through Dan's update (thanks very much for the tests!). I'm uploading a revised patch. The major differences are:

I've refactored the parsing. Now it is a three step process: peel off the extra keyword (FROM:, TO:) if there is one, then pull off the address, then parse the remainder as parameters, doing a best-effort parse (that is, ignore tokens that don't parse as parameters rather than failing the entire parse if one is bad). This fixed a bug where a space between the : and the address would break command parsing. When the RFC5322 parser from email6 lands, it will almost be a drop in replacement for _parseaddr. (Oh, yeah, I took the opportunity to eliminate the last __ methods. There's no reason for those parsing methods to be __ methods.) I say almost because it will allow us to correctly implement the difference in the syntax of the address for VRFY verses MAIL and RCPT by using two different functions from that parser.

I've removed the 8BITMIME support. It was not implemented correctly per its RFC, and the server as it exists does not, in fact, support receiving binary data (it decodes what it receives using the utf-8 codec...which means it will raise a decode error on binary data). It would be possible to add 8BITMIME support, but since it is non trivial we'll leave that to another issue.

I reworked the extended command length support to facilitate adding additional extension support. What I did may not be the most useful refactoring, though. I considered just making the limit "large enough", but decided to keep the current behavior since it allows smtpd to be used to test clients handling smtp servers that enforce the limits. Given that, a nice future feature would be to make the max command length limit settable as well.

I renamed max_message_size back to data_size_limit in order to maintain backward compatibility.

I updated the general help output to reflect the HELO/EHLO state. I don't know what typical servers do for that (since HELP can be issued before them), but I think I've seen it work that way on other servers.

I've added a few more tests.

Unless someone wants to add tests for the smtpd command line, I think this patch is done. Reviews welcome.

msg155863 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-03-15 05:49

Note that this patch causes test_logging to fail/hang. I've opened issue 14314 that mentions the hang (the issue is really about the lack of a timeout in logging's smtp handler) and updated issue 11959 about the issues involved in test_logging using smtpd the way it does. I'm making fixing that issue a dependency for this one.

msg156008 - (view)

Author: Michele Orrù (maker) *

Date: 2012-03-16 08:10

David: yes, I did. About two weeks ago. Probably I'll take a look to those issues :)

msg156009 - (view)

Author: Michele Orrù (maker) *

Date: 2012-03-16 08:13

David, can you tag this issue as dependency for ?

msg161667 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-05-26 15:22

Removing dependency on issue 11959. Instead I'm going to fix the logging test by adding the necessary updates to its init methods on the smtpd subclasses. Then 11959 can be dealt with independently.

msg161674 - (view)

Author: Roundup Robot (python-dev) (Python triager)

Date: 2012-05-26 18:36

New changeset ec7456b3f4fe by R David Murray in branch 'default': #8739: upgrade smtpd to RFC 5321 and 1870. http://hg.python.org/cpython/rev/ec7456b3f4fe

msg161675 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2012-05-26 18:37

Thanks very much to everyone who contributed to this patch. It was a real team effort :)

msg162285 - (view)

Author: Roundup Robot (python-dev) (Python triager)

Date: 2012-06-04 19:56

New changeset 079c1942eedf by R David Murray in branch 'default': #8739: fix omission of DEBUGSTREAM reset in new test in test_smtpd. http://hg.python.org/cpython/rev/079c1942eedf

History

Date

User

Action

Args

2022-04-11 14:57:01

admin

set

github: 52985

2012-06-04 19:56:29

python-dev

set

messages: +

2012-05-26 18:37:15

r.david.murray

set

status: open -> closed
messages: +

assignee: r.david.murray ->
resolution: fixed
stage: needs patch -> resolved

2012-05-26 18:36:04

python-dev

set

nosy: + python-dev
messages: +

2012-05-26 15:22:36

r.david.murray

set

dependencies: - smtpd cannot be used without affecting global state
messages: +

2012-03-16 15:22:25

r.david.murray

link

issue14261 dependencies

2012-03-16 08:13:23

maker

set

messages: +

2012-03-16 08:10:33

maker

set

messages: +

2012-03-15 05:49:32

r.david.murray

set

dependencies: + smtpd cannot be used without affecting global state
messages: +

2012-03-15 03:50:16

r.david.murray

set

files: + issue8739.patch

2012-03-15 03:49:49

r.david.murray

set

messages: +

2012-03-14 20:13:54

r.david.murray

set

messages: +

2012-03-14 01:20:54

fruitnuke

set

nosy:barry, richard, giampaolo.rodola, josiah.carlson, r.david.murray, maker, alfmel, catalin.iacob, tshepang, geoffreyspear, Anthony.Kong, hynek, fruitnuke, Juhana.Jauhiainen

2012-03-13 03:26:26

fruitnuke

set

files: + issue8739.patch
nosy: + fruitnuke
messages: +

2012-03-12 11:19:48

maker

set

files: + issue8739.patch

messages: +

2012-03-12 08:42:33

Juhana.Jauhiainen

set

messages: +

2012-03-11 15:58:45

r.david.murray

set

messages: +

2012-03-11 15:30:17

r.david.murray

set

messages: +

2012-03-11 14:51:29

maker

set

nosy: + maker
messages: +

2012-03-11 09:44:56

Juhana.Jauhiainen

set

files: + size_parameter.patch
nosy: + Juhana.Jauhiainen
messages: +

2012-02-27 14:07:20

tshepang

set

nosy: + tshepang

2012-02-14 11:14:58

geoffreyspear

set

nosy: + geoffreyspear

2012-02-13 20:01:35

hynek

set

nosy: + hynek

2012-02-13 19:46:08

Anthony.Kong

set

nosy: + Anthony.Kong

2012-02-13 17:30:25

r.david.murray

set

keywords: + easy

messages: +
stage: test needed -> needs patch

2012-02-13 17:21:00

alfmel

set

messages: +

2012-02-13 12:31:31

r.david.murray

set

messages: +

2012-02-13 10:23:09

catalin.iacob

set

nosy: + catalin.iacob

2012-02-13 03:36:09

r.david.murray

set

files: + rfc5321.patch
assignee: r.david.murray
messages: +

versions: + Python 3.3, - Python 3.2

2010-08-16 19:50:59

alfmel

set

messages: +

2010-08-16 18:58:06

barry

set

messages: +

2010-08-16 18:11:18

alfmel

set

messages: +

2010-08-16 17:42:46

giampaolo.rodola

set

files: + smtpd.patch

messages: +

2010-08-16 15:53:09

alfmel

set

messages: +

2010-08-15 15:19:25

giampaolo.rodola

set

messages: +

2010-08-15 04:07:42

alfmel

set

messages: +

2010-08-05 06:28:10

alfmel

set

files: + smtpd.py-0.2-rfc5321-enhancements-5.diff

messages: +

2010-08-03 06:43:25

richard

set

nosy: + richard
messages: +

2010-08-02 21:29:59

alfmel

set

files: + smtpd.py-0.2-rfc5321-enhancements-4.diff

messages: +

2010-07-05 16:41:26

r.david.murray

set

messages: +

2010-07-05 16:25:15

alfmel

set

messages: +

2010-05-22 04:08:34

alfmel

set

messages: +

2010-05-20 13:46:40

alfmel

set

files: + smtpd.py-0.2-rfc5321-enhancements-2.diff

messages: +

2010-05-17 23:06:41

giampaolo.rodola

set

nosy: + josiah.carlson
messages: +

2010-05-17 21:48:23

alfmel

set

messages: +

2010-05-17 21:12:23

giampaolo.rodola

set

nosy: + giampaolo.rodola
messages: +

2010-05-17 14:42:39

barry

set

versions: - Python 3.1

2010-05-17 14:06:37

r.david.murray

set

nosy: + r.david.murray

stage: test needed

2010-05-17 13:34:07

alfmel

create