Validate methods passed to @noreply, @nocallback
This commit is contained in:
+24
-12
@@ -24,10 +24,18 @@ def uniqueID():
|
|||||||
_seq_lock.release()
|
_seq_lock.release()
|
||||||
return seqno
|
return seqno
|
||||||
|
|
||||||
|
OPTIONAL_CALLBACKS = frozenset((
|
||||||
|
'connect','hello','envfrom','envrcpt','data','header','eoh','body','unknown'))
|
||||||
def nocallback(func):
|
def nocallback(func):
|
||||||
|
if not func.__name__ in OPTIONAL_CALLBACKS:
|
||||||
|
raise ValueError(
|
||||||
|
'@nocallback applied to non-optional method: '+func.__name__)
|
||||||
func.milter_protocol = 'NO'
|
func.milter_protocol = 'NO'
|
||||||
return func
|
return func
|
||||||
def noreply(func):
|
def noreply(func):
|
||||||
|
if not func.__name__ in OPTIONAL_CALLBACKS:
|
||||||
|
raise ValueError(
|
||||||
|
'@noreply applied to non-optional method: '+func.__name__)
|
||||||
func.milter_protocol = 'NR'
|
func.milter_protocol = 'NR'
|
||||||
return func
|
return func
|
||||||
|
|
||||||
@@ -40,12 +48,12 @@ class DisabledAction(RuntimeError):
|
|||||||
class Base(object):
|
class Base(object):
|
||||||
"The core class interface to the milter module."
|
"The core class interface to the milter module."
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.__actions = CURR_ACTS # all actions enabled
|
|
||||||
def _setctx(self,ctx):
|
def _setctx(self,ctx):
|
||||||
self.__ctx = ctx
|
self.__ctx = ctx
|
||||||
|
self.__actions = CURR_ACTS # all actions enabled by default
|
||||||
if ctx:
|
if ctx:
|
||||||
ctx.setpriv(self)
|
ctx.setpriv(self)
|
||||||
|
def log(self,*msg): pass
|
||||||
@nocallback
|
@nocallback
|
||||||
def connect(self,hostname,family,hostaddr): return CONTINUE
|
def connect(self,hostname,family,hostaddr): return CONTINUE
|
||||||
@nocallback
|
@nocallback
|
||||||
@@ -63,13 +71,13 @@ class Base(object):
|
|||||||
@nocallback
|
@nocallback
|
||||||
def body(self,unused): return CONTINUE
|
def body(self,unused): return CONTINUE
|
||||||
@nocallback
|
@nocallback
|
||||||
def eom(self): return CONTINUE
|
|
||||||
@nocallback
|
|
||||||
def abort(self): return CONTINUE
|
|
||||||
@nocallback
|
|
||||||
def unknown(self,cmd): return CONTINUE
|
def unknown(self,cmd): return CONTINUE
|
||||||
@nocallback
|
def eom(self): return CONTINUE
|
||||||
|
def abort(self): return CONTINUE
|
||||||
def close(self): return CONTINUE
|
def close(self): return CONTINUE
|
||||||
|
|
||||||
|
# Default negotiation sets P_NO* and P_NR* for callbacks
|
||||||
|
# marked @nocallback and @noreply respectively
|
||||||
def negotiate(self,opts):
|
def negotiate(self,opts):
|
||||||
try:
|
try:
|
||||||
self.__actions,p,f1,f2 = opts
|
self.__actions,p,f1,f2 = opts
|
||||||
@@ -85,13 +93,18 @@ class Base(object):
|
|||||||
(self.header,P_NR_HDR,P_NOHDRS)
|
(self.header,P_NR_HDR,P_NOHDRS)
|
||||||
):
|
):
|
||||||
ca = getattr(func,'milter_protocol',None)
|
ca = getattr(func,'milter_protocol',None)
|
||||||
if ca != 'NR': p &= ~nr
|
if ca != 'NR':
|
||||||
elif p & nr: print func.__name__,'NOREPLY'
|
p &= ~nr
|
||||||
if ca != 'NO': p &= ~nc
|
#elif p & nr:
|
||||||
elif p & nc: print func.__name__,'NOCALLBACK'
|
# self.log(func.__name__,'NOREPLY')
|
||||||
|
if ca != 'NO':
|
||||||
|
p &= ~nc
|
||||||
|
#elif p & nc:
|
||||||
|
# self.log(func.__name__,'NOCALLBACK')
|
||||||
opts[1] = p & ~P_RCPT_REJ & ~P_HDR_LEADSPC
|
opts[1] = p & ~P_RCPT_REJ & ~P_HDR_LEADSPC
|
||||||
opts[2] = 0
|
opts[2] = 0
|
||||||
opts[3] = 0
|
opts[3] = 0
|
||||||
|
self.log("Negotiated:",opts)
|
||||||
except:
|
except:
|
||||||
# don't change anything if something went wrong
|
# don't change anything if something went wrong
|
||||||
return ALL_OPTS
|
return ALL_OPTS
|
||||||
@@ -197,7 +210,6 @@ class Milter(Base):
|
|||||||
self.log("eoh")
|
self.log("eoh")
|
||||||
return CONTINUE
|
return CONTINUE
|
||||||
|
|
||||||
@noreply
|
|
||||||
def eom(self):
|
def eom(self):
|
||||||
"Called at the end of message."
|
"Called at the end of message."
|
||||||
self.log("eom")
|
self.log("eom")
|
||||||
|
|||||||
Reference in New Issue
Block a user