From kazuhiro.ogura at hde.co.jp Wed Mar 13 00:58:06 2013 From: kazuhiro.ogura at hde.co.jp (Kazuhiro Ogura) Date: Wed, 13 Mar 2013 13:58:06 +0900 Subject: [Pymilter] pyspf SPF checking raises TypeError exception when checking erroneous record Message-ID: Hi, I'm using pyspf-2.0.7, and I've found that spf.query.check() raises TypeError exception when doing SPF check against particular DNS entries like: example.com IN TXT "v=spf1 mx:mx1.example.com" mx1.example.com IN CNAME . or entries like: example.com IN TXT "v=spf1 a:mx2.example.com" mx2.example.com IN CNAME . (It is apparently wrong, but it do exists in real world) The traceback for the former is like: Traceback (most recent call last): File "", line 1, in File "spf.py", line 543, in check rc = self.check1(spf, self.d, 0) File "spf.py", line 582, in check1 return self.check0(spf, recursion) File "spf.py", line 876, in check0 if self.cidrmatch(self.dns_mx(arg), cidrlength): File "spf.py", line 1163, in dns_mx return [a for mx in mxnames[:max] for a in self.dns_a(mx[1],self.A)] TypeError: 'NoneType' object is unsubscriptable And for the latter is like: Traceback (most recent call last): File "", line 1, in File "spf.py", line 543, in check rc = self.check1(spf, self.d, 0) File "spf.py", line 582, in check1 return self.check0(spf, recursion) File "spf.py", line 871, in check0 if self.cidrmatch(self.dns_a(arg,self.A), cidrlength): File "spf.py", line 1295, in cidrmatch for ip in [bin(ip) for ip in ipaddrs]: TypeError: 'NoneType' object is not iterable I did some debugging and it looks like DNSLookup() call inside spf.query.dns() returns '' instead of '.', and that is not what is expected in the following code. Is this pydns-side problem? Or should it be fixed in pyspf? -- Kazuhiro Ogura Representative Director, Chief Executive Officer HDE, Inc. http://www.hde.co.jp/ GPG Key Id: 0xFA80C875 We support Karesansui Project: http://karesansui-project.info From stuart at bmsi.com Wed Mar 13 10:39:42 2013 From: stuart at bmsi.com (Stuart D Gathman) Date: Wed, 13 Mar 2013 10:39:42 -0400 (EDT) Subject: [Pymilter] pyspf SPF checking raises TypeError exception when checking erroneous record In-Reply-To: References: Message-ID: On Mar 13, Kazuhiro Ogura transmitted in part: > I'm using pyspf-2.0.7, and I've found that spf.query.check() raises > TypeError exception when doing SPF check against particular DNS > entries like: > > example.com IN TXT "v=spf1 mx:mx1.example.com" > mx1.example.com IN CNAME . > > or entries like: > > example.com IN TXT "v=spf1 a:mx2.example.com" > mx2.example.com IN CNAME . > > (It is apparently wrong, but it do exists in real world) Excellent nit nabbing! Will make a great test case for the test suite also. The next question is, what should the correct result be? PermError, or nomatch? From kazuhiro.ogura at hde.co.jp Thu Mar 14 01:33:07 2013 From: kazuhiro.ogura at hde.co.jp (Kazuhiro Ogura) Date: Thu, 14 Mar 2013 14:33:07 +0900 Subject: [Pymilter] pyspf SPF checking raises TypeError exception when checking erroneous record In-Reply-To: References: Message-ID: 2013/3/13 Stuart D Gathman : > Excellent nit nabbing! Will make a great test case for the test suite > also. The next question is, what should the correct result be? > PermError, or nomatch? Theoretically it is not wrong to point a DNS record to ".", so its not a kind of syntax error. So I think PermError is not appropriate. Then, nomatch? -- Kazuhiro Ogura Representative Director, Chief Executive Officer HDE, Inc. http://www.hde.co.jp/ GPG Key Id: 0xFA80C875 We support Karesansui Project: http://karesansui-project.info From stuart at bmsi.com Thu Mar 14 15:55:53 2013 From: stuart at bmsi.com (Stuart D Gathman) Date: Thu, 14 Mar 2013 15:55:53 -0400 (EDT) Subject: [Pymilter] pyspf SPF checking raises TypeError exception when checking erroneous record In-Reply-To: References: Message-ID: On Mar 14, Kazuhiro Ogura transmitted in part: > 2013/3/13 Stuart D Gathman : >> Excellent nit nabbing! Will make a great test case for the test suite >> also. The next question is, what should the correct result be? >> PermError, or nomatch? > > Theoretically it is not wrong to point a DNS record to ".", so its not > a kind of syntax error. So I think PermError is not appropriate. I created a test case for this, and unless I'm missing something, pyspf-2.0.7 doesn't have this problem: it simply doesn't match. What version are you running? tests: null-cname: comment: | pyspf was getting a type error for null CNAMEs helo: mail.example.com host: 1.2.3.4 mailfrom: bar at e3.example.com result: [fail, permerror] zonedata: e3.example.com: - SPF: v=spf1 mx:mx1.example.com -all mx1.example.com: - CNAME: . From stuart at bmsi.com Thu Mar 14 16:00:02 2013 From: stuart at bmsi.com (Stuart D Gathman) Date: Thu, 14 Mar 2013 16:00:02 -0400 (EDT) Subject: [Pymilter] pyspf SPF checking raises TypeError exception when checking erroneous record In-Reply-To: References: Message-ID: On Mar 14, Stuart D Gathman transmitted in part: > I created a test case for this, and unless I'm missing something, > pyspf-2.0.7 doesn't have this problem: it simply doesn't match. > What version are you running? Also, it could be a dnspython or pydns problem/incompatibility. Are you running pydns or dnspython? > tests: > null-cname: > comment: | > pyspf was getting a type error for null CNAMEs > helo: mail.example.com > host: 1.2.3.4 > mailfrom: bar at e3.example.com > result: [fail, permerror] > zonedata: > e3.example.com: > - SPF: v=spf1 mx:mx1.example.com -all > mx1.example.com: > - CNAME: . From kazuhiro.ogura at hde.co.jp Sun Mar 17 22:47:43 2013 From: kazuhiro.ogura at hde.co.jp (Kazuhiro Ogura) Date: Mon, 18 Mar 2013 11:47:43 +0900 Subject: [Pymilter] pyspf SPF checking raises TypeError exception when checking erroneous record In-Reply-To: References: Message-ID: 2013/3/15 Stuart D Gathman : >> I created a test case for this, and unless I'm missing something, >> pyspf-2.0.7 doesn't have this problem: it simply doesn't match. >> What version are you running? > > > Also, it could be a dnspython or pydns problem/incompatibility. Are > you running pydns or dnspython? Thank you for your investigation. I'm using pydns 2.3.6 and pyspf 2.0.7, but I found that it doesn't simply occur by the case I provided. Sorry. Can you try it with a zonedata like this? zonedata: e3.example.com: - SPF: v=spf1 a:mx1.example.com mx:mx1.example.com -all mx1.example.com: - CNAME: . Below is a actual case I'm facing, domain name replaced to "example.com". Python 2.6.5 (r265:79063, Feb 28 2011, 21:55:45) [GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import DNS >>> DNS.__version__ '2.3.6' >>> import spf >>> spf.__version__ '2.0.7: Jan 19, 2012' >>> q = spf.query(s="exchange.example.com", h="exchange.example.com", i="1.2.3.4") >>> q.check(spf="v=spf1 mx a:exchange.example.com a:relay.example.com a:host05.example.com a:smtp1.example.com mx:exchange.example.com mx:relay.example.com mx:host05.example.com mx:smtp1.example.com mx:sqrelay02.example.com ~all") Traceback (most recent call last): File "", line 1, in File "/usr/lib/python2.6/site-packages/spf.py", line 543, in check rc = self.check1(spf, self.d, 0) File "/usr/lib/python2.6/site-packages/spf.py", line 582, in check1 return self.check0(spf, recursion) File "/usr/lib/python2.6/site-packages/spf.py", line 871, in check0 if self.cidrmatch(self.dns_a(arg,self.A), cidrlength): File "/usr/lib/python2.6/site-packages/spf.py", line 1295, in cidrmatch for ip in [bin(ip) for ip in ipaddrs]: TypeError: 'NoneType' object is not iterable I thought I should give you the actual domain name, but I can't decide whether it is ok to post it to the list, so I'll send you the information personally in another mail. -- Kazuhiro Ogura Representative Director, Chief Executive Officer HDE, Inc. http://www.hde.co.jp/ GPG Key Id: 0xFA80C875 We support Karesansui Project: http://karesansui-project.info From tianzy1225 at thundersoft.com Tue Mar 19 07:42:42 2013 From: tianzy1225 at thundersoft.com (Tian Zhiying) Date: Tue, 19 Mar 2013 19:42:42 +0800 Subject: [Pymilter] Mail account filter Message-ID: <2013031919424157737143@thundersoft.com> Hi There is a demand about postfix : #My postfix version is 2.6.5 . #My domain is mydomain.com In intranet, I hope all mail account can send and receive e-mail, In internet, most of the mail account can not send and receive e-mail, but, have three mail account is not limited, they can send and receive e-mail. Pymilter can achieve this function? Thanks ! Tian Zhiying -------------- next part -------------- An HTML attachment was scrubbed... URL: From s.p.foster at leeds.ac.uk Tue Mar 19 11:16:33 2013 From: s.p.foster at leeds.ac.uk (Steve Foster) Date: Tue, 19 Mar 2013 15:16:33 +0000 (GMT) Subject: [Pymilter] milter.setreply exception Message-ID: Hi Folks, I've hit the following error: Traceback (most recent call last): File "/Milter/__init__.py", line 759, in milter.set_envrcpt_callback(lambda ctx,*str: ctx.getpriv().envrcpt(*str)) File "pymilter.py", line 83, in envrcpt self.setreply('200','2.0.0','All OK') File "/Milter/__init__.py", line 438, in setreply return self._ctx.setreply(rcode,xcode,msg,*ml) milter.error: cannot set reply I've followed the FAQ and increased the timeouts but that hasn't resolved the issue. Any Suggestions? Cheers Steve -- Steve Foster Email: s.p.foster at leeds.ac.uk From tom at whyscream.net Tue Mar 19 12:21:44 2013 From: tom at whyscream.net (Tom Hendrikx) Date: Tue, 19 Mar 2013 17:21:44 +0100 Subject: [Pymilter] milter.setreply exception In-Reply-To: References: Message-ID: <51489098.4040609@whyscream.net> On 03/19/2013 04:16 PM, Steve Foster wrote: > Hi Folks, > > I've hit the following error: > > Traceback (most recent call last): > File "/Milter/__init__.py", line 759, in > milter.set_envrcpt_callback(lambda ctx,*str: > ctx.getpriv().envrcpt(*str)) > File "pymilter.py", line 83, in envrcpt > self.setreply('200','2.0.0','All OK') > File "/Milter/__init__.py", line 438, in setreply > return self._ctx.setreply(rcode,xcode,msg,*ml) > milter.error: cannot set reply > > I've followed the FAQ and increased the timeouts but that hasn't > resolved the issue. Any Suggestions? > 200 is no valid SMTP reply code. I serached for a rfc reference and found this: http://tools.ietf.org/html/rfc876 To solve your problem, do: self.setreply('250','2.0.0','All OK') -- Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 899 bytes Desc: OpenPGP digital signature URL: From s.p.foster at leeds.ac.uk Tue Mar 19 12:28:57 2013 From: s.p.foster at leeds.ac.uk (Steve Foster) Date: Tue, 19 Mar 2013 16:28:57 +0000 (GMT) Subject: [Pymilter] milter.setreply exception In-Reply-To: <51489098.4040609@whyscream.net> References: <51489098.4040609@whyscream.net> Message-ID: On Tue, 19 Mar 2013, Tom Hendrikx wrote: > 200 is no valid SMTP reply code. I serached for a rfc reference and > found this: http://tools.ietf.org/html/rfc876 > > To solve your problem, do: > > self.setreply('250','2.0.0','All OK') Thanks for the suggestion... still doesn't work though. Traceback (most recent call last): File "/Milter/__init__.py", line 759, in milter.set_envrcpt_callback(lambda ctx,*str: ctx.getpriv().envrcpt(*str)) File "pymilter.py", line 83, in envrcpt self.setreply('250','2.0.0','All OK') File "/Milter/__init__.py", line 438, in setreply return self._ctx.setreply(rcode,xcode,msg,*ml) milter.error: cannot set reply This feels like something more fundamental... For example I can add and remove headers. Cheers Steve -- Steve Foster Email: s.p.foster at leeds.ac.uk From tianzy1225 at thundersoft.com Tue Mar 19 12:29:24 2013 From: tianzy1225 at thundersoft.com (Tian Zhiying) Date: Wed, 20 Mar 2013 00:29:24 +0800 Subject: [Pymilter] Re: Mail account filter References: <2013031919424157737143@thundersoft.com> Message-ID: <201303200029236719762@thundersoft.com> Hi folks: Can you help me ? Tian Zhiying From: Tian Zhiying Date: 2013-03-19 19:42 To: pymilter Subject: Mail account filter Hi There is a demand about postfix : #My postfix version is 2.6.5 . #My domain is mydomain.com In intranet, I hope all mail account can send and receive e-mail, In internet, most of the mail account can not send and receive e-mail, but, have three mail account is not limited, they can send and receive e-mail. Pymilter can achieve this function? Thanks ! Tian Zhiying -------------- next part -------------- An HTML attachment was scrubbed... URL: From tom at whyscream.net Tue Mar 19 12:31:32 2013 From: tom at whyscream.net (Tom Hendrikx) Date: Tue, 19 Mar 2013 17:31:32 +0100 Subject: [Pymilter] milter.setreply exception In-Reply-To: References: <51489098.4040609@whyscream.net> Message-ID: <514892E4.9020608@whyscream.net> On 03/19/2013 05:28 PM, Steve Foster wrote: > On Tue, 19 Mar 2013, Tom Hendrikx wrote: > >> 200 is no valid SMTP reply code. I serached for a rfc reference and >> found this: http://tools.ietf.org/html/rfc876 >> >> To solve your problem, do: >> >> self.setreply('250','2.0.0','All OK') > > Thanks for the suggestion... still doesn't work though. > > Traceback (most recent call last): > File "/Milter/__init__.py", line 759, in > milter.set_envrcpt_callback(lambda ctx,*str: > ctx.getpriv().envrcpt(*str)) > File "pymilter.py", line 83, in envrcpt > self.setreply('250','2.0.0','All OK') > File "/Milter/__init__.py", line 438, in setreply > return self._ctx.setreply(rcode,xcode,msg,*ml) > milter.error: cannot set reply > > This feels like something more fundamental... For example I can add and > remove headers. > Can you show us a bit more code, so we can see if you're doing stuff in the wrong order or something like that? -- Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 899 bytes Desc: OpenPGP digital signature URL: From s.p.foster at leeds.ac.uk Tue Mar 19 12:36:08 2013 From: s.p.foster at leeds.ac.uk (Steve Foster) Date: Tue, 19 Mar 2013 16:36:08 +0000 (GMT) Subject: [Pymilter] milter.setreply exception In-Reply-To: <514892E4.9020608@whyscream.net> References: <51489098.4040609@whyscream.net> <514892E4.9020608@whyscream.net> Message-ID: On Tue, 19 Mar 2013, Tom Hendrikx wrote: > Can you show us a bit more code, so we can see if you're doing stuff in > the wrong order or something like that? Basically I'm using one of the example from the documentation with the following def envrcpt(self, to, *str): self.log("mail to:", to, *str) self.setreply('250','2.0.0','All OK') return Milter.CONTINUE I've removed the @Milter.noreply decorator... Cheers Steve -- Steve Foster Email: s.p.foster at leeds.ac.uk Unix team Phone: 0113 343 7225 Information Systems Services Fax: 0113 343 5411 University of Leeds Leeds LS2 9JT From stuart at bmsi.com Tue Mar 19 17:02:43 2013 From: stuart at bmsi.com (Stuart D Gathman) Date: Tue, 19 Mar 2013 17:02:43 -0400 (EDT) Subject: [Pymilter] milter.setreply exception In-Reply-To: References: <51489098.4040609@whyscream.net> <514892E4.9020608@whyscream.net> Message-ID: On Mar 19, Steve Foster transmitted in part: > On Tue, 19 Mar 2013, Tom Hendrikx wrote: > >> Can you show us a bit more code, so we can see if you're doing stuff in >> the wrong order or something like that? > > Basically I'm using one of the example from the documentation with the > following > > def envrcpt(self, to, *str): > self.log("mail to:", to, *str) > self.setreply('250','2.0.0','All OK') > return Milter.CONTINUE If you look at the documentation: http://pythonhosted.org/pymilter/classMilter_1_1Base.html#ad474d1db07ac5f7b61ad9b78ece53a23 or the C API documentation: https://www.milter.org/developers/api/smfi_setreply You will see that setreply would be better named "set_error_reply". You can only set 4xx/5xx codes, and cannot change the message for 2xx codes. This is a limitation of the current milter protocol. From stuart at bmsi.com Tue Mar 19 17:09:51 2013 From: stuart at bmsi.com (Stuart D Gathman) Date: Tue, 19 Mar 2013 17:09:51 -0400 (EDT) Subject: [Pymilter] Re: Mail account filter In-Reply-To: <201303200029236719762@thundersoft.com> References: <2013031919424157737143@thundersoft.com> <201303200029236719762@thundersoft.com> Message-ID: On Mar 20, Tian Zhiying transmitted in part: > Can you?help me ? > ? > There?is?a?demand?about?postfix : > #My postfix?version?is?2.6.5 . > #My domain is mydomain.com > In intranet, I hope all mail account can send and receive e-mail, > In internet, most of the mail account can not send and receive e-mail, but, > have three mail account is not limited, they can send and receive e-mail. > ? > Pymilter can?achieve?this?function? If by "mail account on the internet" you mean an SMTP AUTH login, then yes. In fact, spf-milter-0.8.18 will do this for you out of the box. I am wrapping it up for upload now. (0.8.17 was supposed to, but the SMTP AUTH feature was copied without testing from the bms milter, and of course it didn't work - there are now test cases for spf-milter.) spf-milter defines "intranet" via the "internal-connect" config, which provides a list of ips and subnets in CIDR notation. I don't run postfix, so there *may* be some postfix limitation regarding milters, but those have become fairly rare in recent versions. From s.p.foster at leeds.ac.uk Tue Mar 19 17:15:54 2013 From: s.p.foster at leeds.ac.uk (Steve Foster) Date: Tue, 19 Mar 2013 21:15:54 +0000 Subject: [Pymilter] milter.setreply exception In-Reply-To: References: <51489098.4040609@whyscream.net> <514892E4.9020608@whyscream.net> Message-ID: <1dd520e3-6c06-4687-9772-0e4bb6df7c1f@email.android.com> Ok that makes sense... but the following example doesn't follow the points you have made: http://spidey2.bmsi.com/pymilter/milter-template_8py-example.html Stuart D Gathman wrote: >On Mar 19, Steve Foster transmitted in part: > >> On Tue, 19 Mar 2013, Tom Hendrikx wrote: >> >>> Can you show us a bit more code, so we can see if you're doing stuff >in >>> the wrong order or something like that? >> >> Basically I'm using one of the example from the documentation with >the >> following >> >> def envrcpt(self, to, *str): >> self.log("mail to:", to, *str) >> self.setreply('250','2.0.0','All OK') >> return Milter.CONTINUE > >If you look at the documentation: >http://pythonhosted.org/pymilter/classMilter_1_1Base.html#ad474d1db07ac5f7b61ad9b78ece53a23 > >or the C API documentation: >https://www.milter.org/developers/api/smfi_setreply > >You will see that setreply would be better named "set_error_reply". >You can only set 4xx/5xx codes, and cannot change the message for 2xx >codes. > >This is a limitation of the current milter protocol. -- Sent from my Android phone with K-9 Mail. Please excuse my brevity. -------------- next part -------------- An HTML attachment was scrubbed... URL: From stuart at bmsi.com Tue Mar 19 17:20:18 2013 From: stuart at bmsi.com (Stuart D Gathman) Date: Tue, 19 Mar 2013 17:20:18 -0400 (EDT) Subject: [Pymilter] milter.setreply exception In-Reply-To: <1dd520e3-6c06-4687-9772-0e4bb6df7c1f@email.android.com> References: <51489098.4040609@whyscream.net> <514892E4.9020608@whyscream.net> <1dd520e3-6c06-4687-9772-0e4bb6df7c1f@email.android.com> Message-ID: On Mar 19, Steve Foster transmitted in part: > Ok that makes sense... but the following example doesn't follow the points > you have made: > > http://spidey2.bmsi.com/pymilter/milter-template_8py-example.html Removed that bad example. :-) Will update pythonhosted shortly. From stuart at bmsi.com Mon Mar 25 18:03:09 2013 From: stuart at bmsi.com (Stuart D Gathman) Date: Mon, 25 Mar 2013 18:03:09 -0400 (EDT) Subject: [Pymilter] pyspf SPF checking raises TypeError exception when checking erroneous record In-Reply-To: References: Message-ID: On Mar 18, Kazuhiro Ogura transmitted in part: > Can you try it with a zonedata like this? > > zonedata: > e3.example.com: > - SPF: v=spf1 a:mx1.example.com mx:mx1.example.com -all > mx1.example.com: > - CNAME: . That does indeed break it with real DNS, but not as a test case. The reason is that the mock DNSLookup doesn't include supplementary data in addition to answers like a real DNS server does. This supplementary data gets added to a short lived (only for one mail connection) cache, and having the empty CNAME in the cache is what breaks it. I am working on improving the mock DNSLookup. Here is the fix: @@ -1264,7 +1261,7 @@ if name.endswith('.'): name = name[:-1] if not reduce(lambda x,y:x and 0 < len(y) < 64, name.split('.'),True): return [] # invalid DNS name (too long or empty) - result = self.cache.get( (name, qtype) ) + result = self.cache.get( (name, qtype), []) if result: return result cnamek = (name,'CNAME') cname = self.cache.get( cnamek ) From stuart at bmsi.com Mon Mar 25 19:03:08 2013 From: stuart at bmsi.com (Stuart D Gathman) Date: Mon, 25 Mar 2013 19:03:08 -0400 (EDT) Subject: [Pymilter] pyspf SPF checking raises TypeError exception when checking erroneous record In-Reply-To: References: Message-ID: On Mar 25, Stuart D Gathman transmitted in part: > On Mar 18, Kazuhiro Ogura transmitted in part: > >> Can you try it with a zonedata like this? >> >> zonedata: >> e3.example.com: >> - SPF: v=spf1 a:mx1.example.com mx:mx1.example.com -all >> mx1.example.com: >> - CNAME: . > > That does indeed break it with real DNS, but not as a test case. > The reason is that the mock DNSLookup doesn't include supplementary > data in addition to answers like a real DNS server does. This > supplementary data gets added to a short lived (only for one mail > connection) cache, and having the empty CNAME in the cache is what > breaks it. > > I am working on improving the mock DNSLookup. Nothing wrong with mock DNSLookup. The problem was the test zonedata should be: zonedata: e3.example.com: - SPF: v=spf1 a:mx1.example.com mx:mx1.example.com -all mx1.example.com: - CNAME: '' Test case (and fix) committed. Thanks Kazuhiro !