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
cb319634
Commit
cb319634
authored
16 years ago
by
Stuart Gathman
Browse files
Options
Downloads
Patches
Plain Diff
Support new callbacks, including negotiate
parent
ed17f9ce
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
Milter/__init__.py
+120
-41
120 additions, 41 deletions
Milter/__init__.py
miltermodule.c
+53
-0
53 additions, 0 deletions
miltermodule.c
with
173 additions
and
41 deletions
Milter/__init__.py
+
120
−
41
View file @
cb319634
...
...
@@ -30,13 +30,124 @@ def uniqueID():
_seq_lock
.
release
()
return
seqno
class
Milter
:
"""
A simple class interface to the milter module.
"""
def
nocallback
(
func
):
func
.
milter_protocol
=
'
NO
'
return
func
def
noreply
(
func
):
func
.
milter_protocol
=
'
NR
'
return
func
class
DisabledAction
(
RuntimeError
):
pass
class
Base
(
object
):
def
__init__
(
self
):
self
.
__actions
=
CURR_ACTS
# all actions enabled
def
_setctx
(
self
,
ctx
):
self
.
__ctx
=
ctx
if
ctx
:
ctx
.
setpriv
(
self
)
@nocallback
def
connect
(
self
,
hostname
,
family
,
hostaddr
):
return
CONTINUE
@nocallback
def
hello
(
self
,
hostname
):
return
CONTINUE
@nocallback
def
envfrom
(
self
,
f
,
*
str
):
return
CONTINUE
@nocallback
def
envrcpt
(
self
,
to
,
*
str
):
return
CONTINUE
@nocallback
def
data
(
self
):
return
CONTINUE
@nocallback
def
header
(
self
,
field
,
value
):
return
CONTINUE
@nocallback
def
eoh
(
self
):
return
CONTINUE
@nocallback
def
body
(
self
,
unused
):
return
CONTINUE
@nocallback
def
eom
(
self
):
return
CONTINUE
@nocallback
def
abort
(
self
):
return
CONTINUE
@nocallback
def
unknown
(
self
,
cmd
):
return
CONTINUE
@nocallback
def
close
(
self
):
return
CONTINUE
def
negotiate
(
self
,
opts
):
try
:
self
.
__actions
,
p
,
f1
,
f2
=
opts
for
func
,
nr
,
nc
in
(
(
self
.
connect
,
P_NR_CONN
,
P_NOCONNECT
),
(
self
.
hello
,
P_NR_HELO
,
P_NOHELO
),
(
self
.
envfrom
,
P_NR_MAIL
,
P_NOMAIL
),
(
self
.
envrcpt
,
P_NR_RCPT
,
P_NORCPT
),
(
self
.
data
,
P_NR_DATA
,
P_NODATA
),
(
self
.
unknown
,
P_NR_UNKN
,
P_NOUNKNOWN
),
(
self
.
eoh
,
P_NR_EOH
,
P_NOEOH
),
(
self
.
body
,
P_NR_BODY
,
P_NOBODY
),
(
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
'
p
[
1
]
=
p
&
~
P_RCPT_REJ
&
~
P_HDR_LEADSPC
except
:
# don't change anything if something went wrong
return
ALL_OPTS
return
CONTINUE
# Milter methods which can be invoked from callbacks
def
getsymval
(
self
,
sym
):
return
self
.
__ctx
.
getsymval
(
sym
)
# If sendmail does not support setmlreply, then only the
# first msg line is used.
def
setreply
(
self
,
rcode
,
xcode
=
None
,
msg
=
None
,
*
ml
):
return
self
.
__ctx
.
setreply
(
rcode
,
xcode
,
msg
,
*
ml
)
def
setsmlist
(
self
,
stage
,
macros
):
if
not
self
.
__actions
&
SETSMLIST
:
raise
DisabledAction
(
"
SETSMLIST
"
)
if
type
(
macros
)
in
(
list
,
tuple
):
macros
=
'
'
.
join
(
macros
)
return
self
.
__ctx
.
setsmlist
(
stage
,
macros
)
# Milter methods which can only be called from eom callback.
def
addheader
(
self
,
field
,
value
,
idx
=-
1
):
if
not
self
.
__actions
&
ADDHDRS
:
raise
DisabledAction
(
"
ADDHDRS
"
)
return
self
.
__ctx
.
addheader
(
field
,
value
,
idx
)
def
chgheader
(
self
,
field
,
idx
,
value
):
if
not
self
.
__actions
&
CHGHDRS
:
raise
DisabledAction
(
"
CHGHDRS
"
)
return
self
.
__ctx
.
chgheader
(
field
,
idx
,
value
)
def
addrcpt
(
self
,
rcpt
,
params
=
None
):
if
not
self
.
__actions
&
ADDRCPT
:
raise
DisabledAction
(
"
ADDRCPT
"
)
return
self
.
__ctx
.
addrcpt
(
rcpt
,
params
)
def
delrcpt
(
self
,
rcpt
):
if
not
self
.
__actions
&
DELRCPT
:
raise
DisabledAction
(
"
DELRCPT
"
)
return
self
.
__ctx
.
delrcpt
(
rcpt
)
def
replacebody
(
self
,
body
):
if
not
self
.
__actions
&
MODBODY
:
raise
DisabledAction
(
"
MODBODY
"
)
return
self
.
__ctx
.
replacebody
(
body
)
def
chgfrom
(
self
,
sender
,
params
=
None
):
if
not
self
.
__actions
&
CHGFROM
:
raise
DisabledAction
(
"
CHGFROM
"
)
return
self
.
__ctx
.
chgfrom
(
sender
,
params
)
# When quarantined, a message goes into the mailq as if to be delivered,
# but delivery is deferred until the message is unquarantined.
def
quarantine
(
self
,
reason
):
if
not
self
.
__actions
&
QUARANTINE
:
raise
DisabledAction
(
"
QUARANTINE
"
)
return
self
.
__ctx
.
quarantine
(
reason
)
def
progress
(
self
):
return
self
.
__ctx
.
progress
()
class
Milter
(
Base
):
"""
A simple class interface to the milter module.
"""
# user replaceable callbacks
def
log
(
self
,
*
msg
):
...
...
@@ -96,42 +207,6 @@ class Milter:
self
.
log
(
"
close
"
)
return
CONTINUE
# Milter methods which can be invoked from callbacks
def
getsymval
(
self
,
sym
):
return
self
.
__ctx
.
getsymval
(
sym
)
# If sendmail does not support setmlreply, then only the
# first msg line is used.
def
setreply
(
self
,
rcode
,
xcode
=
None
,
msg
=
None
,
*
ml
):
return
self
.
__ctx
.
setreply
(
rcode
,
xcode
,
msg
,
*
ml
)
# Milter methods which can only be called from eom callback.
def
addheader
(
self
,
field
,
value
,
idx
=-
1
):
return
self
.
__ctx
.
addheader
(
field
,
value
,
idx
)
def
chgheader
(
self
,
field
,
idx
,
value
):
return
self
.
__ctx
.
chgheader
(
field
,
idx
,
value
)
def
addrcpt
(
self
,
rcpt
,
params
=
None
):
return
self
.
__ctx
.
addrcpt
(
rcpt
,
params
)
def
delrcpt
(
self
,
rcpt
):
return
self
.
__ctx
.
delrcpt
(
rcpt
)
def
replacebody
(
self
,
body
):
return
self
.
__ctx
.
replacebody
(
body
)
def
chgfrom
(
self
,
sender
,
params
=
None
):
return
self
.
__ctx
.
chgfrom
(
sender
,
params
)
# When quarantined, a message goes into the mailq as if to be delivered,
# but delivery is deferred until the message is unquarantined.
def
quarantine
(
self
,
reason
):
return
self
.
__ctx
.
quarantine
(
reason
)
def
progress
(
self
):
return
self
.
__ctx
.
progress
()
factory
=
Milter
def
connectcallback
(
ctx
,
hostname
,
family
,
hostaddr
):
...
...
@@ -214,7 +289,11 @@ def runmilter(name,socketname,timeout = 0):
milter
.
setconn
(
socketname
)
if
timeout
>
0
:
milter
.
settimeout
(
timeout
)
# The name *must* match the X line in sendmail.cf (supposedly)
milter
.
register
(
name
)
milter
.
register
(
name
,
data
=
lambda
ctx
:
ctx
.
getpriv
().
data
(),
unknown
=
lambda
ctx
,
cmd
:
ctx
.
getpriv
().
unknown
(
cmd
),
negotiate
=
lambda
ctx
,
opt
:
ctx
.
getpriv
().
negotiate
(
opt
)
)
start_seq
=
_seq
try
:
milter
.
main
()
...
...
This diff is collapsed.
Click to expand it.
miltermodule.c
+
53
−
0
View file @
cb319634
...
...
@@ -35,6 +35,9 @@ $ python setup.py help
libraries=["milter","smutil","resolv"]
* $Log$
* Revision 1.18 2009/05/21 21:53:05 customdesigned
* First cut at support unknown, data, negotiate callbacks.
*
* Revision 1.17 2009/02/06 04:28:08 customdesigned
* Oops! Missing options argument pointer for addrcpt.
*
...
...
@@ -1367,6 +1370,27 @@ milter_progress(PyObject *self, PyObject *args) {
}
#endif
#ifdef SMFIF_SETSMLIST
static
char
milter_setsmlist__doc__
[]
=
"setsmlist(stage,macrolist) -> None
\n
\
Tell the MTA which macro values we are interested in for a given stage"
;
static
PyObject
*
milter_setsmlist
(
PyObject
*
self
,
PyObject
*
args
)
{
SMFICTX
*
ctx
;
PyThreadState
*
t
;
int
stage
=
0
;
char
*
smlist
=
0
;
if
(
!
PyArg_ParseTuple
(
args
,
"is:setsmlist"
,
&
stage
,
&
smlist
))
return
NULL
;
ctx
=
_find_context
(
self
);
if
(
ctx
==
NULL
)
return
NULL
;
t
=
PyEval_SaveThread
();
return
_thread_return
(
t
,
smfi_setsmlist
(
ctx
,
stage
,
smlist
),
"cannot set macro list"
);
}
#endif
static
PyMethodDef
context_methods
[]
=
{
{
"getsymval"
,
milter_getsymval
,
METH_VARARGS
,
milter_getsymval__doc__
},
{
"setreply"
,
milter_setreply
,
METH_VARARGS
,
milter_setreply__doc__
},
...
...
@@ -1385,6 +1409,9 @@ static PyMethodDef context_methods[] = {
#endif
#ifdef SMFIF_CHGFROM
{
"chgfrom"
,
milter_chgfrom
,
METH_VARARGS
,
milter_chgfrom__doc__
},
#endif
#ifdef SMFIF_SETSMLIST
{
"setsmlist"
,
milter_setsmlist
,
METH_VARARGS
,
milter_setsmlist__doc__
},
#endif
{
NULL
,
NULL
}
};
...
...
@@ -1505,8 +1532,34 @@ initmilter(void) {
#ifdef SMFIF_CHGFROM
setitem
(
d
,
"CHGFROM"
,
SMFIF_CHGFROM
);
#endif
#ifdef SMFIF_SETSMLIST
setitem
(
d
,
"SETSMLIST"
,
SMFIF_SETSMLIST
);
#endif
#ifdef SMFIF_ALL_OPTS
setitem
(
d
,
"P_RCPT_REJ"
,
SMFIP_RCPT_REJ
);
setitem
(
d
,
"P_NR_CONN"
,
SMFIP_NR_CONN
);
setitem
(
d
,
"P_NR_HELO"
,
SMFIP_NR_HELO
);
setitem
(
d
,
"P_NR_MAIL"
,
SMFIP_NR_MAIL
);
setitem
(
d
,
"P_NR_RCPT"
,
SMFIP_NR_RCPT
);
setitem
(
d
,
"P_NR_DATA"
,
SMFIP_NR_DATA
);
setitem
(
d
,
"P_NR_UNKN"
,
SMFIP_NR_UNKN
);
setitem
(
d
,
"P_NR_EOH"
,
SMFIP_NR_EOH
);
setitem
(
d
,
"P_NR_BODY"
,
SMFIP_NR_BODY
);
setitem
(
d
,
"P_NR_HDR"
,
SMFIP_NR_HDR
);
setitem
(
d
,
"P_NOCONNECT"
,
SMFIP_NR_CONN
);
setitem
(
d
,
"P_NOHELO"
,
SMFIP_NR_HELO
);
setitem
(
d
,
"P_NOMAIL"
,
SMFIP_NR_MAIL
);
setitem
(
d
,
"P_NORCPT"
,
SMFIP_NR_RCPT
);
setitem
(
d
,
"P_NODATA"
,
SMFIP_NR_DATA
);
setitem
(
d
,
"P_NOUNKNOWN"
,
SMFIP_NR_UNKN
);
setitem
(
d
,
"P_NOEOH"
,
SMFIP_NR_EOH
);
setitem
(
d
,
"P_NOBODY"
,
SMFIP_NR_BODY
);
setitem
(
d
,
"P_NOHDRS"
,
SMFIP_NR_HDR
);
setitem
(
d
,
"P_HDR_LEADSPC"
,
SMFIP_HDR_LEADSPC
);
setitem
(
d
,
"P_SKIP"
,
SMFIP_SKIP
);
setitem
(
d
,
"ALL_OPTS"
,
SMFIF_ALL_OPTS
);
setitem
(
d
,
"SKIP"
,
SMFIS_SKIP
);
setitem
(
d
,
"NOREPLY"
,
SMFIS_NOREPLY
);
#endif
setitem
(
d
,
"CONTINUE"
,
SMFIS_CONTINUE
);
setitem
(
d
,
"REJECT"
,
SMFIS_REJECT
);
...
...
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