Skip to content
Snippets Groups Projects
Commit 6048fe6e authored by Stuart Gathman's avatar Stuart Gathman
Browse files

Remove explicit spf dependency.

parent d2253848
Branches
No related tags found
No related merge requests found
# provide a higher level interface to pydns
import DNS
from DNS import DNSError
MAX_CNAME = 10
def DNSLookup(name, qtype):
try:
req = DNS.DnsRequest(name, qtype=qtype)
resp = req.req()
#resp.show()
# key k: ('wayforward.net', 'A'), value v
# FIXME: pydns returns AAAA RR as 16 byte binary string, but
# A RR as dotted quad. For consistency, this driver should
# return both as binary string.
return [((a['name'], a['typename']), a['data']) for a in resp.answers]
except IOError, x:
raise DNSError, str(x)
class Session(object):
"""A Session object has a simple cache with no TTL that is valid
for a single "session", for example an SMTP conversation."""
def __init__(self):
self.cache = {}
def dns(self, name, qtype, cnames=None):
"""DNS query.
If the result is in cache, return that. Otherwise pull the
result from DNS, and cache ALL answers, so additional info
is available for further queries later.
CNAMEs are followed.
If there is no data, [] is returned.
pre: qtype in ['A', 'AAAA', 'MX', 'PTR', 'TXT', 'SPF']
post: isinstance(__return__, types.ListType)
"""
result = self.cache.get( (name, qtype) )
cname = None
if not result:
safe2cache = query.SAFE2CACHE
for k, v in DNSLookup(name, qtype, self.strict):
if k == (name, 'CNAME'):
cname = v
if (qtype,k[1]) in safe2cache:
self.cache.setdefault(k, []).append(v)
result = self.cache.get( (name, qtype), [])
if not result and cname:
if not cnames:
cnames = {}
elif len(cnames) >= MAX_CNAME:
#return result # if too many == NX_DOMAIN
raise DNSError('Length of CNAME chain exceeds %d' % MAX_CNAME)
cnames[name] = cname
if cname in cnames:
raise DNSError, 'CNAME loop'
result = self.dns(cname, qtype, cnames=cnames)
return result
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
# Send DSNs, do call back verification, # Send DSNs, do call back verification,
# and generate DSN messages from a template # and generate DSN messages from a template
# $Log$ # $Log$
# Revision 1.14 2007/03/03 18:19:40 customdesigned
# Handle DNS error sending DSN.
#
# Revision 1.13 2007/01/04 18:01:11 customdesigned # Revision 1.13 2007/01/04 18:01:11 customdesigned
# Do plain CBV when template missing. # Do plain CBV when template missing.
# #
...@@ -19,22 +22,22 @@ ...@@ -19,22 +22,22 @@
# #
import smtplib import smtplib
import spf
import socket import socket
from email.Message import Message from email.Message import Message
import Milter import Milter
import time import time
import dns
def send_dsn(mailfrom,receiver,msg=None,timeout=600): def send_dsn(mailfrom,receiver,msg=None,timeout=600,session=None):
"""Send DSN. If msg is None, do callback verification. """Send DSN. If msg is None, do callback verification.
Mailfrom is original sender we are sending DSN or CBV to. Mailfrom is original sender we are sending DSN or CBV to.
Receiver is the MTA sending the DSN. Receiver is the MTA sending the DSN.
Return None for success or (code,msg) for failure.""" Return None for success or (code,msg) for failure."""
user,domain = mailfrom.split('@') user,domain = mailfrom.split('@')
if not session: session = dns.Session()
try: try:
q = spf.query(None,None,None) mxlist = session.dns(domain,'MX')
mxlist = q.dns(domain,'MX') except dns.DNSError:
except spf.TempError:
return (450,'DNS Timeout: %s MX'%domain) # temp error return (450,'DNS Timeout: %s MX'%domain) # temp error
if not mxlist: if not mxlist:
mxlist = (0,domain), # fallback to A record when no MX mxlist = (0,domain), # fallback to A record when no MX
...@@ -124,6 +127,7 @@ def create_msg(q,rcptlist,origmsg=None,template=None): ...@@ -124,6 +127,7 @@ def create_msg(q,rcptlist,origmsg=None,template=None):
return msg return msg
if __name__ == '__main__': if __name__ == '__main__':
import spf
q = spf.query('192.168.9.50', q = spf.query('192.168.9.50',
'SRS0=pmeHL=RH==stuart@example.com', 'SRS0=pmeHL=RH==stuart@example.com',
'red.example.com',receiver='mail.example.com') 'red.example.com',receiver='mail.example.com')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment