Doxygen updates
This commit is contained in:
@@ -31,7 +31,7 @@ PROJECT_NAME = pymilter
|
|||||||
# This could be handy for archiving the generated documentation or
|
# This could be handy for archiving the generated documentation or
|
||||||
# if some version control system is used.
|
# if some version control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 0.9.2
|
PROJECT_NUMBER = 0.9.3
|
||||||
|
|
||||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||||
# base path where the generated documentation will be put.
|
# base path where the generated documentation will be put.
|
||||||
|
|||||||
@@ -146,6 +146,14 @@ class Base(object):
|
|||||||
def close(self): return CONTINUE
|
def close(self): return CONTINUE
|
||||||
|
|
||||||
## Return mask of SMFIP_N.. protocol option bits to clear for this class
|
## Return mask of SMFIP_N.. protocol option bits to clear for this class
|
||||||
|
# The @@nocallback and @@noreply decorators set the
|
||||||
|
# <code>milter_protocol</code> function attribute to the protocol mask bit to
|
||||||
|
# pass to libmilter, causing that callback or its reply to be skipped.
|
||||||
|
# Overriding a method creates a new function object, so that
|
||||||
|
# <code>milter_protocol</code> defaults to 0.
|
||||||
|
# Libmilter passes the protocol bits that the current MTA knows
|
||||||
|
# how to skip. We clear the ones we don't want to skip.
|
||||||
|
# The negation is somewhat mind bending, but it is simple.
|
||||||
@classmethod
|
@classmethod
|
||||||
def protocol_mask(klass):
|
def protocol_mask(klass):
|
||||||
try:
|
try:
|
||||||
|
|||||||
+29
-16
@@ -1,12 +1,22 @@
|
|||||||
# provide a higher level interface to pydns
|
## @package Milter.dns
|
||||||
|
# Provide a higher level interface to pydns.
|
||||||
|
|
||||||
import DNS
|
import DNS
|
||||||
from DNS import DNSError
|
from DNS import DNSError
|
||||||
|
|
||||||
MAX_CNAME = 10
|
MAX_CNAME = 10
|
||||||
|
|
||||||
|
## Lookup DNS records by label and RR type.
|
||||||
|
# The response can include records of other types that the DNS
|
||||||
|
# server thinks we might need.
|
||||||
|
# @param name the DNS label to lookup
|
||||||
|
# @param qtype the name of the DNS RR type to lookup
|
||||||
|
# @return a list of ((name,type),data) tuples
|
||||||
def DNSLookup(name, qtype):
|
def DNSLookup(name, qtype):
|
||||||
try:
|
try:
|
||||||
|
# To be thread safe, we create a fresh DnsRequest with
|
||||||
|
# each call. It would be more efficient to reuse
|
||||||
|
# a req object stored in a Session.
|
||||||
req = DNS.DnsRequest(name, qtype=qtype)
|
req = DNS.DnsRequest(name, qtype=qtype)
|
||||||
resp = req.req()
|
resp = req.req()
|
||||||
#resp.show()
|
#resp.show()
|
||||||
@@ -24,25 +34,28 @@ class Session(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.cache = {}
|
self.cache = {}
|
||||||
|
|
||||||
|
## Additional DNS RRs we can safely cache.
|
||||||
# We have to be careful which additional DNS RRs we cache. For
|
# We have to be careful which additional DNS RRs we cache. For
|
||||||
# instance, PTR records are controlled by the connecting IP, and they
|
# instance, PTR records are controlled by the connecting IP, and they
|
||||||
# could poison our local cache with bogus A and MX records.
|
# could poison our local cache with bogus A and MX records.
|
||||||
|
# Each entry is a tuple of (query_type,rr_type). So for instance,
|
||||||
|
# the entry ('MX','A') says it is safe (for milter purposes) to cache
|
||||||
|
# any 'A' RRs found in an 'MX' query.
|
||||||
|
SAFE2CACHE = frozenset((
|
||||||
|
('MX','MX'), ('MX','A'),
|
||||||
|
('CNAME','CNAME'), ('CNAME','A'),
|
||||||
|
('A','A'),
|
||||||
|
('AAAA','AAAA'),
|
||||||
|
('PTR','PTR'),
|
||||||
|
('NS','NS'), ('NS','A'),
|
||||||
|
('TXT','TXT'),
|
||||||
|
('SPF','SPF')
|
||||||
|
))
|
||||||
|
|
||||||
SAFE2CACHE = {
|
## Cached DNS lookup.
|
||||||
('MX','A'): None,
|
# @param name the DNS label to query
|
||||||
('MX','MX'): None,
|
# @param qtype the query type, e.g. 'A'
|
||||||
('CNAME','A'): None,
|
# @param cnames tracks CNAMES already followed in recursive calls
|
||||||
('CNAME','CNAME'): None,
|
|
||||||
('A','A'): None,
|
|
||||||
('AAAA','AAAA'): None,
|
|
||||||
('PTR','PTR'): None,
|
|
||||||
('NS','NS'): None,
|
|
||||||
('NS','A'): None,
|
|
||||||
('TXT','TXT'): None,
|
|
||||||
('SPF','SPF'): None
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def dns(self, name, qtype, cnames=None):
|
def dns(self, name, qtype, cnames=None):
|
||||||
"""DNS query.
|
"""DNS query.
|
||||||
|
|
||||||
|
|||||||
+41
-1
@@ -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.17 2009/05/20 20:08:44 customdesigned
|
||||||
|
# Support non-DSN CBV (non-empty MAIL FROM)
|
||||||
|
#
|
||||||
# Revision 1.16 2007/09/25 01:24:59 customdesigned
|
# Revision 1.16 2007/09/25 01:24:59 customdesigned
|
||||||
# Allow arbitrary object, not just spf.query like, to provide data for create_msg
|
# Allow arbitrary object, not just spf.query like, to provide data for create_msg
|
||||||
#
|
#
|
||||||
@@ -26,7 +29,31 @@
|
|||||||
# Revision 1.10 2006/05/24 20:56:35 customdesigned
|
# Revision 1.10 2006/05/24 20:56:35 customdesigned
|
||||||
# Remove default templates. Scrub test.
|
# Remove default templates. Scrub test.
|
||||||
#
|
#
|
||||||
|
## @package Milter.dsn
|
||||||
|
# Support DSNs and CallBackValidations (CBV).
|
||||||
|
#
|
||||||
|
# A Delivery Status Notification (bounce) is sent to the envelope
|
||||||
|
# sender (original MAIL FROM) with a null MAIL FROM (<>) to notify the
|
||||||
|
# original sender # of delays or problems with delivery. A Callback Validation
|
||||||
|
# starts the DSN process, but stops before issuing the DATA command. The
|
||||||
|
# purpose is to check whether the envelope recipient is accepted (and is
|
||||||
|
# therefore a valid email). The null MAIL FROM tells the remote
|
||||||
|
# MTA to never reply according to RFC2821 (but some braindead MTAs
|
||||||
|
# reply anyway, of course).
|
||||||
|
#
|
||||||
|
# Milters should cache CBV results and should avoid sending DSNs
|
||||||
|
# unless the sender is authenticated somehow (e.g. SPF Pass). However,
|
||||||
|
# when email is quarantined, and is not known to be a forgery, sending a DSN
|
||||||
|
# is better than silently disappearing, and a DSN is better than sending
|
||||||
|
# a normal message as notification - because MAIL FROM signing schemes
|
||||||
|
# can reject bounces of forged emails. Whatever you do, don't copy those
|
||||||
|
# assinine commercial filters that send a normal message to notify you
|
||||||
|
# that some virus is forging your email.
|
||||||
|
#
|
||||||
|
# <b>DSNs should *only* be sent to MAIL FROM addresses.</b> Never send
|
||||||
|
# a DSN or use a null MAIL FROM with an email address obtained from
|
||||||
|
# anywhere else.
|
||||||
|
#
|
||||||
import smtplib
|
import smtplib
|
||||||
import socket
|
import socket
|
||||||
from email.Message import Message
|
from email.Message import Message
|
||||||
@@ -34,6 +61,19 @@ import Milter
|
|||||||
import time
|
import time
|
||||||
import dns
|
import dns
|
||||||
|
|
||||||
|
## Send DSN.
|
||||||
|
# Try the published MX names in order, rejecting obviously bogus entries
|
||||||
|
# (like <code>localhost</code>).
|
||||||
|
# @param mailfrom the original sender we are notifying or validating
|
||||||
|
# @param receiver the HELO name of the MTA we are sending the DSN on behalf of.
|
||||||
|
# Be sure to send from an IP that matches the HELO.
|
||||||
|
# @param msg the DSN message in RFC2822 format, or None for CBV.
|
||||||
|
# @param timeout total seconds to wait for a response from an MX
|
||||||
|
# @param session Milter.dns.Session object from current incoming mail
|
||||||
|
# session to reuse its cache, or None to create a fresh one.
|
||||||
|
# @param ourfrom set to a valid email to send a normal notification from, or
|
||||||
|
# to validate emails not obtained from MAIL FROM.
|
||||||
|
# @return None on success or (status_code,msg) on failure.
|
||||||
def send_dsn(mailfrom,receiver,msg=None,timeout=600,session=None,ourfrom=''):
|
def send_dsn(mailfrom,receiver,msg=None,timeout=600,session=None,ourfrom=''):
|
||||||
"""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.
|
||||||
|
|||||||
Reference in New Issue
Block a user