More doxygen docs.
This commit is contained in:
@@ -552,8 +552,7 @@ WARN_LOGFILE =
|
|||||||
# directories like "/usr/src/myproject". Separate the files or directories
|
# directories like "/usr/src/myproject". Separate the files or directories
|
||||||
# with spaces.
|
# with spaces.
|
||||||
|
|
||||||
INPUT = mime.py \
|
INPUT = mime.py doc/mainpage.py doc/milter.py Milter
|
||||||
Milter
|
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||||
|
|||||||
+44
-2
@@ -4,7 +4,7 @@
|
|||||||
# Clients generally subclass Milter.Base and define callback
|
# Clients generally subclass Milter.Base and define callback
|
||||||
# methods.
|
# methods.
|
||||||
#
|
#
|
||||||
# author Stuart D. Gathman <stuart@bmsi.com>
|
# @author Stuart D. Gathman <stuart@bmsi.com>
|
||||||
# Copyright 2001,2009 Business Management Systems, Inc.
|
# Copyright 2001,2009 Business Management Systems, Inc.
|
||||||
# This code is under the GNU General Public License. See COPYING for details.
|
# This code is under the GNU General Public License. See COPYING for details.
|
||||||
|
|
||||||
@@ -224,6 +224,7 @@ class Base(object):
|
|||||||
# RCPT TO command (and as delivered to the envrcpt callback), for example
|
# RCPT TO command (and as delivered to the envrcpt callback), for example
|
||||||
# "self.addrcpt('<foo@example.com>')".
|
# "self.addrcpt('<foo@example.com>')".
|
||||||
# @param rcpt the message recipient
|
# @param rcpt the message recipient
|
||||||
|
# @param params an optional list of ESMTP parameters
|
||||||
def addrcpt(self,rcpt,params=None):
|
def addrcpt(self,rcpt,params=None):
|
||||||
if not self._actions & ADDRCPT: raise DisabledAction("ADDRCPT")
|
if not self._actions & ADDRCPT: raise DisabledAction("ADDRCPT")
|
||||||
return self._ctx.addrcpt(rcpt,params)
|
return self._ctx.addrcpt(rcpt,params)
|
||||||
@@ -242,6 +243,12 @@ class Base(object):
|
|||||||
if not self._actions & MODBODY: raise DisabledAction("MODBODY")
|
if not self._actions & MODBODY: raise DisabledAction("MODBODY")
|
||||||
return self._ctx.replacebody(body)
|
return self._ctx.replacebody(body)
|
||||||
|
|
||||||
|
## Change the SMTP envelope sender address.
|
||||||
|
# The syntax of the sender is that same as used in the SMTP
|
||||||
|
# MAIL FROM command (and as delivered to the envfrom callback),
|
||||||
|
# for example <code>self.chgfrom('<bar@example.com>')</code>.
|
||||||
|
# @param sender the new sender address
|
||||||
|
# @param params an optional list of ESMTP parameters
|
||||||
def chgfrom(self,sender,params=None):
|
def chgfrom(self,sender,params=None):
|
||||||
if not self._actions & CHGFROM: raise DisabledAction("CHGFROM")
|
if not self._actions & CHGFROM: raise DisabledAction("CHGFROM")
|
||||||
return self._ctx.chgfrom(sender,params)
|
return self._ctx.chgfrom(sender,params)
|
||||||
@@ -325,13 +332,19 @@ class Milter(Base):
|
|||||||
self.log("close")
|
self.log("close")
|
||||||
return CONTINUE
|
return CONTINUE
|
||||||
|
|
||||||
|
## The milter connection factory
|
||||||
|
# This factory method is called for each connection to create the
|
||||||
|
# python object that tracks the connection. It should return
|
||||||
|
# an object derived from Milter.Base.
|
||||||
factory = Milter
|
factory = Milter
|
||||||
|
|
||||||
|
## @private
|
||||||
def negotiate_callback(ctx,opts):
|
def negotiate_callback(ctx,opts):
|
||||||
m = factory()
|
m = factory()
|
||||||
m._setctx(ctx)
|
m._setctx(ctx)
|
||||||
return m.negotiate(opts)
|
return m.negotiate(opts)
|
||||||
|
|
||||||
|
## @private
|
||||||
def connect_callback(ctx,hostname,family,hostaddr,nr_mask=P_NR_CONN):
|
def connect_callback(ctx,hostname,family,hostaddr,nr_mask=P_NR_CONN):
|
||||||
m = ctx.getpriv()
|
m = ctx.getpriv()
|
||||||
if not m:
|
if not m:
|
||||||
@@ -341,6 +354,7 @@ def connect_callback(ctx,hostname,family,hostaddr,nr_mask=P_NR_CONN):
|
|||||||
m._setctx(ctx)
|
m._setctx(ctx)
|
||||||
return m.connect(hostname,family,hostaddr)
|
return m.connect(hostname,family,hostaddr)
|
||||||
|
|
||||||
|
## @private
|
||||||
def close_callback(ctx):
|
def close_callback(ctx):
|
||||||
m = ctx.getpriv()
|
m = ctx.getpriv()
|
||||||
if not m: return CONTINUE
|
if not m: return CONTINUE
|
||||||
@@ -350,8 +364,10 @@ def close_callback(ctx):
|
|||||||
m._setctx(None) # release milterContext
|
m._setctx(None) # release milterContext
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
|
## Convert ESMTP parameters with values to a keyword dictionary.
|
||||||
|
# @deprecated You probably want Milter.param2dict instead.
|
||||||
def dictfromlist(args):
|
def dictfromlist(args):
|
||||||
"Convert ESMTP parm list to keyword dictionary."
|
"Convert ESMTP parms with values to keyword dictionary."
|
||||||
kw = {}
|
kw = {}
|
||||||
for s in args:
|
for s in args:
|
||||||
pos = s.find('=')
|
pos = s.find('=')
|
||||||
@@ -359,6 +375,16 @@ def dictfromlist(args):
|
|||||||
kw[s[:pos].upper()] = s[pos+1:]
|
kw[s[:pos].upper()] = s[pos+1:]
|
||||||
return kw
|
return kw
|
||||||
|
|
||||||
|
## Convert ESMTP parm list to keyword dictionary.
|
||||||
|
# Params with no value are set to None in the dictionary.
|
||||||
|
# @param str list of param strings of the form "NAME" or "NAME=VALUE"
|
||||||
|
def param2dict(str):
|
||||||
|
"Convert ESMTP parm list to keyword dictionary."
|
||||||
|
pairs = [x.split('=',1) for x in str]
|
||||||
|
for e in pairs:
|
||||||
|
if len(e) < 2: e.append(None)
|
||||||
|
return dict([(k.upper(),v) for k,v in pairs])
|
||||||
|
|
||||||
def envcallback(c,args):
|
def envcallback(c,args):
|
||||||
"""Call function c with ESMTP parms converted to keyword parameters.
|
"""Call function c with ESMTP parms converted to keyword parameters.
|
||||||
Can be used in the envfrom and/or envrcpt callbacks to process
|
Can be used in the envfrom and/or envrcpt callbacks to process
|
||||||
@@ -373,6 +399,22 @@ def envcallback(c,args):
|
|||||||
pargs.append(s)
|
pargs.append(s)
|
||||||
return c(*pargs,**kw)
|
return c(*pargs,**kw)
|
||||||
|
|
||||||
|
## Run the milter.
|
||||||
|
# The MTA can communicate with the milter by means of a
|
||||||
|
# unix, inet, or inet6 socket. By default, a unix domain socket
|
||||||
|
# is used. It must not exist,
|
||||||
|
# and sendmail will throw warnings if, eg, the file is under a
|
||||||
|
# group or world writable directory.
|
||||||
|
# <pre>
|
||||||
|
# setconn('unix:/var/run/pythonfilter')
|
||||||
|
# setconn('inet:8800') # listen on ANY interface
|
||||||
|
# setconn('inet:7871@@publichost') # listen on a specific interface
|
||||||
|
# setconn('inet6:8020')
|
||||||
|
# </pre>
|
||||||
|
# @param name the name of the milter known by the MTA
|
||||||
|
# @param socketname the descriptor of the unix socket
|
||||||
|
# @param timeout the time in secs the MTA should wait for a response before
|
||||||
|
# considering this milter dead
|
||||||
def runmilter(name,socketname,timeout = 0):
|
def runmilter(name,socketname,timeout = 0):
|
||||||
# This bit is here on the assumption that you will be starting this filter
|
# This bit is here on the assumption that you will be starting this filter
|
||||||
# before sendmail. If sendmail is not running and the socket already exists,
|
# before sendmail. If sendmail is not running and the socket already exists,
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
## @mainpage Writing Milters in Python
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# At the lowest level, the <code>milter</code> module provides a thin wrapper
|
||||||
|
# around the <a href="https://www.milter.org/developers/api/index"> sendmail
|
||||||
|
# libmilter API</a>. This API lets you register callbacks for a number of
|
||||||
|
# events in the process of sendmail receiving a message via SMTP. These
|
||||||
|
# events include the initial connection from a MTA, the envelope sender and
|
||||||
|
# recipients, the top level mail headers, and the message body. There are
|
||||||
|
# options to mangle all of these components of the message as it passes through
|
||||||
|
# the milter.
|
||||||
|
#
|
||||||
|
# At the next level, the <code>Milter</code> module (note the case difference)
|
||||||
|
# provides a Python friendly object oriented wrapper for the low level API. To
|
||||||
|
# use the Milter module, an application registers a 'factory' to create an
|
||||||
|
# object for each connection from a MTA to sendmail. These connection objects
|
||||||
|
# must provide methods corresponding to the libmilter callback events.
|
||||||
|
#
|
||||||
|
# Each event method returns a code to tell sendmail whether to proceed with
|
||||||
|
# processing the message. This is a big advantage of milters over other mail
|
||||||
|
# filtering systems. Unwanted mail can be stopped in its tracks at the
|
||||||
|
# earliest possible point.
|
||||||
|
#
|
||||||
|
# The <code>Milter.Base</code> class provides default implementations for
|
||||||
|
# event methods that do nothing, and also provides wrappers for the libmilter
|
||||||
|
# methods to mutate the message. It automatically negotiates with MTA
|
||||||
|
# which protocol steps need to be processed by the milter, based on
|
||||||
|
# which callback methods are overridden.
|
||||||
|
#
|
||||||
|
# The <code>Milter.Milter</code> class provides an alternate default
|
||||||
|
# implementation that logs the main milter events, but otherwise does nothing.
|
||||||
|
# It is provided for compatibility.
|
||||||
|
#
|
||||||
|
# The <code>mime</code> module provides a wrapper for the Python email package
|
||||||
|
# that fixes some bugs, and simplifies modifying selected parts of a MIME
|
||||||
|
# message.
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Document miltermodule for Doxygen
|
||||||
|
#
|
||||||
|
|
||||||
|
## @package milter
|
||||||
|
#
|
||||||
|
# A thin wrapper around libmilter.
|
||||||
|
#
|
||||||
|
|
||||||
|
class milterContext(object):
|
||||||
|
def getsymval(self,sym): pass
|
||||||
|
def setreply(self,rcode,xcode,*msg): pass
|
||||||
|
def addheader(self,name,value,idx=-1): pass
|
||||||
|
def chgheader(self,name,idx,value): pass
|
||||||
|
def addrcpt(self,rcpt,params=None): pass
|
||||||
|
def delrcpt(self,rcpt): pass
|
||||||
|
def replacebody(self,data): pass
|
||||||
|
def setpriv(self,priv): pass
|
||||||
|
def getpriv(self): pass
|
||||||
|
def quarantine(self,reason): pass
|
||||||
|
def progress(self): pass
|
||||||
|
def chgfrom(self,sender,param=None): pass
|
||||||
|
def setsmlist(self,stage,macrolist): pass
|
||||||
|
|
||||||
|
class error(Exception): pass
|
||||||
|
|
||||||
|
def set_flags(flags): pass
|
||||||
|
def set_connect_callback(cb): pass
|
||||||
|
def set_helo_callback(cb): pass
|
||||||
|
def set_envfrom_callback(cb): pass
|
||||||
|
def set_envrcpt_callback(cb): pass
|
||||||
|
def set_header_callback(cb): pass
|
||||||
|
def set_eoh_callback(cb): pass
|
||||||
|
def set_body_callback(cb): pass
|
||||||
|
def set_abort_callback(cb): pass
|
||||||
|
def set_close_callback(cb): pass
|
||||||
|
def set_exception_policy(code): pass
|
||||||
|
def register(name,negotiate=None,unknown=None,data=None): pass
|
||||||
|
def opensocket(rmsock): pass
|
||||||
|
def main(): pass
|
||||||
|
def setdbg(lev): pass
|
||||||
|
def settimeout(secs): pass
|
||||||
|
def setbacklog(n): pass
|
||||||
|
def setconn(s): pass
|
||||||
|
def stop(): pass
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
# $Log$
|
# $Log$
|
||||||
|
# Revision 1.5 2005/07/20 14:49:43 customdesigned
|
||||||
|
# Handle corrupt and empty ZIP files.
|
||||||
|
#
|
||||||
# Revision 1.4 2005/06/17 01:49:39 customdesigned
|
# Revision 1.4 2005/06/17 01:49:39 customdesigned
|
||||||
# Handle zip within zip.
|
# Handle zip within zip.
|
||||||
#
|
#
|
||||||
@@ -70,8 +73,12 @@
|
|||||||
# with old milter code.
|
# with old milter code.
|
||||||
#
|
#
|
||||||
|
|
||||||
# This module provides a "defang" function to replace naughty attachments
|
## @package mime
|
||||||
# with a warning message.
|
# This module provides a "defang" function to replace naughty attachments.
|
||||||
|
#
|
||||||
|
# We also provide workarounds for bugs in the email module that comes
|
||||||
|
# with python. The "bugs" fixed mostly come up only with malformed
|
||||||
|
# messages - but that is what you have when dealing with spam.
|
||||||
|
|
||||||
# Author: Stuart D. Gathman <stuart@bmsi.com>
|
# Author: Stuart D. Gathman <stuart@bmsi.com>
|
||||||
# Copyright 2001,2002,2003,2004,2005 Business Management Systems, Inc.
|
# Copyright 2001,2002,2003,2004,2005 Business Management Systems, Inc.
|
||||||
@@ -93,6 +100,8 @@ from email import Errors
|
|||||||
|
|
||||||
from types import ListType,StringType
|
from types import ListType,StringType
|
||||||
|
|
||||||
|
## Return a list of filenames in a zip file.
|
||||||
|
# Embedded zip files are recursively expanded.
|
||||||
def zipnames(txt):
|
def zipnames(txt):
|
||||||
fp = StringIO.StringIO(txt)
|
fp = StringIO.StringIO(txt)
|
||||||
zipf = zipfile.ZipFile(fp,'r')
|
zipf = zipfile.ZipFile(fp,'r')
|
||||||
@@ -103,6 +112,8 @@ def zipnames(txt):
|
|||||||
names += zipnames(zipf.read(nm))
|
names += zipnames(zipf.read(nm))
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
## Fix multipart handling in email.Generator.
|
||||||
|
#
|
||||||
class MimeGenerator(Generator):
|
class MimeGenerator(Generator):
|
||||||
def _dispatch(self, msg):
|
def _dispatch(self, msg):
|
||||||
# Get the Content-Type: for the message, then try to dispatch to
|
# Get the Content-Type: for the message, then try to dispatch to
|
||||||
@@ -142,11 +153,8 @@ def _unquotevalue(value):
|
|||||||
|
|
||||||
from email.Message import _parseparam
|
from email.Message import _parseparam
|
||||||
|
|
||||||
# Enhance email.Message
|
## Enhance email.Message
|
||||||
# - Provide a headerchange event for integration with Milter
|
#
|
||||||
# Headerchange attribute can be assigned a function to be called when
|
|
||||||
# changing headers. The signature is:
|
|
||||||
# headerchange(msg,name,value) -> None
|
|
||||||
# - Track modifications to headers of body or any part independently
|
# - Track modifications to headers of body or any part independently
|
||||||
|
|
||||||
class MimeMessage(Message):
|
class MimeMessage(Message):
|
||||||
@@ -158,6 +166,12 @@ class MimeMessage(Message):
|
|||||||
self.submsg = None
|
self.submsg = None
|
||||||
self.modified = False
|
self.modified = False
|
||||||
|
|
||||||
|
## @var headerchange
|
||||||
|
# Provide a headerchange event for integration with Milter.
|
||||||
|
# The headerchange attribute can be assigned a function to be called when
|
||||||
|
# changing headers. The signature is:
|
||||||
|
# headerchange(msg,name,value) -> None
|
||||||
|
|
||||||
def get_param(self, param, failobj=None, header='content-type', unquote=True):
|
def get_param(self, param, failobj=None, header='content-type', unquote=True):
|
||||||
val = Message.get_param(self,param,failobj,header,unquote)
|
val = Message.get_param(self,param,failobj,header,unquote)
|
||||||
if val != failobj and param == 'boundary' and unquote:
|
if val != failobj and param == 'boundary' and unquote:
|
||||||
|
|||||||
Reference in New Issue
Block a user