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