proto.m4
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:66k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. divert(-1)
  2. #
  3. # Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  4. # All rights reserved.
  5. # Copyright (c) 1983, 1995 Eric P. Allman.  All rights reserved.
  6. # Copyright (c) 1988, 1993
  7. # The Regents of the University of California.  All rights reserved.
  8. #
  9. # By using this file, you agree to the terms and conditions set
  10. # forth in the LICENSE file which can be found at the top level of
  11. # the sendmail distribution.
  12. #
  13. #
  14. divert(0)
  15. VERSIONID(`$Id: proto.m4,v 8.404 1999/12/09 19:06:12 gshapiro Exp $')
  16. MAILER(local)dnl
  17. define(`CF_LEVEL', `9')dnl
  18. # level CF_LEVEL config file format
  19. V`'CF_LEVEL/ifdef(`VENDOR_NAME', `VENDOR_NAME', `Berkeley')
  20. divert(-1)
  21. # do some sanity checking
  22. ifdef(`__OSTYPE__',,
  23. `errprint(`*** ERROR: No system type defined (use OSTYPE macro)
  24. ')')
  25. # pick our default mailers
  26. ifdef(`confSMTP_MAILER',, `define(`confSMTP_MAILER', `esmtp')')
  27. ifdef(`confLOCAL_MAILER',, `define(`confLOCAL_MAILER', `local')')
  28. ifdef(`confRELAY_MAILER',,
  29. `define(`confRELAY_MAILER',
  30. `ifdef(`_MAILER_smtp_', `relay',
  31. `ifdef(`_MAILER_uucp', `uucp-new', `unknown')')')')
  32. ifdef(`confUUCP_MAILER',, `define(`confUUCP_MAILER', `uucp-old')')
  33. define(`_SMTP_', `confSMTP_MAILER')dnl for readability only
  34. define(`_LOCAL_', `confLOCAL_MAILER')dnl for readability only
  35. define(`_RELAY_', `confRELAY_MAILER')dnl for readability only
  36. define(`_UUCP_', `confUUCP_MAILER')dnl for readability only
  37. # back compatibility with old config files
  38. ifdef(`confDEF_GROUP_ID',
  39. `errprint(`*** confDEF_GROUP_ID is obsolete.
  40.     Use confDEF_USER_ID with a colon in the value instead.
  41. ')')
  42. ifdef(`confREAD_TIMEOUT',
  43. `errprint(`*** confREAD_TIMEOUT is obsolete.
  44.     Use individual confTO_<timeout> parameters instead.
  45. ')')
  46. ifdef(`confMESSAGE_TIMEOUT',
  47. `define(`_ARG_', index(confMESSAGE_TIMEOUT, /))
  48.  ifelse(_ARG_, -1,
  49. `define(`confTO_QUEUERETURN', confMESSAGE_TIMEOUT)',
  50. `define(`confTO_QUEUERETURN',
  51. substr(confMESSAGE_TIMEOUT, 0, _ARG_))
  52.  define(`confTO_QUEUEWARN',
  53. substr(confMESSAGE_TIMEOUT, eval(_ARG_+1)))')')
  54. ifdef(`confMIN_FREE_BLOCKS', `ifelse(index(confMIN_FREE_BLOCKS, /), -1,,
  55. `errprint(`*** compound confMIN_FREE_BLOCKS is obsolete.
  56.     Use confMAX_MESSAGE_SIZE for the second part of the value.
  57. ')')')
  58. # Sanity check on ldap_routing feature
  59. # If the user doesn't specify a new map, they better have given as a
  60. # default LDAP specification which has the LDAP base (and most likely the host)
  61. ifdef(`confLDAP_DEFAULT_SPEC',, `ifdef(`_LDAP_ROUTING_WARN_', `errprint(`
  62. WARNING: Using default FEATURE(ldap_routing) map definition(s)
  63. without setting confLDAP_DEFAULT_SPEC option.
  64. ')')')dnl
  65. # clean option definitions below....
  66. define(`_OPTION', `ifdef(`$2', `O $1`'ifelse(defn(`$2'), `',, `=$2')', `#O $1`'ifelse(`$3', `',,`=$3')')')dnl
  67. dnl required to "rename" the check_* rulesets...
  68. define(`_U_',ifdef(`_DELAY_CHECKS_',`',`_'))
  69. divert(0)dnl
  70. # override file safeties - setting this option compromises system security,
  71. # addressing the actual file configuration problem is preferred
  72. # need to set this before any file actions are encountered in the cf file
  73. _OPTION(DontBlameSendmail, `confDONT_BLAME_SENDMAIL', `safe')
  74. # default LDAP map specification
  75. # need to set this now before any LDAP maps are defined
  76. _OPTION(LDAPDefaultSpec, `confLDAP_DEFAULT_SPEC', `-h localhost')
  77. ##################
  78. #   local info   #
  79. ##################
  80. Cwlocalhost
  81. ifdef(`USE_CW_FILE',
  82. `# file containing names of hosts for which we receive email
  83. Fw`'confCW_FILE',
  84. `dnl')
  85. # my official domain name
  86. # ... `define' this only if sendmail cannot automatically determine your domain
  87. ifdef(`confDOMAIN_NAME', `Dj`'confDOMAIN_NAME', `#Dj$w.Foo.COM')
  88. CP.
  89. ifdef(`UUCP_RELAY',
  90. `# UUCP relay host
  91. DY`'UUCP_RELAY
  92. CPUUCP
  93. ')dnl
  94. ifdef(`BITNET_RELAY',
  95. `#  BITNET relay host
  96. DB`'BITNET_RELAY
  97. CPBITNET
  98. ')dnl
  99. ifdef(`DECNET_RELAY',
  100. `define(`_USE_DECNET_SYNTAX_', 1)dnl
  101. # DECnet relay host
  102. DC`'DECNET_RELAY
  103. CPDECNET
  104. ')dnl
  105. ifdef(`FAX_RELAY',
  106. `# FAX relay host
  107. DF`'FAX_RELAY
  108. CPFAX
  109. ')dnl
  110. # "Smart" relay host (may be null)
  111. DS`'ifdef(`SMART_HOST', SMART_HOST)
  112. ifdef(`LUSER_RELAY', `dnl
  113. # place to which unknown users should be forwarded
  114. Kuser user -m -a<>
  115. DL`'LUSER_RELAY',
  116. `dnl')
  117. # operators that cannot be in local usernames (i.e., network indicators)
  118. CO @ % ifdef(`_NO_UUCP_', `', `!')
  119. # a class with just dot (for identifying canonical names)
  120. C..
  121. # a class with just a left bracket (for identifying domain literals)
  122. C[[
  123. ifdef(`_ACCESS_TABLE_', `dnl
  124. # access_db acceptance class
  125. C{Accept}OK RELAY
  126. ifdef(`_DELAY_CHECKS_',`dnl
  127. ifdef(`_BLACKLIST_RCPT_',`dnl
  128. # possible access_db RHS for spam friends/haters
  129. C{SpamTag}SPAMFRIEND SPAMHATER')')',
  130. `dnl')
  131. ifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_',`dnl',`dnl
  132. # Resolve map (to check if a host exists in check_mail)
  133. Kresolve host -a<OK> -T<TEMP>')
  134. ifdef(`confCR_FILE', `dnl
  135. # Hosts that will permit relaying ($=R)
  136. FR`'confCR_FILE',
  137. `dnl')
  138. # who I send unqualified names to (null means deliver locally)
  139. DR`'ifdef(`LOCAL_RELAY', LOCAL_RELAY)
  140. # who gets all local email traffic ($R has precedence for unqualified names)
  141. DH`'ifdef(`MAIL_HUB', MAIL_HUB)
  142. # dequoting map
  143. Kdequote dequote
  144. divert(0)dnl # end of nullclient diversion
  145. # class E: names that should be exposed as from this host, even if we masquerade
  146. # class L: names that should be delivered locally, even if we have a relay
  147. # class M: domains that should be converted to $M
  148. # class N: domains that should not be converted to $M
  149. #CL root
  150. undivert(5)dnl
  151. ifdef(`_VIRTHOSTS_', `CR$={VirtHost}', `dnl')
  152. # who I masquerade as (null for no masquerading) (see also $=M)
  153. DM`'ifdef(`MASQUERADE_NAME', MASQUERADE_NAME)
  154. # my name for error messages
  155. ifdef(`confMAILER_NAME', `Dn`'confMAILER_NAME', `#DnMAILER-DAEMON')
  156. undivert(6)dnl LOCAL_CONFIG
  157. include(_CF_DIR_`m4/version.m4')
  158. ###############
  159. #   Options   #
  160. ###############
  161. # strip message body to 7 bits on input?
  162. _OPTION(SevenBitInput, `confSEVEN_BIT_INPUT', `False')
  163. # 8-bit data handling
  164. _OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', `adaptive')
  165. # wait for alias file rebuild (default units: minutes)
  166. _OPTION(AliasWait, `confALIAS_WAIT', `5m')
  167. # location of alias file
  168. _OPTION(AliasFile, `ALIAS_FILE', `MAIL_SETTINGS_DIR`'aliases')
  169. # minimum number of free blocks on filesystem
  170. _OPTION(MinFreeBlocks, `confMIN_FREE_BLOCKS', `100')
  171. # maximum message size
  172. _OPTION(MaxMessageSize, `confMAX_MESSAGE_SIZE', `1000000')
  173. # substitution for space (blank) characters
  174. _OPTION(BlankSub, `confBLANK_SUB', `_')
  175. # avoid connecting to "expensive" mailers on initial submission?
  176. _OPTION(HoldExpensive, `confCON_EXPENSIVE', `False')
  177. # checkpoint queue runs after every N successful deliveries
  178. _OPTION(CheckpointInterval, `confCHECKPOINT_INTERVAL', `10')
  179. # default delivery mode
  180. _OPTION(DeliveryMode, `confDELIVERY_MODE', `background')
  181. # automatically rebuild the alias database?
  182. # NOTE: There is a potential for a denial of service attack if this is set.
  183. #       This option is deprecated and will be removed from a future version.
  184. _OPTION(AutoRebuildAliases, `confAUTO_REBUILD', `False')
  185. # error message header/file
  186. _OPTION(ErrorHeader, `confERROR_MESSAGE', `MAIL_SETTINGS_DIR`'error-header')
  187. # error mode
  188. _OPTION(ErrorMode, `confERROR_MODE', `print')
  189. # save Unix-style "From_" lines at top of header?
  190. _OPTION(SaveFromLine, `confSAVE_FROM_LINES', `False')
  191. # temporary file mode
  192. _OPTION(TempFileMode, `confTEMP_FILE_MODE', `0600')
  193. # match recipients against GECOS field?
  194. _OPTION(MatchGECOS, `confMATCH_GECOS', `False')
  195. # maximum hop count
  196. _OPTION(MaxHopCount, `confMAX_HOP', `17')
  197. # location of help file
  198. O HelpFile=ifdef(`HELP_FILE', HELP_FILE, `MAIL_SETTINGS_DIR`'helpfile')
  199. # ignore dots as terminators in incoming messages?
  200. _OPTION(IgnoreDots, `confIGNORE_DOTS', `False')
  201. # name resolver options
  202. _OPTION(ResolverOptions, `confBIND_OPTS', `+AAONLY')
  203. # deliver MIME-encapsulated error messages?
  204. _OPTION(SendMimeErrors, `confMIME_FORMAT_ERRORS', `True')
  205. # Forward file search path
  206. _OPTION(ForwardPath, `confFORWARD_PATH', `/var/forward/$u:$z/.forward.$w:$z/.forward')
  207. # open connection cache size
  208. _OPTION(ConnectionCacheSize, `confMCI_CACHE_SIZE', `2')
  209. # open connection cache timeout
  210. _OPTION(ConnectionCacheTimeout, `confMCI_CACHE_TIMEOUT', `5m')
  211. # persistent host status directory
  212. _OPTION(HostStatusDirectory, `confHOST_STATUS_DIRECTORY', `.hoststat')
  213. # single thread deliveries (requires HostStatusDirectory)?
  214. _OPTION(SingleThreadDelivery, `confSINGLE_THREAD_DELIVERY', `False')
  215. # use Errors-To: header?
  216. _OPTION(UseErrorsTo, `confUSE_ERRORS_TO', `False')
  217. # log level
  218. _OPTION(LogLevel, `confLOG_LEVEL', `10')
  219. # send to me too, even in an alias expansion?
  220. _OPTION(MeToo, `confME_TOO', `True')
  221. # verify RHS in newaliases?
  222. _OPTION(CheckAliases, `confCHECK_ALIASES', `False')
  223. # default messages to old style headers if no special punctuation?
  224. _OPTION(OldStyleHeaders, `confOLD_STYLE_HEADERS', `False')
  225. # SMTP daemon options
  226. ifelse(defn(`confDAEMON_OPTIONS'), `', `dnl',
  227. `errprint(WARNING: `confDAEMON_OPTIONS' is no longer valid.  See cf/README for more information.
  228. )'dnl
  229. `DAEMON_OPTIONS(`confDAEMON_OPTIONS')')
  230. ifelse(defn(`_DPO_'), `', `O DaemonPortOptions=Name=MTA', `_DPO_')
  231. ifdef(`_NO_MSA_', `dnl', `O DaemonPortOptions=Port=587, Name=MSA, M=E')
  232. # SMTP client options
  233. _OPTION(ClientPortOptions, `confCLIENT_OPTIONS', `Address=0.0.0.0')
  234. # privacy flags
  235. _OPTION(PrivacyOptions, `confPRIVACY_FLAGS', `authwarnings')
  236. # who (if anyone) should get extra copies of error messages
  237. _OPTION(PostmasterCopy, `confCOPY_ERRORS_TO', `Postmaster')
  238. # slope of queue-only function
  239. _OPTION(QueueFactor, `confQUEUE_FACTOR', `600000')
  240. # queue directory
  241. O QueueDirectory=ifdef(`QUEUE_DIR', QUEUE_DIR, `/var/spool/mqueue')
  242. # timeouts (many of these)
  243. _OPTION(Timeout.initial, `confTO_INITIAL', `5m')
  244. _OPTION(Timeout.connect, `confTO_CONNECT', `5m')
  245. _OPTION(Timeout.iconnect, `confTO_ICONNECT', `5m')
  246. _OPTION(Timeout.helo, `confTO_HELO', `5m')
  247. _OPTION(Timeout.mail, `confTO_MAIL', `10m')
  248. _OPTION(Timeout.rcpt, `confTO_RCPT', `1h')
  249. _OPTION(Timeout.datainit, `confTO_DATAINIT', `5m')
  250. _OPTION(Timeout.datablock, `confTO_DATABLOCK', `1h')
  251. _OPTION(Timeout.datafinal, `confTO_DATAFINAL', `1h')
  252. _OPTION(Timeout.rset, `confTO_RSET', `5m')
  253. _OPTION(Timeout.quit, `confTO_QUIT', `2m')
  254. _OPTION(Timeout.misc, `confTO_MISC', `2m')
  255. _OPTION(Timeout.command, `confTO_COMMAND', `1h')
  256. _OPTION(Timeout.ident, `confTO_IDENT', `30s')
  257. _OPTION(Timeout.fileopen, `confTO_FILEOPEN', `60s')
  258. _OPTION(Timeout.control, `confTO_CONTROL', `2m')
  259. _OPTION(Timeout.queuereturn, `confTO_QUEUERETURN', `5d')
  260. _OPTION(Timeout.queuereturn.normal, `confTO_QUEUERETURN_NORMAL', `5d')
  261. _OPTION(Timeout.queuereturn.urgent, `confTO_QUEUERETURN_URGENT', `2d')
  262. _OPTION(Timeout.queuereturn.non-urgent, `confTO_QUEUERETURN_NONURGENT', `7d')
  263. _OPTION(Timeout.queuewarn, `confTO_QUEUEWARN', `4h')
  264. _OPTION(Timeout.queuewarn.normal, `confTO_QUEUEWARN_NORMAL', `4h')
  265. _OPTION(Timeout.queuewarn.urgent, `confTO_QUEUEWARN_URGENT', `1h')
  266. _OPTION(Timeout.queuewarn.non-urgent, `confTO_QUEUEWARN_NONURGENT', `12h')
  267. _OPTION(Timeout.hoststatus, `confTO_HOSTSTATUS', `30m')
  268. _OPTION(Timeout.resolver.retrans, `confTO_RESOLVER_RETRANS', `5s')
  269. _OPTION(Timeout.resolver.retrans.first, `confTO_RESOLVER_RETRANS_FIRST', `5s')
  270. _OPTION(Timeout.resolver.retrans.normal, `confTO_RESOLVER_RETRANS_NORMAL', `5s')
  271. _OPTION(Timeout.resolver.retry, `confTO_RESOLVER_RETRY', `4')
  272. _OPTION(Timeout.resolver.retry.first, `confTO_RESOLVER_RETRY_FIRST', `4')
  273. _OPTION(Timeout.resolver.retry.normal, `confTO_RESOLVER_RETRY_NORMAL', `4')
  274. # should we not prune routes in route-addr syntax addresses?
  275. _OPTION(DontPruneRoutes, `confDONT_PRUNE_ROUTES', `False')
  276. # queue up everything before forking?
  277. _OPTION(SuperSafe, `confSAFE_QUEUE', `True')
  278. # status file
  279. O StatusFile=ifdef(`STATUS_FILE', `STATUS_FILE', `MAIL_SETTINGS_DIR`'statistics')
  280. # time zone handling:
  281. #  if undefined, use system default
  282. #  if defined but null, use TZ envariable passed in
  283. #  if defined and non-null, use that info
  284. ifelse(confTIME_ZONE, `USE_SYSTEM', `#O TimeZoneSpec=',
  285. confTIME_ZONE, `USE_TZ', `O TimeZoneSpec=',
  286. `O TimeZoneSpec=confTIME_ZONE')
  287. # default UID (can be username or userid:groupid)
  288. _OPTION(DefaultUser, `confDEF_USER_ID', `mailnull')
  289. # list of locations of user database file (null means no lookup)
  290. _OPTION(UserDatabaseSpec, `confUSERDB_SPEC', `MAIL_SETTINGS_DIR`'userdb')
  291. # fallback MX host
  292. _OPTION(FallbackMXhost, `confFALLBACK_MX', `fall.back.host.net')
  293. # if we are the best MX host for a site, try it directly instead of config err
  294. _OPTION(TryNullMXList, `confTRY_NULL_MX_LIST', `False')
  295. # load average at which we just queue messages
  296. _OPTION(QueueLA, `confQUEUE_LA', `8')
  297. # load average at which we refuse connections
  298. _OPTION(RefuseLA, `confREFUSE_LA', `12')
  299. # maximum number of children we allow at one time
  300. _OPTION(MaxDaemonChildren, `confMAX_DAEMON_CHILDREN', `12')
  301. # maximum number of new connections per second
  302. _OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `3')
  303. # work recipient factor
  304. _OPTION(RecipientFactor, `confWORK_RECIPIENT_FACTOR', `30000')
  305. # deliver each queued job in a separate process?
  306. _OPTION(ForkEachJob, `confSEPARATE_PROC', `False')
  307. # work class factor
  308. _OPTION(ClassFactor, `confWORK_CLASS_FACTOR', `1800')
  309. # work time factor
  310. _OPTION(RetryFactor, `confWORK_TIME_FACTOR', `90000')
  311. # shall we sort the queue by hostname first?
  312. _OPTION(QueueSortOrder, `confQUEUE_SORT_ORDER', `priority')
  313. # minimum time in queue before retry
  314. _OPTION(MinQueueAge, `confMIN_QUEUE_AGE', `30m')
  315. # default character set
  316. _OPTION(DefaultCharSet, `confDEF_CHAR_SET', `iso-8859-1')
  317. # service switch file (ignored on Solaris, Ultrix, OSF/1, others)
  318. _OPTION(ServiceSwitchFile, `confSERVICE_SWITCH_FILE', `MAIL_SETTINGS_DIR`'service.switch')
  319. # hosts file (normally /etc/hosts)
  320. _OPTION(HostsFile, `confHOSTS_FILE', `/etc/hosts')
  321. # dialup line delay on connection failure
  322. _OPTION(DialDelay, `confDIAL_DELAY', `10s')
  323. # action to take if there are no recipients in the message
  324. _OPTION(NoRecipientAction, `confNO_RCPT_ACTION', `add-to-undisclosed')
  325. # chrooted environment for writing to files
  326. _OPTION(SafeFileEnvironment, `confSAFE_FILE_ENV', `/arch')
  327. # are colons OK in addresses?
  328. _OPTION(ColonOkInAddr, `confCOLON_OK_IN_ADDR', `True')
  329. # how many jobs can you process in the queue?
  330. _OPTION(MaxQueueRunSize, `confMAX_QUEUE_RUN_SIZE', `10000')
  331. # shall I avoid expanding CNAMEs (violates protocols)?
  332. _OPTION(DontExpandCnames, `confDONT_EXPAND_CNAMES', `False')
  333. # SMTP initial login message (old $e macro)
  334. _OPTION(SmtpGreetingMessage, `confSMTP_LOGIN_MSG', `$j Sendmail $v ready at $b')
  335. # UNIX initial From header format (old $l macro)
  336. _OPTION(UnixFromLine, `confFROM_LINE', `From $g $d')
  337. # From: lines that have embedded newlines are unwrapped onto one line
  338. _OPTION(SingleLineFromHeader, `confSINGLE_LINE_FROM_HEADER', `False')
  339. # Allow HELO SMTP command that does not `include' a host name
  340. _OPTION(AllowBogusHELO, `confALLOW_BOGUS_HELO', `False')
  341. # Characters to be quoted in a full name phrase (@,;:()[] are automatic)
  342. _OPTION(MustQuoteChars, `confMUST_QUOTE_CHARS', `.')
  343. # delimiter (operator) characters (old $o macro)
  344. _OPTION(OperatorChars, `confOPERATORS', `.:@[]')
  345. # shall I avoid calling initgroups(3) because of high NIS costs?
  346. _OPTION(DontInitGroups, `confDONT_INIT_GROUPS', `False')
  347. # are group-writable `:include:' and .forward files (un)trustworthy?
  348. _OPTION(UnsafeGroupWrites, `confUNSAFE_GROUP_WRITES', `True')
  349. # where do errors that occur when sending errors get sent?
  350. _OPTION(DoubleBounceAddress, `confDOUBLE_BOUNCE_ADDRESS', `postmaster')
  351. # where to save bounces if all else fails
  352. _OPTION(DeadLetterDrop, `confDEAD_LETTER_DROP', `/var/tmp/dead.letter')
  353. # what user id do we assume for the majority of the processing?
  354. _OPTION(RunAsUser, `confRUN_AS_USER', `sendmail')
  355. # maximum number of recipients per SMTP envelope
  356. _OPTION(MaxRecipientsPerMessage, `confMAX_RCPTS_PER_MESSAGE', `100')
  357. # shall we get local names from our installed interfaces?
  358. _OPTION(DontProbeInterfaces, `confDONT_PROBE_INTERFACES', `False')
  359. # Return-Receipt-To: header implies DSN request
  360. _OPTION(RrtImpliesDsn, `confRRT_IMPLIES_DSN', `False')
  361. # override connection address (for testing)
  362. _OPTION(ConnectOnlyTo, `confCONNECT_ONLY_TO', `0.0.0.0')
  363. # Trusted user for file ownership and starting the daemon
  364. _OPTION(TrustedUser, `confTRUSTED_USER', `root')
  365. # Control socket for daemon management
  366. _OPTION(ControlSocketName, `confCONTROL_SOCKET_NAME', `/var/spool/mqueue/.control')
  367. # Maximum MIME header length to protect MUAs
  368. _OPTION(MaxMimeHeaderLength, `confMAX_MIME_HEADER_LENGTH', `0/0')
  369. # Maximum length of the sum of all headers
  370. _OPTION(MaxHeadersLength, `confMAX_HEADERS_LENGTH', `32768')
  371. # Maximum depth of alias recursion
  372. _OPTION(MaxAliasRecursion, `confMAX_ALIAS_RECURSION', `10')
  373. # location of pid file
  374. _OPTION(PidFile, `confPID_FILE', `/var/run/sendmail.pid')
  375. # Prefix string for the process title shown on 'ps' listings
  376. _OPTION(ProcessTitlePrefix, `confPROCESS_TITLE_PREFIX', `prefix')
  377. # Data file (df) memory-buffer file maximum size
  378. _OPTION(DataFileBufferSize, `confDF_BUFFER_SIZE', `4096')
  379. # Transcript file (xf) memory-buffer file maximum size
  380. _OPTION(XscriptFileBufferSize, `confXF_BUFFER_SIZE', `4096')
  381. # list of authentication mechanisms
  382. _OPTION(AuthMechanisms, `confAUTH_MECHANISMS', `GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5')
  383. # default authentication information for outgoing connections
  384. _OPTION(DefaultAuthInfo, `confDEF_AUTH_INFO', `MAIL_SETTINGS_DIR`'default-auth-info')
  385. # try to authenticate? (Try when available/only when Authenticated)
  386. _OPTION(AuthOptions, `confAUTH_OPTIONS', `T')
  387. ###########################
  388. #   Message precedences   #
  389. ###########################
  390. Pfirst-class=0
  391. Pspecial-delivery=100
  392. Plist=-30
  393. Pbulk=-60
  394. Pjunk=-100
  395. #####################
  396. #   Trusted users   #
  397. #####################
  398. # this is equivalent to setting class "t"
  399. ifdef(`_USE_CT_FILE_', `', `#')Ft`'ifdef(`confCT_FILE', confCT_FILE, `MAIL_SETTINGS_DIR`'trusted-users')
  400. Troot
  401. Tdaemon
  402. ifdef(`_NO_UUCP_', `dnl', `Tuucp')
  403. ifdef(`confTRUSTED_USERS', `T`'confTRUSTED_USERS', `dnl')
  404. #########################
  405. #   Format of headers   #
  406. #########################
  407. ifdef(`confFROM_HEADER',, `define(`confFROM_HEADER', `$?x$x <$g>$|$g$.')')dnl
  408. H?P?Return-Path: <$g>
  409. HReceived: confRECEIVED_HEADER
  410. H?D?Resent-Date: $a
  411. H?D?Date: $a
  412. H?F?Resent-From: confFROM_HEADER
  413. H?F?From: confFROM_HEADER
  414. H?x?Full-Name: $x
  415. # HPosted-Date: $a
  416. # H?l?Received-Date: $b
  417. H?M?Resent-Message-Id: <$t.$i@$j>
  418. H?M?Message-Id: <$t.$i@$j>
  419. #
  420. ######################################################################
  421. ######################################################################
  422. #####
  423. ##### REWRITING RULES
  424. #####
  425. ######################################################################
  426. ######################################################################
  427. ############################################
  428. ###  Ruleset 3 -- Name Canonicalization  ###
  429. ############################################
  430. Scanonify=3
  431. # handle null input (translate to <@> special case)
  432. R$@ $@ <@>
  433. # strip group: syntax (not inside angle brackets!) and trailing semicolon
  434. R$* $: $1 <@> mark addresses
  435. R$* < $* > $* <@> $: $1 < $2 > $3 unmark <addr>
  436. R@ $* <@> $: @ $1 unmark @host:...
  437. R$* :: $* <@> $: $1 :: $2 unmark node::addr
  438. R:`include': $* <@> $: :`include': $1 unmark :`include':...
  439. R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr
  440. R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon
  441. R$* : $* <@> $: $2 strip colon if marked
  442. R$* <@> $: $1 unmark
  443. R$* ;    $1 strip trailing semi
  444. R$* < $* ; >    $1 < $2 > bogus bracketed semi
  445. # null input now results from list:; syntax
  446. R$@ $@ :; <@>
  447. # strip angle brackets -- note RFC733 heuristic to get innermost item
  448. R$* $: < $1 > housekeeping <>
  449. R$+ < $* >    < $2 > strip excess on left
  450. R< $* > $+    < $1 > strip excess on right
  451. R<> $@ < @ > MAIL FROM:<> case
  452. R< $+ > $: $1 remove housekeeping <>
  453. ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl
  454. # make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later
  455. R@ $+ , $+ @ $1 : $2 change all "," to ":"
  456. # localize and dispose of route-based addresses
  457. R@ $+ : $+ $@ $>Canonify2 < @$1 > : $2 handle <route-addr>
  458. dnl',`dnl
  459. # strip route address <@a,@b,@c:user@d> -> <user@d>
  460. R@ $+ , $+ $2
  461. R@ $+ : $+ $2
  462. dnl')
  463. # find focus for list syntax
  464. R $+ : $* ; @ $+ $@ $>Canonify2 $1 : $2 ; < @ $3 > list syntax
  465. R $+ : $* ; $@ $1 : $2; list syntax
  466. # find focus for @ syntax addresses
  467. R$+ @ $+ $: $1 < @ $2 > focus on domain
  468. R$+ < $+ @ $+ > $1 $2 < @ $3 > move gaze right
  469. R$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical
  470. # do some sanity checking
  471. R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs
  472. ifdef(`_NO_UUCP_', `dnl',
  473. `# convert old-style addresses to a domain-based address
  474. R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names
  475. R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps
  476. R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains
  477. ')
  478. ifdef(`_USE_DECNET_SYNTAX_',
  479. `# convert node::user addresses into a domain-based address
  480. R$- :: $+ $@ $>Canonify2 $2 < @ $1 .DECNET > resolve DECnet names
  481. R$- . $- :: $+ $@ $>Canonify2 $3 < @ $1.$2 .DECNET > numeric DECnet addr
  482. ',
  483. `dnl')
  484. # if we have % signs, take the rightmost one
  485. R$* % $* $1 @ $2 First make them all @s.
  486. R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last.
  487. R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish
  488. # else we must be a local name
  489. R$* $@ $>Canonify2 $1
  490. ################################################
  491. ###  Ruleset 96 -- bottom half of ruleset 3  ###
  492. ################################################
  493. SCanonify2=96
  494. # handle special cases for local names
  495. R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all
  496. R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain
  497. ifdef(`_NO_UUCP_', `dnl',
  498. `R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain')
  499. # check for IPv6 domain literal (save quoted form)
  500. R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr
  501. R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal
  502. R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr
  503. # check for IPv4 domain literal
  504. R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d]
  505. R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal
  506. R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr
  507. ifdef(`_DOMAIN_TABLE_', `dnl
  508. # look up domains in the domain table
  509. R$* < @ $+ > $*  $: $1 < @ $(domaintable $2 $) > $3', `dnl')
  510. undivert(2)dnl LOCAL_RULE_3
  511. ifdef(`_BITDOMAIN_TABLE_', `dnl
  512. # handle BITNET mapping
  513. R$* < @ $+ .BITNET > $* $: $1 < @ $(bitdomain $2 $: $2.BITNET $) > $3', `dnl')
  514. ifdef(`_UUDOMAIN_TABLE_', `dnl
  515. # handle UUCP mapping
  516. R$* < @ $+ .UUCP > $* $: $1 < @ $(uudomain $2 $: $2.UUCP $) > $3', `dnl')
  517. ifdef(`_NO_UUCP_', `dnl',
  518. `ifdef(`UUCP_RELAY',
  519. `# pass UUCP addresses straight through
  520. R$* < @ $+ . UUCP > $* $@ $1 < @ $2 . UUCP . > $3',
  521. `# if really UUCP, handle it immediately
  522. ifdef(`_CLASS_U_',
  523. `R$* < @ $=U . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl')
  524. ifdef(`_CLASS_V_',
  525. `R$* < @ $=V . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl')
  526. ifdef(`_CLASS_W_',
  527. `R$* < @ $=W . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl')
  528. ifdef(`_CLASS_X_',
  529. `R$* < @ $=X . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl')
  530. ifdef(`_CLASS_Y_',
  531. `R$* < @ $=Y . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl')
  532. ifdef(`_NO_CANONIFY_', `dnl', `dnl
  533. # try UUCP traffic as a local address
  534. R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3
  535. R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3')
  536. ')')
  537. dnl which daemon flags are set?
  538. R$* $: $&{daemon_flags} $| $1
  539. ifdef(`_NO_CANONIFY_', `dnl
  540. # pass to name server to make hostname canonical if in class Canonify
  541. R$* $| $* < @ $* $={Canonify} > $* $: $2 < @ $[ $3 $4 $] > $5
  542. # pass to name server to make hostname canonical if requested
  543. R$* c $* $| $* < @ $* $~P > $* $: $3 < @ $[ $4 $5 $] > $6
  544. dnl trailing dot? -> do not apply _CANONIFY_HOSTS_
  545. R$* $| $* < @ $+ . > $* $: $2 < @ $3 . > $4
  546. # add a trailing dot to qualified hostnames so other rules will work
  547. R$* $| $* < @ $+.$+ > $* $: $2 < @ $3.$4 . > $5
  548. ifdef(`_CANONIFY_HOSTS_', `dnl
  549. dnl this should only apply to unqualified hostnames
  550. dnl but if a valid character inside an unqualified hostname is an OperatorChar
  551. dnl then $- does not work.
  552. dnl paranoia: avoid looking up hostnames which end in $=P
  553. # lookup unqualified hostnames
  554. R$* $| $* < @ $* $~P > $* $: $2 < @ $[ $3 $4 $] > $5', `dnl')', `dnl
  555. dnl {daemon_flags} contains CC -> do not perform canonicalization!
  556. R$* CC $* $| $* $: $3
  557. # pass to name server to make hostname canonical unless turned off
  558. R$* $| $* < @ $* $~P > $* $: $2 < @ $[ $3 $4 $] > $5')
  559. dnl remove {daemon_flags} for other cases
  560. R$* $| $* $: $2
  561. # local host aliases and pseudo-domains are always canonical
  562. R$* < @ $=w > $* $: $1 < @ $2 . > $3
  563. R$* < @ $j > $* $: $1 < @ $j . > $2
  564. ifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
  565. `R$* < @ $* $=M > $* $: $1 < @ $2 $3 . > $4',
  566. `R$* < @ $=M > $* $: $1 < @ $2 . > $3')
  567. R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4
  568. ifdef(`_VIRTUSER_TABLE_', `dnl
  569. dnl virtual hosts are also canonical
  570. ifdef(`_VIRTUSER_ENTIRE_DOMAIN_',
  571. `R$* < @ $* $={VirtHost} > $*  $: $1 < @ $2 $3 . > $4',
  572. `R$* < @ $={VirtHost} > $*  $: $1 < @ $2 . > $3')',
  573. `dnl')
  574. dnl remove superfluous dots (maybe repeatedly) which may have been added
  575. dnl by one of the rules before
  576. R$* < @ $* . . > $* $1 < @ $2 . > $3
  577. ##################################################
  578. ###  Ruleset 4 -- Final Output Post-rewriting  ###
  579. ##################################################
  580. Sfinal=4
  581. R$* <@> $@ handle <> and list:;
  582. # strip trailing dot off possibly canonical name
  583. R$* < @ $+ . > $* $1 < @ $2 > $3
  584. # eliminate internal code
  585. R$* < @ *LOCAL* > $* $1 < @ $j > $2
  586. # externalize local domain info
  587. R$* < $+ > $* $1 $2 $3 defocus
  588. R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 <route-addr> canonical
  589. R@ $* $@ @ $1 ... and exit
  590. ifdef(`_NO_UUCP_', `dnl',
  591. `# UUCP must always be presented in old form
  592. R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u')
  593. ifdef(`_USE_DECNET_SYNTAX_',
  594. `# put DECnet back in :: form
  595. R$+ @ $+ . DECNET $2 :: $1 u@h.DECNET => h::u',
  596. `dnl')
  597. # delete duplicate local names
  598. R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host
  599. ##############################################################
  600. ###   Ruleset 97 -- recanonicalize and call ruleset zero   ###
  601. ###    (used for recursive calls)    ###
  602. ##############################################################
  603. SRecurse=97
  604. R$* $: $>canonify $1
  605. R$* $@ $>parse $1
  606. ######################################
  607. ###   Ruleset 0 -- Parse Address   ###
  608. ######################################
  609. Sparse=0
  610. R$* $: $>Parse0 $1 initial parsing
  611. R<@> $#_LOCAL_ $: <@> special case error msgs
  612. R$* $: $>ParseLocal $1 handle local hacks
  613. R$* $: $>Parse1 $1 final parsing
  614. #
  615. #  Parse0 -- do initial syntax checking and eliminate local addresses.
  616. # This should either return with the (possibly modified) input
  617. # or return with a #error mailer.  It should not return with a
  618. # #mailer other than the #error mailer.
  619. #
  620. SParse0
  621. R<@> $@ <@> special case error msgs
  622. R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses"
  623. R@ <@ $* > < @ $1 > catch "@@host" bogosity
  624. R<@ $+> $#error $@ 5.1.3 $: "553 User address required"
  625. R$* $: <> $1
  626. R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3
  627. R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part"
  628. R<> $* $1
  629. R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name"
  630. R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name"
  631. # now delete the local info -- note $=O to find characters that cause forwarding
  632. R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user
  633. R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ...
  634. R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here
  635. R< @ $+ > $#error $@ 5.1.3 $: "553 User address required"
  636. R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ...
  637. R$-  $: $(dequote $1 $) < @ *LOCAL* > dequote "foo"
  638. R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required"
  639. R$* $=O $* < @ *LOCAL* >
  640. $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ...
  641. R$* < @ *LOCAL* > $: $1
  642. #
  643. #  Parse1 -- the bottom half of ruleset 0.
  644. #
  645. SParse1
  646. ifdef(`_LDAP_ROUTING_', `dnl
  647. # handle LDAP routing for hosts in $={LDAPRoute}
  648. R$+ < @ $={LDAPRoute} . > $: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $2>',
  649. `dnl')
  650. ifdef(`_MAILER_smtp_',
  651. `# handle numeric address spec
  652. dnl there is no check whether this is really an IP number
  653. R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec
  654. R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path
  655. R$* < @ [ IPv6 $- ] : > $*
  656. $#_SMTP_ $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send
  657. R$* < @ [ $+ ] : > $* $#_SMTP_ $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send
  658. R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer
  659. R$* < @ [ $+ ] : $+ > $* $#_SMTP_ $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer',
  660. `dnl')
  661. ifdef(`_VIRTUSER_TABLE_', `dnl
  662. # handle virtual users
  663. R$+ $: <!> $1 Mark for lookup
  664. ifdef(`_VIRTUSER_ENTIRE_DOMAIN_',
  665. `R<!> $+ < @ $* $={VirtHost} . >  $: < $(virtuser $1 @ $2 $3 $@ $1 $: @ $) > $1 < @ $2 $3 . >',
  666. `R<!> $+ < @ $={VirtHost} . >  $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >')
  667. R<!> $+ < @ $=w . >  $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
  668. R<@> $+ + $* < @ $* . >
  669. $: < $(virtuser $1 + * @ $3 $@ $1 $@ $2 $: @ $) > $1 + $2 < @ $3 . >
  670. R<@> $+ + $* < @ $* . >
  671. $: < $(virtuser $1 @ $3 $@ $1 $: @ $) > $1 + $2 < @ $3 . >
  672. dnl try default entry: @domain
  673. dnl +detail
  674. R<@> $+ + $* < @ $+ . > $: < $(virtuser @ $3 $@ $1 $@ $2 $: @ $) > $1 + $2 < @ $3 . >
  675. dnl without +detail (or no match)
  676. R<@> $+ < @ $+ . > $: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
  677. R<@> $+ $: $1
  678. R<!> $+ $: $1
  679. R< error : $-.$-.$- : $+ > $*  $#error $@ $1.$2.$3 $: $4
  680. R< error : $- $+ > $*  $#error $@ $(dequote $1 $) $: $2
  681. R< $+ > $+ < @ $+ > $: $>Recurse $1',
  682. `dnl')
  683. # short circuit local delivery so forwarded email works
  684. ifdef(`_MAILER_usenet_', `dnl
  685. R$+ . USENET < @ $=w . > $#usenet $: $1 handle usenet specially', `dnl')
  686. ifdef(`_STICKY_LOCAL_DOMAIN_',
  687. `R$+ < @ $=w . > $: < $H > $1 < @ $2 . > first try hub
  688. R< $+ > $+ < $+ > $>MailerToTriple < $1 > $2 < $3 > yep ....
  689. dnl $H empty (but @$=w.)
  690. R< > $+ + $* < $+ > $#_LOCAL_ $: $1 + $2 plussed name?
  691. R< > $+ < $+ > $#_LOCAL_ $: @ $1 nope, local address',
  692. `R$=L < @ $=w . > $#_LOCAL_ $: @ $1 special local names
  693. R$+ < @ $=w . > $#_LOCAL_ $: $1 regular local name')
  694. ifdef(`_MAILER_TABLE_', `dnl
  695. # not local -- try mailer table lookup
  696. R$* <@ $+ > $* $: < $2 > $1 < @ $2 > $3 extract host name
  697. R< $+ . > $* $: < $1 > $2 strip trailing dot
  698. R< $+ > $* $: < $(mailertable $1 $) > $2 lookup
  699. dnl it is $~[ instead of $- to avoid matches on IPv6 addresses
  700. R< $~[ : $* > $*  $>MailerToTriple < $1 : $2 > $3 check -- resolved?
  701. R< $+ > $* $: $>Mailertable <$1> $2 try domain',
  702. `dnl')
  703. undivert(4)dnl UUCP rules from `MAILER(uucp)'
  704. ifdef(`_NO_UUCP_', `dnl',
  705. `# resolve remotely connected UUCP links (if any)
  706. ifdef(`_CLASS_V_',
  707. `R$* < @ $=V . UUCP . > $* $: $>MailerToTriple < $V > $1 <@$2.UUCP.> $3',
  708. `dnl')
  709. ifdef(`_CLASS_W_',
  710. `R$* < @ $=W . UUCP . > $* $: $>MailerToTriple < $W > $1 <@$2.UUCP.> $3',
  711. `dnl')
  712. ifdef(`_CLASS_X_',
  713. `R$* < @ $=X . UUCP . > $* $: $>MailerToTriple < $X > $1 <@$2.UUCP.> $3',
  714. `dnl')')
  715. # resolve fake top level domains by forwarding to other hosts
  716. ifdef(`BITNET_RELAY',
  717. `R$*<@$+.BITNET.>$* $: $>MailerToTriple < $B > $1 <@$2.BITNET.> $3 user@host.BITNET',
  718. `dnl')
  719. ifdef(`DECNET_RELAY',
  720. `R$*<@$+.DECNET.>$* $: $>MailerToTriple < $C > $1 <@$2.DECNET.> $3 user@host.DECNET',
  721. `dnl')
  722. ifdef(`_MAILER_pop_',
  723. `R$+ < @ POP. > $#pop $: $1 user@POP',
  724. `dnl')
  725. ifdef(`_MAILER_fax_',
  726. `R$+ < @ $+ .FAX. > $#fax $@ $2 $: $1 user@host.FAX',
  727. `ifdef(`FAX_RELAY',
  728. `R$*<@$+.FAX.>$* $: $>MailerToTriple < $F > $1 <@$2.FAX.> $3 user@host.FAX',
  729. `dnl')')
  730. ifdef(`UUCP_RELAY',
  731. `# forward non-local UUCP traffic to our UUCP relay
  732. R$*<@$*.UUCP.>$* $: $>MailerToTriple < $Y > $1 <@$2.UUCP.> $3 uucp mail',
  733. `ifdef(`_MAILER_uucp_',
  734. `# forward other UUCP traffic straight to UUCP
  735. R$* < @ $+ .UUCP. > $* $#_UUCP_ $@ $2 $: $1 < @ $2 .UUCP. > $3 user@host.UUCP',
  736. `dnl')')
  737. ifdef(`_MAILER_usenet_', `
  738. # addresses sent to net.group.USENET will get forwarded to a newsgroup
  739. R$+ . USENET $#usenet $: $1',
  740. `dnl')
  741. ifdef(`_LOCAL_RULES_',
  742. `# figure out what should stay in our local mail system
  743. undivert(1)', `dnl')
  744. # pass names that still have a host to a smarthost (if defined)
  745. R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name
  746. # deal with other remote names
  747. ifdef(`_MAILER_smtp_',
  748. `R$* < @$* > $* $#_SMTP_ $@ $2 $: $1 < @ $2 > $3 user@host.domain',
  749. `R$* < @$* > $* $#error $@ 5.1.2 $: "553 Unrecognized host name " $2')
  750. # handle locally delivered names
  751. R$=L $#_LOCAL_ $: @ $1 special local names
  752. R$+ $#_LOCAL_ $: $1 regular local names
  753. ###########################################################################
  754. ###   Ruleset 5 -- special rewriting after aliases have been expanded   ###
  755. ###########################################################################
  756. SLocal_localaddr
  757. Slocaladdr=5
  758. R$+ $: $1 $| $>"Local_localaddr" $1
  759. R$+ $| $#$* $#$2
  760. R$+ $| $* $: $1
  761. # deal with plussed users so aliases work nicely
  762. R$+ + * $#_LOCAL_ $@ $&h $: $1
  763. R$+ + $* $#_LOCAL_ $@ + $2 $: $1 + *
  764. # prepend an empty "forward host" on the front
  765. R$+ $: <> $1
  766. ifdef(`LUSER_RELAY', `dnl
  767. # send unrecognized local users to a relay host
  768. R< > $+  $: < $L > $(user $1 $) look up user
  769. R< $* > $+ <> $: < > $2 found; strip $L',
  770. `dnl')
  771. # see if we have a relay or a hub
  772. R< > $+ $: < $H > $1 try hub
  773. R< > $+ $: < $R > $1 try relay
  774. R< > $+ $: < > < $1 <> $&h > nope, restore +detail
  775. R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail
  776. R< > < $+ <> $* > $: < > < $1 > else discard
  777. R< > < $+ + $* > $*    < > < $1 > + $2 $3 find the user part
  778. R< > < $+ > + $* $#_LOCAL_ $@ $2 $: @ $1 strip the extra +
  779. R< > < $+ > $@ $1 no +detail
  780. R$+ $: $1 <> $&h add +detail back in
  781. R$+ <> + $* $: $1 + $2 check whether +detail
  782. R$+ <> $* $: $1 else discard
  783. R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension
  784. R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension
  785. R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 >
  786. R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 >
  787. ifdef(`_MAILER_TABLE_', `dnl
  788. ###################################################################
  789. ###  Ruleset 90 -- try domain part of mailertable entry  ###
  790. dnl input: LeftPartOfDomain <RightPartOfDomain> FullAddress
  791. ###################################################################
  792. SMailertable=90
  793. dnl shift and check
  794. dnl %2 is not documented in cf/README
  795. R$* <$- . $+ > $* $: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4
  796. dnl it is $~[ instead of $- to avoid matches on IPv6 addresses
  797. R$* <$~[ : $* > $* $>MailerToTriple < $2 : $3 > $4 check -- resolved?
  798. R$* < . $+ > $*  $@ $>Mailertable $1 . <$2> $3 no -- strip & try again
  799. dnl is $2 always empty?
  800. R$* < $* > $* $: < $(mailertable . $@ $1$2 $) > $3 try "."
  801. R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 "." found?
  802. dnl return full address
  803. R< $* > $* $@ $2 no mailertable match',
  804. `dnl')
  805. ###################################################################
  806. ###  Ruleset 95 -- canonify mailer:[user@]host syntax to triple ###
  807. dnl input: in general: <[mailer:]host> lp<@domain>rest
  808. dnl <> address -> address
  809. dnl <error:d.s.n:text> -> error
  810. dnl <error:text> -> error
  811. dnl <mailer:user@host> lp<@domain>rest -> mailer host user
  812. dnl <mailer:host> address -> mailer host address
  813. dnl <localdomain> address -> address
  814. dnl <[IPv6 number]> address -> relay number address
  815. dnl <host> address -> relay host address
  816. ###################################################################
  817. SMailerToTriple=95
  818. R< > $* $@ $1 strip off null relay
  819. R< error : $-.$-.$- : $+ > $*  $#error $@ $1.$2.$3 $: $4
  820. R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2
  821. R< local : $* > $* $>CanonLocal < $1 > $2
  822. R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user
  823. R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer
  824. R< $=w > $* $@ $2 delete local host
  825. R< [ IPv6 $+ ] > $* $#_RELAY_ $@ $(dequote $1 $) $: $2 use unqualified mailer
  826. R< $+ > $* $#_RELAY_ $@ $1 $: $2 use unqualified mailer
  827. ###################################################################
  828. ###  Ruleset CanonLocal -- canonify local: syntax ###
  829. dnl input: <user> address
  830. dnl <x> <@host> : rest -> Recurse rest
  831. dnl <x> p1 $=O p2 <@host> -> Recurse p1 $=O p2
  832. dnl <> user <@host> rest -> local user@host user
  833. dnl <> user -> local user user
  834. dnl <user@host> lp <@domain> rest -> <user> lp <@host> [cont]
  835. dnl <user> lp <@host> rest -> local lp@host user
  836. dnl <user> lp -> local lp user
  837. ###################################################################
  838. SCanonLocal
  839. # strip local host from routed addresses
  840. R< $* > < @ $+ > : $+ $@ $>Recurse $3
  841. R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4
  842. # strip trailing dot from any host name that may appear
  843. R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 >
  844. # handle local: syntax -- use old user, either with or without host
  845. R< > $* < @ $* > $* $#_LOCAL_ $@ $1@$2 $: $1
  846. R< > $+ $#_LOCAL_ $@ $1    $: $1
  847. # handle local:user@host syntax -- ignore host part
  848. R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 >
  849. # handle local:user syntax
  850. R< $+ > $* <@ $* > $* $#_LOCAL_ $@ $2@$3 $: $1
  851. R< $+ > $*  $#_LOCAL_ $@ $2    $: $1
  852. ###################################################################
  853. ###  Ruleset 93 -- convert header names to masqueraded form ###
  854. ###################################################################
  855. SMasqHdr=93
  856. ifdef(`_GENERICS_TABLE_', `dnl
  857. # handle generics database
  858. ifdef(`_GENERICS_ENTIRE_DOMAIN_',
  859. dnl if generics should be applied add a @ as mark
  860. `R$+ < @ $* $=G . > $: < $1@$2$3 > $1 < @ $2$3 . > @ mark',
  861. `R$+ < @ $=G . > $: < $1@$2 > $1 < @ $2 . > @ mark')
  862. R$+ < @ *LOCAL* > $: < $1@$j > $1 < @ *LOCAL* > @ mark
  863. dnl workspace: either user<@domain> or <user@domain> user <@domain> @
  864. dnl ignore the first case for now
  865. dnl if it has the mark lookup full address
  866. R< $+ > $+ < $* > @ $: < $(generics $1 $: @ $1 $) > $2 < $3 >
  867. dnl workspace: ... or <match|@user@domain> user <@domain>
  868. dnl no match, try user+detail@domain
  869. R<@$+ + $* @ $+> $+ < @ $+ >
  870. $: < $(generics $1+*@$3 $@ $2 $:@$1 + $2@$3 $) >  $4 < @ $5 >
  871. R<@$+ + $* @ $+> $+ < @ $+ >
  872. $: < $(generics $1@$3 $: $) > $4 < @ $5 >
  873. dnl no match, remove mark
  874. R<@$+ > $+ < @ $+ > $: < > $2 < @ $3 >
  875. dnl no match, try @domain for exceptions
  876. R< > $+ < @ $+ . > $: < $(generics @$2 $@ $1 $: $) > $1 < @ $2 . >
  877. dnl workspace: ... or <match> user <@domain>
  878. dnl no match, try local part
  879. R< > $+ < @ $+ >  $: < $(generics $1 $: $) > $1 < @ $2 >
  880. R< > $+ + $* < @ $+ >  $: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 >
  881. R< > $+ + $* < @ $+ >  $: < $(generics $1 $: $) > $1 + $2 < @ $3 >
  882. R< $* @ $* > $* < $* > $@ $>canonify $1 @ $2 found qualified
  883. R< $+ > $* < $* > $: $>canonify $1 @ *LOCAL* found unqualified
  884. R< > $* $: $1 not found',
  885. `dnl')
  886. # do not masquerade anything in class N
  887. R$* < @ $* $=N . > $@ $1 < @ $2 $3 . >
  888. # special case the users that should be exposed
  889. R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed
  890. ifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
  891. `R$=E < @ $* $=M . > $@ $1 < @ $2 $3 . >',
  892. `R$=E < @ $=M . > $@ $1 < @ $2 . >')
  893. ifdef(`_LIMITED_MASQUERADE_', `dnl',
  894. `R$=E < @ $=w . > $@ $1 < @ $2 . >')
  895. # handle domain-specific masquerading
  896. ifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
  897. `R$* < @ $* $=M . > $* $: $1 < @ $2 $3 . @ $M > $4 convert masqueraded doms',
  898. `R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms')
  899. ifdef(`_LIMITED_MASQUERADE_', `dnl',
  900. `R$* < @ $=w . > $* $: $1 < @ $2 . @ $M > $3')
  901. R$* < @ *LOCAL* > $* $: $1 < @ $j . @ $M > $2
  902. R$* < @ $+ @ > $* $: $1 < @ $2 > $3 $M is null
  903. R$* < @ $+ @ $+ > $* $: $1 < @ $3 . > $4 $M is not null
  904. ###################################################################
  905. ###  Ruleset 94 -- convert envelope names to masqueraded form ###
  906. ###################################################################
  907. SMasqEnv=94
  908. ifdef(`_MASQUERADE_ENVELOPE_',
  909. `R$+ $@ $>MasqHdr $1',
  910. `R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2')
  911. ###################################################################
  912. ###  Ruleset 98 -- local part of ruleset zero (can be null) ###
  913. ###################################################################
  914. SParseLocal=98
  915. undivert(3)dnl LOCAL_RULE_0
  916. ifdef(`_LDAP_ROUTING_', `dnl
  917. SLDAPExpand
  918. # do the LDAP lookups
  919. R<$+><$+>
  920. $: <$(ldap_mailroutingaddress $2 $: $)> <$(ldap_mailhost $2 $: $)> <$1> <$2>
  921. # if mailRoutingAddress and local or non-existant mailHost,
  922. # return the new mailRoutingAddress
  923. R< $+ > < $=w > < $+ > < $+ > $@ $>Parse0 $>canonify $1
  924. R< $+ > <  > < $+ > < $+ > $@ $>Parse0 $>canonify $1
  925. # if mailRoutingAddress and non-local mailHost,
  926. # relay to mailHost with new mailRoutingAddress
  927. R< $+ > < $+ > < $+ > < $+ > $#_RELAY_ $@ $2 $: $>canonify $1
  928. # if no mailRoutingAddress and local mailHost,
  929. # return original address
  930. R< > < $=w > <$+> <$+> $@ $2
  931. # if no mailRoutingAddress and non-local mailHost,
  932. # relay to mailHost with original address
  933. R< > < $+ > <$+> <$+> $#_RELAY_ $@ $1 $: $2
  934. # if no mailRoutingAddress and no mailHost,
  935. # try @domain
  936. R< > < > <$+> <$+ @ $+> $@ $>LDAPExpand <$1> <@ $3>
  937. # if no mailRoutingAddress and no mailHost and this was a domain attempt,
  938. ifelse(_LDAP_ROUTING_, `_MUST_EXIST_', `dnl
  939. # user does not exist
  940. R< > < > <$+> <@ $+> $#error $@ nouser $: "550 User unknown"',
  941. `dnl
  942. # return the original address
  943. R< > < > <$+> <@ $+> $@ $1')',
  944. `dnl')
  945. ifelse(substr(confDELIVERY_MODE,0,1), `d', `errprint(`WARNING: Antispam rules not available in deferred delivery mode.
  946. ')')
  947. ifdef(`_ACCESS_TABLE_', `dnl
  948. ######################################################################
  949. ###  LookUpDomain -- search for domain in access database
  950. ###
  951. ### Parameters:
  952. ### <$1> -- key (domain name)
  953. ### <$2> -- default (what to return if not found in db)
  954. dnl must not be empty
  955. ### <$3> -- passthru (additional data passed unchanged through)
  956. ### <$4> -- mark (must be <(!|+) single-token>)
  957. ### ! does lookup only with tag
  958. ### + does lookup with and without tag
  959. dnl returns: <default> <passthru>
  960. dnl  <result> <passthru>
  961. ######################################################################
  962. SLookUpDomain
  963. dnl remove IPv6 mark and dequote address
  964. dnl it is a bit ugly because it is checked on each "iteration"
  965. R<[IPv6 $-]> <$+> <$*> <$*> $: <[$(dequote $1 $)]> <$2> <$3> <$4>
  966. dnl workspace <key> <default> <passthru> <mark>
  967. dnl lookup with tag (in front, no delimiter here)
  968. R<$*> <$+> <$*> <$- $-> $: < $(access $5`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3> <$4 $5>
  969. dnl workspace <result-of-lookup|?> <key> <default> <passthru> <mark>
  970. ifdef(`_FFR_LOOKUPDOTDOMAIN', `dnl omit first component: lookup .rest
  971. R<?> <$+.$+> <$+> <$*> <$- $-> $: < $(access $5`'_TAG_DELIM_`'.$2 $: ? $) > <$1.$2> <$3> <$4> <$5 $6>', `dnl')
  972. dnl lookup without tag?
  973. R<?> <$+> <$+> <$*> <+ $*> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <+ $4>
  974. ifdef(`_FFR_LOOKUPDOTDOMAIN', `dnl omit first component: lookup .rest
  975. R<?> <$+.$+> <$+> <$*> <+ $*> $: < $(access .$2 $: ? $) > <$1.$2> <$3> <$4> <+ $5>', `dnl')
  976. dnl lookup IP address (no check is done whether it is an IP number!)
  977. R<?> <[$+.$-]> <$+> <$*> <$*> $@ $>LookUpDomain <[$1]> <$3> <$4> <$5>
  978. dnl lookup IPv6 address
  979. R<?> <[$+:$-]> <$+> <$*> <$*> $: $>LookUpDomain <[$1]> <$3> <$4> <$5>
  980. dnl not found, but subdomain: try again
  981. R<?> <$+.$+> <$+> <$*> <$*> $@ $>LookUpDomain <$2> <$3> <$4> <$5>
  982. dnl not found, no subdomain: return default
  983. R<?> <$+> <$+> <$*> <$*> $@ <$2> <$3>
  984. dnl return result of lookup
  985. R<$*> <$+> <$+> <$*> <$*> $@ <$1> <$4>
  986. ######################################################################
  987. ###  LookUpAddress -- search for host address in access database
  988. ###
  989. ### Parameters:
  990. ### <$1> -- key (dot quadded host address)
  991. ### <$2> -- default (what to return if not found in db)
  992. dnl must not be empty
  993. ### <$3> -- passthru (additional data passed through)
  994. ### <$4> -- tag (should end with _TAG_DELIM_)
  995. dnl returns: <default> <passthru>
  996. dnl <result> <passthru>
  997. dnl maybe the tag should not include _TAG_DELIM_ to be consistent
  998. dnl with LookUpDomain?
  999. ######################################################################
  1000. SLookUpAddress
  1001. R<$+> <$+> <$*> <$*> $: < $(access $4$1 $: ? $) > <$1> <$2> <$3> <$4>
  1002. R<?> <$+> <$+> <$*> <$*> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <$4>
  1003. R<?> <$+:$-> <$+> <$*> <$*> $: $>LookUpAddress <$1> <$3> <$4> <$5>
  1004. R<?> <$+.$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5>
  1005. R<?> <$+> <$+> <$*> <$*> $@ <$2> <$3>
  1006. R<$*> <$+> <$+> <$*> <$*> $@ <$1> <$4>',
  1007. `dnl')
  1008. ######################################################################
  1009. ###  CanonAddr -- Convert an address into a standard form for
  1010. ### relay checking.  Route address syntax is
  1011. ### crudely converted into a %-hack address.
  1012. ###
  1013. ### Parameters:
  1014. ### $1 -- full recipient address
  1015. ###
  1016. ### Returns:
  1017. ### parsed address, not in source route form
  1018. dnl user%host%host<@domain>
  1019. dnl host!user<@domain>
  1020. ######################################################################
  1021. SCanonAddr
  1022. R$* $: $>Parse0 $>canonify $1 make domain canonical
  1023. ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl
  1024. R< @ $+ > : $* @ $* < @ $1 > : $2 % $3 change @ to % in src route
  1025. R$* < @ $+ > : $* : $* $3 $1 < @ $2 > : $4 change to % hack.
  1026. R$* < @ $+ > : $* $3 $1 < @ $2 >
  1027. dnl')
  1028. ######################################################################
  1029. ###  ParseRecipient -- Strip off hosts in $=R as well as possibly
  1030. ### $* $=m or the access database.
  1031. ### Check user portion for host separators.
  1032. ###
  1033. ### Parameters:
  1034. ### $1 -- full recipient address
  1035. ###
  1036. ### Returns:
  1037. ### parsed, non-local-relaying address
  1038. ######################################################################
  1039. SParseRecipient
  1040. dnl mark and canonify address
  1041. R$* $: <?> $>CanonAddr $1
  1042. R<?> $* < @ $* . > <?> $1 < @ $2 > strip trailing dots
  1043. R<?> $- < @ $* > $: <?> $(dequote $1 $) < @ $2 > dequote local part
  1044. # if no $=O character, no host in the user portion, we are done
  1045. R<?> $* $=O $* < @ $* > $: <NO> $1 $2 $3 < @ $4>
  1046. R<?> $* $@ $1
  1047. ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl
  1048. # if we relay, check username portion for user%host so host can be checked also
  1049. R<NO> $* < @ $* $=m > $: <RELAY> $1 < @ $2 $3 >', `dnl')
  1050. ifdef(`_RELAY_MX_SERVED_', `dnl
  1051. R<NO> $* < @ $+ > $: <MX> < : $(mxserved $2 $) : > < $1 < @$2 > >
  1052. R<MX> < : $* <TEMP> : > $* $#error $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1
  1053. R<MX> < $* : $=w. : $* > < $+ > $: <RELAY> $4
  1054. R<MX> < : $* : > < $+ > $: <NO> $2', `dnl')
  1055. ifdef(`_RELAY_HOSTS_ONLY_',
  1056. `R<NO> $* < @ $=R > $: <RELAY> $1 < @ $2 >
  1057. ifdef(`_ACCESS_TABLE_', `dnl
  1058. R<NO> $* < @ $+ > $: <$(access To:$2 $: NO $)> $1 < @ $2 >
  1059. R<NO> $* < @ $+ > $: <$(access $2 $: NO $)> $1 < @ $2 >',`dnl')',
  1060. `R<NO> $* < @ $* $=R > $: <RELAY> $1 < @ $2 $3 >
  1061. ifdef(`_ACCESS_TABLE_', `dnl
  1062. R<NO> $* < @ $+ > $: $>LookUpDomain <$2> <NO> <$1 < @ $2 >> <+To>
  1063. R<$+> <$+> $: <$1> $2',`dnl')')
  1064. R<RELAY> $* < @ $* > $@ $>ParseRecipient $1
  1065. R<$-> $* $@ $2
  1066. ######################################################################
  1067. ###  check_relay -- check hostname/address on SMTP startup
  1068. ######################################################################
  1069. SLocal_check_relay
  1070. Scheck`'_U_`'relay
  1071. R$* $: $1 $| $>"Local_check_relay" $1
  1072. R$* $| $* $| $#$* $#$3
  1073. R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2
  1074. SBasic_check_relay
  1075. # check for deferred delivery mode
  1076. R$* $: < ${deliveryMode} > $1
  1077. R< d > $* $@ deferred
  1078. R< $* > $* $: $2
  1079. ifdef(`_ACCESS_TABLE_', `dnl
  1080. R$+ $| $+ $: $>LookUpDomain < $1 > <?> < $2 > <+Connect>
  1081. R<?> <$+> $: $>LookUpAddress < $1 > <?> < $1 > <Connect:> no: another lookup
  1082. R<?> < $+ > $: $1 found nothing
  1083. R<$={Accept}> < $* > $@ $1
  1084. R<REJECT> $* $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"')
  1085. R<DISCARD> $* $#discard $: discard
  1086. dnl error tag
  1087. R<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4
  1088. R<ERROR:$+> $* $#error $: $1
  1089. dnl generic error from access map
  1090. R<$+> $* $#error $: $1', `dnl')
  1091. ifdef(`_RBL_',`dnl
  1092. # DNS based IP address spam list
  1093. R$* $: $&{client_addr}
  1094. R::ffff:$-.$-.$-.$- $: <?> $(host $4.$3.$2.$1._RBL_. $: OK $)
  1095. R$-.$-.$-.$- $: <?> $(host $4.$3.$2.$1._RBL_. $: OK $)
  1096. R<?>OK $: OKSOFAR
  1097. R<?>$+ $#error $@ 5.7.1 $: "550 Mail from " $&{client_addr} " refused by blackhole site _RBL_"',
  1098. `dnl')
  1099. undivert(8)
  1100. ######################################################################
  1101. ###  check_mail -- check SMTP ``MAIL FROM:'' command argument
  1102. ######################################################################
  1103. SLocal_check_mail
  1104. Scheck`'_U_`'mail
  1105. R$* $: $1 $| $>"Local_check_mail" $1
  1106. R$* $| $#$* $#$2
  1107. R$* $| $* $@ $>"Basic_check_mail" $1
  1108. SBasic_check_mail
  1109. # check for deferred delivery mode
  1110. R$* $: < ${deliveryMode} > $1
  1111. R< d > $* $@ deferred
  1112. R< $* > $* $: $2
  1113. dnl workspace: address as given by MAIL FROM:
  1114. R<> $@ <OK> we MUST accept <> (RFC 1123)
  1115. ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl
  1116. dnl do some additional checks
  1117. dnl no user@host
  1118. dnl no user@localhost (if nonlocal sender)
  1119. dnl this is a pretty simple canonification, it will not catch every case
  1120. dnl just make sure the address has <> around it (which is required by
  1121. dnl the RFC anyway, maybe we should complain if they are missing...)
  1122. dnl dirty trick: if it is user@host, just add a dot: user@host. this will
  1123. dnl not be modified by host lookups.
  1124. R$+ $: <?> $1
  1125. R<?><$+> $: <@> <$1>
  1126. R<?>$+ $: <@> <$1>
  1127. dnl workspace: <@> <address>
  1128. dnl prepend daemon_flags
  1129. R$* $: $&{daemon_flags} $| $1
  1130. dnl workspace: ${daemon_flags} $| <@> <address>
  1131. dnl do not allow these at all or only from local systems?
  1132. R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 >
  1133. dnl accept unqualified sender: change mark to avoid test
  1134. R$* u $* $| <@> < $* > $: <?> < $3 >
  1135. dnl workspace: ${daemon_flags} $| <@> <address>
  1136. dnl        or:                    <? ${client_name} > <address>
  1137. dnl        or:                    <?> <address>
  1138. dnl remove daemon_flags
  1139. R$* $| $* $: $2
  1140. # handle case of @localhost on address
  1141. R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost >
  1142. R<@> < $* @ [127.0.0.1] >
  1143. $: < ? $&{client_name} > < $1 @ [127.0.0.1] >
  1144. R<@> < $* @ localhost.$m >
  1145. $: < ? $&{client_name} > < $1 @ localhost.$m >
  1146. ifdef(`_NO_UUCP_', `dnl',
  1147. `R<@> < $* @ localhost.UUCP >
  1148. $: < ? $&{client_name} > < $1 @ localhost.UUCP >')
  1149. dnl workspace: < ? $&{client_name} > <user@localhost|host>
  1150. dnl or:    <@> <address>
  1151. dnl or:    <?> <address> (thanks to u in ${daemon_flags})
  1152. R<@> $* $: $1 no localhost as domain
  1153. dnl workspace: < ? $&{client_name} > <user@localhost|host>
  1154. dnl or:    <address>
  1155. dnl or:    <?> <address> (thanks to u in ${daemon_flags})
  1156. R<? $=w> $* $: $2 local client: ok
  1157. R<? $+> <$+> $#error $@ 5.5.4 $: "553 Real domain name required"
  1158. dnl remove <?> (happens only if ${client_name} == "" or u in ${daemon_flags})
  1159. R<?> $* $: $1')
  1160. dnl workspace: address (or <address>)
  1161. R$* $: <?> $>CanonAddr $1 canonify sender address and mark it
  1162. dnl workspace: <?> CanonicalAddress (i.e. address in canonical form localpart<@host>)
  1163. dnl there is nothing behind the <@host> so no trailing $* needed
  1164. R<?> $* < @ $+ . > <?> $1 < @ $2 > strip trailing dots
  1165. # handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc)
  1166. R<?> $* < @ $* $=P > $: <OK> $1 < @ $2 $3 >
  1167. dnl workspace <mark> CanonicalAddress where mark is ? or OK
  1168. ifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_',
  1169. `R<?> $* < @ $+ > $: <OK> $1 < @ $2 > ... unresolvable OK',
  1170. `R<?> $* < @ $+ > $: <? $(resolve $2 $: $2 <PERM> $) > $1 < @ $2 >
  1171. R<? $* <$->> $* < @ $+ >
  1172. $: <$2> $3 < @ $4 >')
  1173. dnl workspace <mark> CanonicalAddress where mark is ?, OK, PERM, TEMP
  1174. dnl mark is ? iff the address is user (wo @domain)
  1175. ifdef(`_ACCESS_TABLE_', `dnl
  1176. # check sender address: user@address, user@, @address
  1177. dnl should we remove +ext from user?
  1178. dnl workspace: <mark> CanonicalAddress where mark is: ?, OK, PERM, TEMP
  1179. R<$+> $+ < @ $* > $: @<$1> <$2 < @ $3 >> $| <F:$2@$3> <U:$2@> <H:$3>
  1180. R<$+> $+ $: @<$1> <$2> $| <U:$2@>
  1181. dnl workspace: @<mark> <CanonicalAddress> $| <@type:address> ....
  1182. dnl $| is used as delimiter, otherwise false matches may occur: <user<@domain>>
  1183. dnl will only return user<@domain when "reversing" the args
  1184. R@ <$+> <$*> $| <$+> $: <@> <$1> <$2> $| $>SearchList <+From> $| <$3> <>
  1185. dnl workspace: <@><mark> <CanonicalAddress> $| <result>
  1186. R<@> <$+> <$*> $| <$*> $: <$3> <$1> <$2> reverse result
  1187. dnl workspace: <result> <mark> <CanonicalAddress>
  1188. # retransform for further use
  1189. dnl required form:
  1190. dnl <ResultOfLookup|mark> CanonicalAddress
  1191. R<?> <$+> <$*> $: <$1> $2 no match
  1192. R<$+> <$+> <$*> $: <$1> $3 relevant result, keep it', `dnl')
  1193. dnl workspace <ResultOfLookup|mark> CanonicalAddress
  1194. dnl mark is ? iff the address is user (wo @domain)
  1195. ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl
  1196. # handle case of no @domain on address
  1197. dnl prepend daemon_flags
  1198. R<?> $* $: $&{daemon_flags} $| <?> $1
  1199. dnl accept unqualified sender: change mark to avoid test
  1200. R$* u $* $| <?> $* $: <OK> $3
  1201. dnl remove daemon_flags
  1202. R$* $| $* $: $2
  1203. R<?> $* $: < ? $&{client_name} > $1
  1204. R<?> $* $@ <OK> ...local unqualed ok
  1205. R<? $+> $* $#error $@ 5.5.4 $: "553 Domain name required"
  1206. ...remote is not')
  1207. # check results
  1208. R<?> $* $: @ $1 mark address: nothing known about it
  1209. R<OK> $* $@ <OK>
  1210. R<TEMP> $* $#error $@ 4.1.8 $: "451 Sender domain must resolve"
  1211. R<PERM> $* $#error $@ 5.1.8 $: "501 Sender domain must exist"
  1212. ifdef(`_ACCESS_TABLE_', `dnl
  1213. R<$={Accept}> $* $@ $1
  1214. R<DISCARD> $* $#discard $: discard
  1215. R<REJECT> $* $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"')
  1216. dnl error tag
  1217. R<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4
  1218. R<ERROR:$+> $* $#error $: $1
  1219. dnl generic error from access map
  1220. R<$+> $* $#error $: $1 error from access db',
  1221. `dnl')
  1222. ######################################################################
  1223. ###  check_rcpt -- check SMTP ``RCPT TO:'' command argument
  1224. ######################################################################
  1225. SLocal_check_rcpt
  1226. Scheck`'_U_`'rcpt
  1227. R$* $: $1 $| $>"Local_check_rcpt" $1
  1228. R$* $| $#$* $#$2
  1229. R$* $| $* $@ $>"Basic_check_rcpt" $1
  1230. SBasic_check_rcpt
  1231. # check for deferred delivery mode
  1232. R$* $: < ${deliveryMode} > $1
  1233. R< d > $* $@ deferred
  1234. R< $* > $* $: $2
  1235. ifdef(`_REQUIRE_QUAL_RCPT_', `dnl
  1236. # require qualified recipient?
  1237. R$+ $: <?> $1
  1238. R<?><$+> $: <@> <$1>
  1239. R<?>$+ $: <@> <$1>
  1240. dnl prepend daemon_flags
  1241. R$* $: $&{daemon_flags} $| $1
  1242. dnl workspace: ${daemon_flags} $| <@> <address>
  1243. dnl do not allow these at all or only from local systems?
  1244. R$* r $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 >
  1245. R<?> < $* > $: <$1>
  1246. R<? $=w> < $* > $: <$1>
  1247. R<? $+> <$+> $#error $@ 5.5.4 $: "553 Domain name required"
  1248. dnl remove daemon_flags for other cases
  1249. R$* $| <@> $* $: $2', `dnl')
  1250. ifdef(`_LOOSE_RELAY_CHECK_',`dnl
  1251. R$* $: $>CanonAddr $1
  1252. R$* < @ $* . > $1 < @ $2 > strip trailing dots',
  1253. `R$* $: $>ParseRecipient $1 strip relayable hosts')
  1254. ifdef(`_BESTMX_IS_LOCAL_',`dnl
  1255. ifelse(_BESTMX_IS_LOCAL_, `', `dnl
  1256. # unlimited bestmx
  1257. R$* < @ $* > $* $: $1 < @ $2 @@ $(bestmx $2 $) > $3',
  1258. `dnl
  1259. # limit bestmx to $=B
  1260. R$* < @ $* $=B > $* $: $1 < @ $2 $3 @@ $(bestmx $2 $3 $) > $4')
  1261. R$* $=O $* < @ $* @@ $=w . > $* $@ $>Basic_check_rcpt $1 $2 $3
  1262. R$* < @ $* @@ $=w . > $* $: $1 < @ $3 > $4
  1263. R$* < @ $* @@ $* > $* $: $1 < @ $2 > $4')
  1264. ifdef(`_BLACKLIST_RCPT_',`dnl
  1265. ifdef(`_ACCESS_TABLE_', `dnl
  1266. # blacklist local users or any host from receiving mail
  1267. R$* $: <?> $1
  1268. dnl user is now tagged with @ to be consistent with check_mail
  1269. dnl and to distinguish users from hosts (com would be host, com@ would be user)
  1270. R<?> $+ < @ $=w > $: <> <$1 < @ $2 >> $| <F:$1@$2> <U:$1@>
  1271. R<?> $+ < @ $* > $: <> <$1 < @ $2 >> $| <F:$1@$2> <H:$2>
  1272. R<?> $+ $: <> <$1> $| <U:$1@>
  1273. dnl $| is used as delimiter, otherwise false matches may occur: <user<@domain>>
  1274. dnl will only return user<@domain when "reversing" the args
  1275. R<> <$*> $| <$+> $: <@> <$1> $| $>SearchList <+To> $| <$2> <>
  1276. R<@> <$*> $| <$*> $: <$2> <$1> reverse result
  1277. R<?> <$*> $: @ $1 mark address as no match
  1278. R<$={Accept}> <$*> $: @ $2 mark address as no match
  1279. ifdef(`_DELAY_CHECKS_',`dnl
  1280. dnl we have to filter these because otherwise they would be interpreted
  1281. dnl as generic error message...
  1282. dnl error messages should be "tagged" by prefixing them with error: !
  1283. dnl that would make a lot of things easier.
  1284. dnl maybe we should stop checks already here (if SPAM_xyx)?
  1285. R<$={SpamTag}> <$*> $: @ $2 mark address as no match')
  1286. R<REJECT> $* $#error $@ 5.2.1 $: "550 Mailbox disabled for this recipient"
  1287. R<DISCARD> $* $#discard $: discard
  1288. dnl error tag
  1289. R<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4
  1290. R<ERROR:$+> $* $#error $: $1
  1291. dnl generic error from access map
  1292. R<$+> $* $#error $: $1 error from access db
  1293. R@ $* $1 remove mark', `dnl')', `dnl')
  1294. ifdef(`_PROMISCUOUS_RELAY_', `divert(-1)')
  1295. # authenticated by a trusted mechanism?
  1296. R$* $: $1 $| $&{auth_type}
  1297. dnl empty ${auth_type}?
  1298. R$* $| $: $1
  1299. dnl mechanism ${auth_type} accepted?
  1300. R$* $| $={TrustAuthMech} $@ RELAYAUTH
  1301. dnl undo addition of ${auth_type}
  1302. R$* $| $* $: $1
  1303. ifelse(defn(`_NO_UUCP_'), `r',
  1304. `R$* ! $* < @ $* > $: <REMOTE> $2 < @ BANG_PATH >', `dnl')
  1305. # anything terminating locally is ok
  1306. ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl
  1307. R$+ < @ $* $=m > $@ RELAYTO', `dnl')
  1308. R$+ < @ $=w > $@ RELAYTO
  1309. ifdef(`_RELAY_HOSTS_ONLY_',
  1310. `R$+ < @ $=R > $@ RELAYTO
  1311. ifdef(`_ACCESS_TABLE_', `dnl
  1312. R$+ < @ $+ > $: <$(access To:$2 $: ? $)> <$1 < @ $2 >>
  1313. R$+ < @ $+ > $: <$(access $2 $: ? $)> <$1 < @ $2 >>',`dnl')',
  1314. `R$+ < @ $* $=R > $@ RELAYTO
  1315. ifdef(`_ACCESS_TABLE_', `dnl
  1316. R$+ < @ $+ > $: $>LookUpDomain <$2> <?> <$1 < @ $2 >> <+To>',`dnl')')
  1317. ifdef(`_ACCESS_TABLE_', `dnl
  1318. R<RELAY> $* $@ RELAYTO
  1319. R<$*> <$*> $: $2',`dnl')
  1320. ifdef(`_RELAY_MX_SERVED_', `dnl
  1321. # allow relaying for hosts which we MX serve
  1322. R$+ < @ $+ > $: < : $(mxserved $2 $) : > $1 < @ $2 >
  1323. dnl this must not necessarily happen if the client is checked first...
  1324. R< : $* <TEMP> : > $* $#error $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1
  1325. R<$* : $=w . : $*> $* $@ RELAYTO
  1326. R< : $* : > $* $: $2',
  1327. `dnl')
  1328. # check for local user (i.e. unqualified address)
  1329. R$* $: <?> $1
  1330. R<?> $* < @ $+ > $: <REMOTE> $1 < @ $2 >
  1331. # local user is ok
  1332. dnl is it really? the standard requires user@domain, not just user
  1333. dnl but we should accept it anyway (maybe making it an option:
  1334. dnl RequireFQDN ?)
  1335. dnl postmaster must be accepted without domain (DRUMS)
  1336. ifdef(`_REQUIRE_QUAL_RCPT_', `dnl
  1337. R<?> postmaster $@ TOPOSTMASTER
  1338. # require qualified recipient?
  1339. dnl prepend daemon_flags
  1340. R<?> $+ $: $&{daemon_flags} $| <?> $1
  1341. dnl workspace: ${daemon_flags} $| <?> localpart
  1342. dnl do not allow these at all or only from local systems?
  1343. dnl r flag? add client_name
  1344. R$* r $* $| <?> $+ $: < ? $&{client_name} > <?> $3
  1345. dnl no r flag: relay to local user (only local part)
  1346. # no qualified recipient required
  1347. R$* $| <?> $+ $@ RELAYTOLOCAL
  1348. dnl client_name is empty
  1349. R<?> <?> $+ $@ RELAYTOLOCAL
  1350. dnl client_name is local
  1351. R<? $=w> <?> $+ $@ RELAYTOLOCAL
  1352. dnl client_name is not local
  1353. R<? $+> $+ $#error $@ 5.5.4 $: "553 Domain name required"', `dnl
  1354. dnl no qualified recipient required
  1355. R<?> $+ $@ RELAYTOLOCAL')
  1356. dnl it is a remote user: remove mark and then check client
  1357. R<$+> $* $: $2
  1358. dnl currently the recipient address is not used below
  1359. # anything originating locally is ok
  1360. # check IP address
  1361. R$* $: $&{client_addr}
  1362. R$@ $@ RELAYFROM originated locally
  1363. R0 $@ RELAYFROM originated locally
  1364. R$=R $* $@ RELAYFROM relayable IP address
  1365. ifdef(`_ACCESS_TABLE_', `dnl
  1366. R$* $: $>LookUpAddress <$1> <?> <$1> <Connect:>
  1367. R<RELAY> $*  $@ RELAYFROM relayable IP address
  1368. R<$*> <$*> $: $2', `dnl')
  1369. R$* $: [ $1 ] put brackets around it...
  1370. R$=w $@ RELAYFROM ... and see if it is local
  1371. ifdef(`_RELAY_DB_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl
  1372. ifdef(`_RELAY_LOCAL_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl
  1373. ifdef(`_RELAY_MAIL_FROM_', `dnl
  1374. # check whether FROM is allowed to use system as relay
  1375. R$* $: $1 $| <?> $>CanonAddr $&f
  1376. ifdef(`_RELAY_LOCAL_FROM_', `dnl
  1377. # check whether local FROM is ok
  1378. R$* $| <?> $+ < @ $=w . > $@ RELAYFROMMAIL FROM local', `dnl')
  1379. ifdef(`_RELAY_DB_FROM_', `dnl
  1380. R$* $| <?> $+ < @ $+ . > $1 $| <?> $2 < @ $3 > remove trailing dot
  1381. R$* $| <?> $+ < @ $+ > $: $1 $| $2 < @ $3 > $| $>SearchList <! From> $| <F:$2@$3> ifdef(`_RELAY_DB_FROM_DOMAIN_', `<H:$3>') <>
  1382. R$* $| $* <RELAY> $@ RELAYFROMMAIL RELAY FROM sender ok', `dnl
  1383. ifdef(`_RELAY_DB_FROM_DOMAIN_', `errprint(`*** ERROR: _RELAY_DB_FROM_DOMAIN_ requires _RELAY_DB_FROM_
  1384. ')',
  1385. `dnl')
  1386. dnl')
  1387. R$* $| $* $: $1 restore recipient
  1388. dnl we do not need that right now, but maybe if we add more rules...
  1389. ', `dnl')
  1390. # check client name: first: did it resolve?
  1391. R$* $: < $&{client_resolve} >
  1392. R<TEMP> $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr}
  1393. R<FORGED> $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name}
  1394. R<FAIL> $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name}
  1395. dnl ${client_resolve} should be OK, so go ahead
  1396. R$* $: <?> $&{client_name}
  1397. dnl should not be necessary since it has been done for client_addr already
  1398. R<?> $@ RELAYFROM
  1399. ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl
  1400. R<?> $* $=m $@ RELAYFROM', `dnl')
  1401. R<?> $=w $@ RELAYFROM
  1402. ifdef(`_RELAY_HOSTS_ONLY_',
  1403. `R<?> $=R $@ RELAYFROM
  1404. ifdef(`_ACCESS_TABLE_', `dnl
  1405. R<?> $* $: <$(access Connect:$1 $: ? $)> <$1>
  1406. R<?> <$*> $: <$(access $1 $: ? $)> <$1>',`dnl')',
  1407. `R<?> $* $=R $@ RELAYFROM
  1408. ifdef(`_ACCESS_TABLE_', `dnl
  1409. R<?> $* $: $>LookUpDomain <$1> <?> <$1> <+Connect>',`dnl')')
  1410. ifdef(`_ACCESS_TABLE_', `dnl
  1411. R<RELAY> $* $@ RELAYFROM
  1412. R<$*> <$*> $: $2',`dnl')
  1413. # anything else is bogus
  1414. R$* $#error $@ 5.7.1 $: "550 Relaying denied"
  1415. divert(0)
  1416. ifdef(`_DELAY_CHECKS_',`dnl
  1417. # turn a canonical address in the form user<@domain>
  1418. # qualify unqual. addresses with $j
  1419. dnl it might have been only user (without <@domain>)
  1420. SFullAddr
  1421. R$* <@ $+ . > $1 <@ $2 >
  1422. R$* <@ $* > $@ $1 <@ $2 >
  1423. R$+ $@ $1 <@ $j >
  1424. # call all necessary rulesets
  1425. Scheck_rcpt
  1426. dnl this test should be in the Basic_check_rcpt ruleset
  1427. dnl which is the correct DSN code?
  1428. # R$@ $#error $@ 5.1.3 $: "553 Recipient address required"
  1429. R$+ $: $1 $| $>checkrcpt $1
  1430. dnl now we can simply stop checks by returning "$# xyz" instead of just "ok"
  1431. R$+ $| $#$* $#$2
  1432. R$+ $| $* $: <?> $>FullAddr $>CanonAddr $1
  1433. ifdef(`_SPAM_FH_',
  1434. `dnl lookup user@ and user@address
  1435. dnl one of the next two rules is supposed to match
  1436. dnl this code has been copied from BLACKLIST... etc
  1437. dnl and simplified by omitting some < >.
  1438. R<?> $+ < @ $=w > $: <> $1 < @ $2 > $| <F: $1@$2 > <U: $1@>
  1439. R<?> $+ < @ $* > $: <> $1 < @ $2 > $| <F: $1@$2 >
  1440. dnl R<?> $@ something_is_very_wrong_here
  1441. # lookup the addresses only with To tag
  1442. R<> $* $| <$+> $: <@> $1 $| $>SearchList <!To> $| <$2> <>
  1443. R<@> $* $| $* $: $2 $1 reverse result
  1444. dnl', `dnl')
  1445. ifdef(`_SPAM_FRIEND_',
  1446. `# is the recipient a spam friend?
  1447. ifdef(`_SPAM_HATER_',
  1448. `errprint(`*** ERROR: define either SpamHater or SpamFriend
  1449. ')', `dnl')
  1450. R<SPAMFRIEND> $+ $@ SPAMFRIEND
  1451. R<$*> $+ $: $2',
  1452. `dnl')
  1453. ifdef(`_SPAM_HATER_',
  1454. `# is the recipient no spam hater?
  1455. R<SPAMHATER> $+ $: $1 spam hater: continue checks
  1456. R<$*> $+ $@ NOSPAMHATER everyone else: stop
  1457. dnl',`dnl')
  1458. dnl run further checks: check_mail
  1459. dnl should we "clean up" $&f?
  1460. R$* $: $1 $| $>checkmail <$&f>
  1461. R$* $| $#$* $#$2
  1462. dnl run further checks: check_relay
  1463. R$* $: $1 $| $>checkrelay $&{client_name} $| $&{client_addr}
  1464. R$* $| $#$* $#$2
  1465. R$* $| $* $: $1
  1466. ', `dnl')
  1467. ifdef(`_ACCESS_TABLE_', `dnl
  1468. ######################################################################
  1469. ###  SearchList: search a list of items in the access map
  1470. ### Parameters:
  1471. ### <exact tag> $| <mark:address> <mark:address> ... <>
  1472. dnl maybe we should have a @ (again) in front of the mark to
  1473. dnl avoid errorneous matches (with error messages?)
  1474. dnl if we can make sure that tag is always a single token
  1475. dnl then we can omit the delimiter $|, otherwise we need it
  1476. dnl to avoid errorneous matchs (first rule: H: if there
  1477. dnl is that mark somewhere in the list, it will be taken).
  1478. dnl moreover, we can do some tricks to enforce lookup with
  1479. dnl the tag only, e.g.:
  1480. ### where "exact" is either "+" or "!":
  1481. ### <+ TAG> lookup with and w/o tag
  1482. ### <! TAG> lookup with tag
  1483. dnl Warning: + and ! should be in OperatorChars (otherwise there must be
  1484. dnl a blank between them and the tag.
  1485. ### possible values for "mark" are:
  1486. ### H: recursive host lookup (LookUpDomain)
  1487. dnl A: recursive address lookup (LookUpAddress) [not yet required]
  1488. ### E: exact lookup, no modifications
  1489. ### F: full lookup, try user+ext@domain and user@domain
  1490. ### U: user lookup, try user+ext and user (input must have trailing @)
  1491. ### return: <RHS of lookup> or <?> (not found)
  1492. ######################################################################
  1493. SSearchList
  1494. # if it is H: do lookup?
  1495. R<$+> $| <H:$+> <$*> $: <$1> $| <@> $>LookUpDomain <$2> <?> <$3> <$1>
  1496. R<$+> $| <@> <$+> <$*> $: <$1> $| <$2> <$3>
  1497. dnl A: NOT YET REQUIRED
  1498. dnl R<$+> $| <A:$+> <$*> $: <$1> $| <@> $>LookUpAddress <$2> <?> <$3> <$1>
  1499. dnl R<$+> $| <@> <$+> <$*> $: <$1> $| <$2> <$3>
  1500. dnl lookup of the item with tag
  1501. dnl this applies to F: U: E:
  1502. R<$- $-> $| <$-:$+> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$4 $: $3:$4 $)> <$5>
  1503. dnl no match, try without tag
  1504. R<+ $-> $| <$-:$+> <$*> $: <+ $1> $| <$(access $3 $: $2:$3 $)> <$4>
  1505. dnl do we really have to distinguish these cases?
  1506. dnl probably yes, there might be a + in the domain part (is that allowed?)
  1507. R<$- $-> $| <F:$* + $*@$+> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$3@$5 $: F:$3 + $4@$5$)> <$6>
  1508. R<+ $-> $| <F:$* + $*@$+> <$*> $: <+ $1> $| <$(access $2@$4 $: F:$2 + $3@$4$)> <$5>
  1509. dnl user lookups are always with trailing @
  1510. dnl do not remove the @ from the lookup:
  1511. dnl it is part of the +detail@ which is omitted for the lookup
  1512. R<$- $-> $| <U:$* + $*> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$3@ $: U:$3 + $4$)> <$5>
  1513. R<+ $-> $| <U:$* + $*> <$*> $: <+ $1> $| <$(access $2@ $: U:$2 + $3$)> <$4>
  1514. dnl special case for ERROR because this matches the input mark:address
  1515. R<$+> $| <ERROR:$+> <> $@ <ERROR:$2>
  1516. dnl no match, try rest of list
  1517. R<$+> $| <$-:$+> <$+> $@ $>SearchList <$1> $| <$4>
  1518. dnl no match, list empty: return failure
  1519. R<$+> $| <$-:$+> <> $@ <?>
  1520. dnl got result, return it
  1521. R<$+> $| <$+> <$*> $@ <$2>
  1522. dnl return result from recursive invocation
  1523. R<$+> $| <$+> $@ <$2>', `dnl')
  1524. # is user trusted to authenticate as someone else?
  1525. dnl AUTH= parameter from MAIL command
  1526. Strust_auth
  1527. R$* $: $&{auth_type} $| $1
  1528. # required by RFC 2554 section 4.
  1529. R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated"
  1530. dnl seems to be useful...
  1531. R$* $| $&{auth_authen} $@ identical
  1532. dnl call user supplied code
  1533. R$* $| $* $: $1 $| $>"Local_trust_auth" $1
  1534. R$* $| $#$* $#$2
  1535. dnl default: error
  1536. R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author}
  1537. dnl empty ruleset definition so it can be called
  1538. SLocal_trust_auth
  1539. undivert(9)dnl LOCAL_RULESETS
  1540. #
  1541. ######################################################################
  1542. ######################################################################
  1543. #####
  1544. `##### MAILER DEFINITIONS'
  1545. #####
  1546. ######################################################################
  1547. ######################################################################
  1548. undivert(7)dnl MAILER_DEFINITIONS