📄 proto.m4
字号:
')
# prepend an empty "forward host" on the front
R$+ $: <> $1
ifdef(`LUSER_RELAY', `dnl
# send unrecognized local users to a relay host
ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `
R< > $+ + $* $: < ? $L > <+ $2> $(user $1 $) look up user+
R< > $+ $: < ? $L > < > $(user $1 $) look up user
R< ? $* > < $* > $+ <> $: < > $3 $2 found; strip $L
R< ? $* > < $* > $+ $: < $1 > $3 $2 not found', `
R< > $+ $: < $L > $(user $1 $) look up user
R< $* > $+ <> $: < > $2 found; strip $L')',
`dnl')
# see if we have a relay or a hub
R< > $+ $: < $H > $1 try hub
R< > $+ $: < $R > $1 try relay
ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `
R< > $+ $@ $1', `
R< > $+ $: < > < $1 <> $&h > nope, restore +detail
R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail
R< > < $+ <> $* > $: < > < $1 > else discard
R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part
R< > < $+ > + $* $#_LOCAL_ $@ $2 $: @ $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') strip the extra +
R< > < $+ > $@ $1 no +detail
R$+ $: $1 <> $&h add +detail back in
R$+ <> + $* $: $1 + $2 check whether +detail
R$+ <> $* $: $1 else discard')
R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension
R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension
R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 >
R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 >
ifdef(`_MAILER_TABLE_', `dnl
###################################################################
### Ruleset 90 -- try domain part of mailertable entry ###
dnl input: LeftPartOfDomain <RightPartOfDomain> FullAddress
###################################################################
SMailertable=90
dnl shift and check
dnl %2 is not documented in cf/README
R$* <$- . $+ > $* $: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4
dnl it is $~[ instead of $- to avoid matches on IPv6 addresses
R$* <$~[ : $* > $* $>MailerToTriple < $2 : $3 > $4 check -- resolved?
R$* < . $+ > $* $@ $>Mailertable $1 . <$2> $3 no -- strip & try again
dnl is $2 always empty?
R$* < $* > $* $: < $(mailertable . $@ $1$2 $) > $3 try "."
R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 "." found?
dnl return full address
R< $* > $* $@ $2 no mailertable match',
`dnl')
###################################################################
### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ###
dnl input: in general: <[mailer:]host> lp<@domain>rest
dnl <> address -> address
dnl <error:d.s.n:text> -> error
dnl <error:text> -> error
dnl <mailer:user@host> lp<@domain>rest -> mailer host user
dnl <mailer:host> address -> mailer host address
dnl <localdomain> address -> address
dnl <[IPv6 number]> address -> relay number address
dnl <host> address -> relay host address
###################################################################
SMailerToTriple=95
R< > $* $@ $1 strip off null relay
R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4
R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2
R< local : $* > $* $>CanonLocal < $1 > $2
R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user
R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer
R< $=w > $* $@ $2 delete local host
R< [ IPv6 $+ ] > $* $#_RELAY_ $@ $(dequote $1 $) $: $2 use unqualified mailer
R< $+ > $* $#_RELAY_ $@ $1 $: $2 use unqualified mailer
###################################################################
### Ruleset CanonLocal -- canonify local: syntax ###
dnl input: <user> address
dnl <x> <@host> : rest -> Recurse rest
dnl <x> p1 $=O p2 <@host> -> Recurse p1 $=O p2
dnl <> user <@host> rest -> local user@host user
dnl <> user -> local user user
dnl <user@host> lp <@domain> rest -> <user> lp <@host> [cont]
dnl <user> lp <@host> rest -> local lp@host user
dnl <user> lp -> local lp user
###################################################################
SCanonLocal
# strip local host from routed addresses
R< $* > < @ $+ > : $+ $@ $>Recurse $3
R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4
# strip trailing dot from any host name that may appear
R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 >
# handle local: syntax -- use old user, either with or without host
R< > $* < @ $* > $* $#_LOCAL_ $@ $1@$2 $: $1
R< > $+ $#_LOCAL_ $@ $1 $: $1
# handle local:user@host syntax -- ignore host part
R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 >
# handle local:user syntax
R< $+ > $* <@ $* > $* $#_LOCAL_ $@ $2@$3 $: $1
R< $+ > $* $#_LOCAL_ $@ $2 $: $1
###################################################################
### Ruleset 93 -- convert header names to masqueraded form ###
###################################################################
SMasqHdr=93
ifdef(`_GENERICS_TABLE_', `dnl
# handle generics database
ifdef(`_GENERICS_ENTIRE_DOMAIN_',
dnl if generics should be applied add a @ as mark
`R$+ < @ $* $=G . > $: < $1@$2$3 > $1 < @ $2$3 . > @ mark',
`R$+ < @ $=G . > $: < $1@$2 > $1 < @ $2 . > @ mark')
R$+ < @ *LOCAL* > $: < $1@$j > $1 < @ *LOCAL* > @ mark
dnl workspace: either user<@domain> or <user@domain> user <@domain> @
dnl ignore the first case for now
dnl if it has the mark lookup full address
R< $+ > $+ < $* > @ $: < $(generics $1 $: @ $1 $) > $2 < $3 >
dnl workspace: ... or <match|@user@domain> user <@domain>
dnl no match, try user+detail@domain
R<@$+ + $* @ $+> $+ < @ $+ >
$: < $(generics $1+*@$3 $@ $2 $:@$1 + $2@$3 $) > $4 < @ $5 >
R<@$+ + $* @ $+> $+ < @ $+ >
$: < $(generics $1@$3 $: $) > $4 < @ $5 >
dnl no match, remove mark
R<@$+ > $+ < @ $+ > $: < > $2 < @ $3 >
dnl no match, try @domain for exceptions
R< > $+ < @ $+ . > $: < $(generics @$2 $@ $1 $: $) > $1 < @ $2 . >
dnl workspace: ... or <match> user <@domain>
dnl no match, try local part
R< > $+ < @ $+ > $: < $(generics $1 $: $) > $1 < @ $2 >
R< > $+ + $* < @ $+ > $: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 >
R< > $+ + $* < @ $+ > $: < $(generics $1 $: $) > $1 + $2 < @ $3 >
R< $* @ $* > $* < $* > $@ $>canonify $1 @ $2 found qualified
R< $+ > $* < $* > $: $>canonify $1 @ *LOCAL* found unqualified
R< > $* $: $1 not found',
`dnl')
# do not masquerade anything in class N
R$* < @ $* $=N . > $@ $1 < @ $2 $3 . >
# special case the users that should be exposed
R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed
ifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
`R$=E < @ $* $=M . > $@ $1 < @ $2 $3 . >',
`R$=E < @ $=M . > $@ $1 < @ $2 . >')
ifdef(`_LIMITED_MASQUERADE_', `dnl',
`R$=E < @ $=w . > $@ $1 < @ $2 . >')
# handle domain-specific masquerading
ifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
`R$* < @ $* $=M . > $* $: $1 < @ $2 $3 . @ $M > $4 convert masqueraded doms',
`R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms')
ifdef(`_LIMITED_MASQUERADE_', `dnl',
`R$* < @ $=w . > $* $: $1 < @ $2 . @ $M > $3')
R$* < @ *LOCAL* > $* $: $1 < @ $j . @ $M > $2
R$* < @ $+ @ > $* $: $1 < @ $2 > $3 $M is null
R$* < @ $+ @ $+ > $* $: $1 < @ $3 . > $4 $M is not null
###################################################################
### Ruleset 94 -- convert envelope names to masqueraded form ###
###################################################################
SMasqEnv=94
ifdef(`_MASQUERADE_ENVELOPE_',
`R$+ $@ $>MasqHdr $1',
`R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2')
###################################################################
### Ruleset 98 -- local part of ruleset zero (can be null) ###
###################################################################
SParseLocal=98
undivert(3)dnl LOCAL_RULE_0
ifdef(`_LDAP_ROUTING_', `dnl
SLDAPExpand
# do the LDAP lookups
R<$+><$+> $: <$(ldapmra $2 $: $)> <$(ldapmh $2 $: $)> <$1> <$2>
# if mailRoutingAddress and local or non-existant mailHost,
# return the new mailRoutingAddress
R< $+ > < $=w > < $+ > < $+ > $@ $>Parse0 $>canonify $1
R< $+ > < > < $+ > < $+ > $@ $>Parse0 $>canonify $1
# if mailRoutingAddress and non-local mailHost,
# relay to mailHost with new mailRoutingAddress
R< $+ > < $+ > < $+ > < $+ > $#_RELAY_ $@ $2 $: $>canonify $1
# if no mailRoutingAddress and local mailHost,
# return original address
R< > < $=w > <$+> <$+> $@ $2
# if no mailRoutingAddress and non-local mailHost,
# relay to mailHost with original address
R< > < $+ > <$+> <$+> $#_RELAY_ $@ $1 $: $2
# if no mailRoutingAddress and no mailHost,
# try @domain
R< > < > <$+> <$+ @ $+> $@ $>LDAPExpand <$1> <@ $3>
# if no mailRoutingAddress and no mailHost and this was a domain attempt,
ifelse(_LDAP_ROUTING_, `_MUST_EXIST_', `dnl
# user does not exist
R< > < > <$+> <@ $+> $#error $@ nouser $: "550 User unknown"',
`dnl
# return the original address
R< > < > <$+> <@ $+> $@ $1')',
`dnl')
ifelse(substr(confDELIVERY_MODE,0,1), `d', `errprint(`WARNING: Antispam rules not available in deferred delivery mode.
')')
ifdef(`_ACCESS_TABLE_', `dnl
######################################################################
### LookUpDomain -- search for domain in access database
###
### Parameters:
### <$1> -- key (domain name)
### <$2> -- default (what to return if not found in db)
dnl must not be empty
### <$3> -- passthru (additional data passed unchanged through)
### <$4> -- mark (must be <(!|+) single-token>)
### ! does lookup only with tag
### + does lookup with and without tag
dnl returns: <default> <passthru>
dnl <result> <passthru>
######################################################################
SLookUpDomain
dnl remove IPv6 mark and dequote address
dnl it is a bit ugly because it is checked on each "iteration"
R<[IPv6 $-]> <$+> <$*> <$*> $: <[$(dequote $1 $)]> <$2> <$3> <$4>
dnl workspace <key> <default> <passthru> <mark>
dnl lookup with tag (in front, no delimiter here)
R<$*> <$+> <$*> <$- $-> $: < $(access $5`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3> <$4 $5>
dnl workspace <result-of-lookup|?> <key> <default> <passthru> <mark>
ifdef(`_FFR_LOOKUPDOTDOMAIN', `dnl omit first component: lookup .rest
R<?> <$+.$+> <$+> <$*> <$- $-> $: < $(access $5`'_TAG_DELIM_`'.$2 $: ? $) > <$1.$2> <$3> <$4> <$5 $6>', `dnl')
dnl lookup without tag?
R<?> <$+> <$+> <$*> <+ $*> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <+ $4>
ifdef(`_FFR_LOOKUPDOTDOMAIN', `dnl omit first component: lookup .rest
R<?> <$+.$+> <$+> <$*> <+ $*> $: < $(access .$2 $: ? $) > <$1.$2> <$3> <$4> <+ $5>', `dnl')
dnl lookup IP address (no check is done whether it is an IP number!)
R<?> <[$+.$-]> <$+> <$*> <$*> $@ $>LookUpDomain <[$1]> <$3> <$4> <$5>
dnl lookup IPv6 address
R<?> <[$+:$-]> <$+> <$*> <$*> $: $>LookUpDomain <[$1]> <$3> <$4> <$5>
dnl not found, but subdomain: try again
R<?> <$+.$+> <$+> <$*> <$*> $@ $>LookUpDomain <$2> <$3> <$4> <$5>
dnl not found, no subdomain: return default
R<?> <$+> <$+> <$*> <$*> $@ <$2> <$3>
dnl return result of lookup
R<$*> <$+> <$+> <$*> <$*> $@ <$1> <$4>
######################################################################
### LookUpAddress -- search for host address in access database
###
### Parameters:
### <$1> -- key (dot quadded host address)
### <$2> -- default (what to return if not found in db)
dnl must not be empty
### <$3> -- passthru (additional data passed through)
### <$4> -- mark (must be <(!|+) single-token>)
### ! does lookup only with tag
### + does lookup with and without tag
dnl returns: <default> <passthru>
dnl <result> <passthru>
######################################################################
SLookUpAddress
dnl lookup with tag
R<$+> <$+> <$*> <$- $+> $: < $(access $5`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3> <$4 $5>
dnl lookup without tag
R<?> <$+> <$+> <$*> <+ $+> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <+ $4>
dnl no match; IPv6: remove last part
R<?> <$+:$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5>
dnl no match; IPv4: remove last part
R<?> <$+.$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5>
dnl no match: return default
R<?> <$+> <$+> <$*> <$*> $@ <$2> <$3>
dnl match: return result
R<$*> <$+> <$+> <$*> <$*> $@ <$1> <$4>',
`dnl')
######################################################################
### CanonAddr -- Convert an address into a standard form for
### relay checking. Route address syntax is
### crudely converted into a %-hack address.
###
### Parameters:
### $1 -- full recipient address
###
### Returns:
### parsed address, not in source route form
dnl user%host%host<@domain>
dnl host!user<@domain>
######################################################################
SCanonAddr
R$* $: $>Parse0 $>canonify $1 make domain canonical
ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl
R< @ $+ > : $* @ $* < @ $1 > : $2 % $3 change @ to % in src route
R$* < @ $+ > : $* : $* $3 $1 < @ $2 > : $4 change to % hack.
R$* < @ $+ > : $* $3 $1 < @ $2 >
dnl')
######################################################################
### ParseRecipient -- Strip off hosts in $=R as well as possibly
### $* $=m or the access database.
### Check user portion for host separators.
###
### Parameters:
### $1 -- full recipient address
###
### Returns:
### parsed, non-local-relaying address
######################################################################
SParseRecipient
dnl mark and canonify address
R$* $: <?> $>CanonAddr $1
dnl workspace: <?> localpart<@domain[.]>
R<?> $* < @ $* . > <?> $1 < @ $2 > strip trailing dots
dnl workspace: <?> localpart<@domain>
R<?> $- < @ $* > $: <?> $(dequote $1 $) < @ $2 > dequote local part
# if no $=O character, no host in the user portion, we are done
R<?> $* $=O $* < @ $* > $: <NO> $1 $2 $3 < @ $4>
dnl no $=O in localpart: return
R<?> $* $@ $1
dnl workspace: <?> localpart<@domain>, where localpart contains $=O
dnl mark everything which has an "authorized" domain with <RELAY>
ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl
# if we relay, check username portion for user%host so host can be checked also
R<NO> $* < @ $* $=m > $: <RELAY> $1 < @ $2 $3 >', `dnl')
ifdef(`_RELAY_MX_SERVED_', `dnl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -