Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pymilter
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
misc
pymilter
Commits
a3530d4c
Commit
a3530d4c
authored
16 years ago
by
Stuart Gathman
Browse files
Options
Downloads
Patches
Plain Diff
Doxygen updates
parent
307c54e1
No related branches found
No related tags found
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
Doxyfile
+1
-1
1 addition, 1 deletion
Doxyfile
Milter/__init__.py
+8
-0
8 additions, 0 deletions
Milter/__init__.py
Milter/dns.py
+29
-16
29 additions, 16 deletions
Milter/dns.py
Milter/dsn.py
+41
-1
41 additions, 1 deletion
Milter/dsn.py
with
79 additions
and
18 deletions
Doxyfile
+
1
−
1
View file @
a3530d4c
...
@@ -31,7 +31,7 @@ PROJECT_NAME = pymilter
...
@@ -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.
...
...
This diff is collapsed.
Click to expand it.
Milter/__init__.py
+
8
−
0
View file @
a3530d4c
...
@@ -146,6 +146,14 @@ class Base(object):
...
@@ -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
:
...
...
This diff is collapsed.
Click to expand it.
Milter/dns.py
+
29
−
16
View file @
a3530d4c
# 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):
...
@@ -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.
...
...
This diff is collapsed.
Click to expand it.
Milter/dsn.py
+
41
−
1
View file @
a3530d4c
...
@@ -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.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 @@
...
@@ -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
...
@@ -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.
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment