home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / mail / sendmail / sendmail.rules < prev    next >
Encoding:
Text File  |  1991-04-29  |  27.0 KB  |  545 lines

  1. (Message inbox:31)
  2. Return-Path: comp.mail.sendmail
  3. From: rickert@mp.cs.niu.edu (Neil Rickert)
  4. Date: Mon, 29 Apr 1991 14:40:19 GMT
  5. Newsgroup: comp.mail.sendmail/2224
  6. Message-Id: <1991Apr29.144019.22206@mp.cs.niu.edu>
  7. Subject: Sendmail address rewrite sequence (was Re: From: , relaying and FAQ)
  8.  
  9.          ----------------------------
  10.  
  11.                   ADDRESS REWRITING IN SENDMAIL.
  12.  
  13.  Prepared by Neil Rickert, Northern Illinois University, Apr 29, 1991.
  14.  <rickert@cs.niu.edu>
  15.  
  16.  The author of this document has no relation whatsoever with the developers of 
  17. sendmail at Berkeley.  Consequently any errors are in no way the fault of
  18. Berkeley.  No guarantee is made as to the accuracy of this document.  Those
  19. who wish guaranteed accurate information must read the source code themselves.
  20.  
  21.  Any comments or corrections are welcome.
  22.  
  23.                      -------------------------
  24.  
  25.  This description is intended to be a more thorough description of address 
  26. parsing than is contained in the usual manual.  Some basic familiarity with 
  27. the manual is assumed.  In particular, we do not attempt to explain the 
  28. rewriting which occurs in a single rule, or the process in which an address 
  29. passes from one rule to the next. 
  30.  
  31.  The description contains a few oversimplifications, such as omitting mention 
  32. of some special cases during internal processing of alias expansions.  These 
  33. simplifications are not directly related to the main issues covered.
  34.  
  35.  I make no guarantees as to the accuracy of this document.  It is based on 
  36. experience with developing and debugging rulesets, and with reading parts of 
  37. the code.  It mostly reflects my understanding of the status of sendmail based 
  38. on the 5.65+IDA versions but with some cross checks with the Berkeley 5.65 
  39. code. 
  40.  
  41. 1.  A BRIEF OVERVIEW OF THE REWRITING PROCESS.
  42.  
  43.     Each address is initially rewritten by ruleset 3.  Thereafter the 
  44.     processing depends on whether this is a recipient address or a sender 
  45.     address.  A sender address is processed by ruleset 1, then by the ruleset 
  46.     declared in the mailer, and finally by ruleset 4.  A recipient address, 
  47.     after processing by ruleset 3, is normally processed by ruleset 2, the 
  48.     ruleset declared in the mailer, and by ruleset 4. 
  49.  
  50.     The above description is, of course, a gross oversimplification.  We shall 
  51.     fill in some of the details below. 
  52.  
  53. 2.  BASIC ADDRESS PARSING.
  54.  
  55.     In order to send a message, the recipient address must be parsed, so as to 
  56.     determine the transport mechanism and the next step in the chain of mail 
  57.     relays.  This is handled in the function parseaddr(), which is in 
  58.     parseaddr.c 
  59.  
  60.     The basic parsing strategy is as follows:
  61.  
  62.     As with all rewriting, the address is first rewritten by ruleset 3.  The 
  63.     result of this rewrite is now rewritten by ruleset 0.  The purpose of 
  64.     ruleset 0 is to resolve the address into a triple: Mailer, Host, 
  65.     User_address.  This resolution occurs when the left hand side matches a 
  66.     suitable rule, and the RHS is rewritten as: 
  67.  
  68.              $# MAILER_NAME $@ HOST_NAME $: USER_ADDRESS
  69.  
  70.     Apart from the exceptions noted below, every address must resolve into 
  71.     such a triple.  If not 'sendmail' will complain.  We should clarify, 
  72.     however, that the user address is allowed to contain a host component.  
  73.     Thus a UUCP address of john@uunet.UUCP might resolve to:
  74.                       $# UUCP $@ uunet $: john 
  75.     while uunet!seismo!harry might resolve to
  76.                        $# UUCP $@ uunet $: seismo!harry
  77.     (In all the above examples the spacing is for readability.  We will comment 
  78.     more on spacing when we discuss the function prescan() later in this 
  79.     document). 
  80.  
  81.     It should also be clarified that the HOST_NAME as returned by ruleset 0 
  82.     does not necessarily have anything to do with the domain component of the 
  83.     original address.  It is the name of the host to which the message will 
  84.     be next sent as known to the transmission software.  For the tcp mailers, 
  85.     this is the fully qualified domain name.  For other mailers it may be 
  86.     different.  In our example above, although the fully qualified uucp name 
  87.     of uunet may be uunet.UUCP, the name known to the uucp software is just 
  88.     uunet, so that must be the host name returned from ruleset 0.
  89.  
  90.     There are two exceptions to the above description.  The local mailer, and 
  91.     the ERROR mailer. Both of these must resolve to just MAILER_NAME and 
  92.     USER_ADDRESS, since a host does not make sense.  (The IDA versions of 
  93.     'sendmail' permit the use of a triple with the local mailer, but ignore 
  94.     the host).  In the case of the ERROR mailer, the USER_ADDRESS is actually 
  95.     the error message.  Thus one could imagine a rewrite rule in ruleset 0. 
  96.  
  97.     R$+@annex1.$D           $#ERROR $:terminal servers don't accept mail 
  98.  
  99.     It is a basic principle of 'sendmail' that ruleset 0 must select a mailer, 
  100.     even if only the ERROR mailer. 
  101.  
  102.     An address which resolves to the ERROR mailer is said to be 'unparseable' 
  103.     and normally leads to bounced mail. 
  104.  
  105. 3.  DIFFERENT CLASSES OF ADDRESSES: ENVELOPES AND HEADERS.
  106.  
  107.     'sendmail' must deal with addresses on the message envelope, and addresses 
  108.     on the headers inside the message.  The distinction between envelope and 
  109.     header is quite important for an understanding of how 'sendmail' 
  110.     functions.  However it can be confusing at first. 
  111.  
  112.     In basic terms, the "header recipients" are the addresses on the "To:" and 
  113.     "Cc:" header lines.  (We could include the "Bcc:" header, but this is 
  114.     usually discarded.)  The "header senders" are the addresses on the "From:" 
  115.     and the "Reply-To:" headers.  Sometimes there may also be "Resent-To:", 
  116.     "Resent-Cc:", "Resent-From:" headers with additional header addresses. 
  117.  
  118.     The "envelope recipients" are the addresses the messages is really being 
  119.     sent to.  They are often different from the "header recipients".  The 
  120.     "envelope sender" is the real sender of the message, and is occasionally 
  121.     different from the "header senders". 
  122.  
  123.     To the novice it often not obvious why there need be a distinction between 
  124.     header and envelope addresses.  When a typical message originates the 
  125.     envelope and header addresses are the same.  However much can change 
  126.     during processing. A message might be sent to two recipients A and B on 
  127.     different machines, host-A and host-B.  Initially both addresses are in 
  128.     the envelope.  However when the message is relayed to host-A, only 
  129.     recipient A remains in the envelope.  Likewise the copy of the message 
  130.     sent to host-B will contain only B in the envelope.  Roughly speaking, as 
  131.     a message is delivered to a recipient address, that address is deleted 
  132.     from the envelope.  However all recipient addresses remain in the headers, 
  133.     as these provide documentation to the human reader of the message as to 
  134.     whom the message was sent to. 
  135.  
  136.     As another example, you may have a '.forward' file in your home directory 
  137.     to forward your mail.  The forwarding action applies only to the envelope 
  138.     recipients of a message, while the addresses on the header are not 
  139.     affected. 
  140.  
  141.     The distinction between header senders and envelope sender is sometimes 
  142.     harder to explain.  We start with an example unrelated to computing.  
  143.     Suppose as a gift you purchase for a friend a subscription to "Scientific 
  144.     American".  As part of the process you fill out a gift card which the 
  145.     publishers will send.  When the gift card arrives, the card says it is 
  146.     from you.  However the return address on the envelope is that of 
  147.     Scientific American.  Essentially you were the header sender, but 
  148.     Scientific American was the envelope sender.  For a comparable example in 
  149.     computing, suppose you post an article in Usenet news.  This article comes 
  150.     from you, and this is shown in the "From:" header.  However at some other 
  151.     site, a copy of your article is mailed to someone without direct Usenet 
  152.     news access.  The Usenet news system on the mailing host is the real 
  153.     sender, or envelope sender, while as the author of the article you remain 
  154.     the header sender. 
  155.  
  156.     In simple terms, the addresses in the headers are for humans to read, 
  157.     while the addresses in the envelope are for machines to read. 
  158.  
  159. 4.  WHERE DO ENVELOPES COME FROM AND WHERE DO THEY GO.
  160.  
  161.     When mail is sent or received over the network with SMTP, the envelope 
  162.     sender is transmitted first in the 'MAIL-From' SMTP command.  Then a 
  163.     sequence of 'RCPT-To' commands transfer the envelope recipients. 
  164.  
  165.     When you send a normal message on your system, the Mail User Agent (MUA) 
  166.     invokes sendmail as:
  167.  
  168.     /usr/lib/sendmail recipient1 recipient2 recipient3 ...
  169.  
  170.     Thus the envelope recipients are passed as parameters on the argument 
  171.     list.  The envelope sender, in that case, is taken from the uid of the 
  172.     person sending the message.  It is also possible to invoke sendmail as 
  173.  
  174.     /usr/lib/sendmail -fsender recipient1 recipient2 recipient3 ...
  175.  
  176.     and thereby give a separate envelope sender.  However sendmail normally 
  177.     will ignore the '-fsender' operand unless given by a trusted user such as 
  178.     'root' or 'uucp' or 'daemon'. 
  179.  
  180.     When 'sendmail' invokes /bin/mail for delivery to your mailbox, it uses a 
  181.     parameter list something like: 
  182.  
  183.     /bin/mail -r sender -d recipient1 recipient2 recipient3 ...
  184.  
  185.     Thus the envelope information is passed along to /bin/mail in a manner 
  186.     similar to the way 'sendmail' received it.  If mail is sent out through 
  187.     UUCP, the envelope sender is recorded on the unix "From " line which is 
  188.     the first line of the message, and the envelope recipients become the 
  189.     command operands to 'rmail' on the remote system. 
  190.  
  191. 5.  TOKENIZING AND REBUILDING ADDRESSES.  prescan() AND cataddr().
  192.  
  193.     Before an address it processed by one of the rewrite rulesets, it must be 
  194.     tokenized.  The rewriting rules only examine complete tokens and strings 
  195.     of tokens during their matching.  After the rewriting is complete the 
  196.     tokenized address must be converted back to a character string.  The 
  197.     function prescan() does the tokenizing, while cataddr() converts a 
  198.     tokenized address back to a character string. 
  199.  
  200.     The output of prescan() is an array of strings, with one array entry for 
  201.     each token.  The tokenizing is done based on the characters in $o, defined 
  202.     in the line beginning 'Do' in 'sendmail.cf'.  There are, additionally, a 
  203.     few characters whose special handling is built into prescan().
  204.  
  205.     In an address such as the following (from RFC822):
  206.  
  207.          Wilt . (the Stilt) Chamberlain@NBA.US
  208.  
  209.     the parenthesized comments "(the Stilt)" are filtered out by prescan().  
  210.     (However when such an address appears on a header, the comments are saved 
  211.     for reinsertion after the address has been rewritten).  prescan() also 
  212.     insists on properly balanced parentheses and properly balanced <angle 
  213.     brackets>.  A string between "double quotes" becomes a single token.  With 
  214.     one exception, an escaped character (such as \@) loses any special 
  215.     properties.  Thus the address 'user@host' would ordinarily become the 
  216.     three tokens "user", "@", "host", while the address 'user\@host' becomes a 
  217.     single token.  The one exception to the backslash escaping is \!, which is 
  218.     simply converted to !.  The special handling is an attempt to be somewhat 
  219.     forgiving to csh users who sometimes become overly zealous in escaping 
  220.     their bangs. 
  221.  
  222.     In tokenizing, special characters (those characters defined in $o) become 
  223.     single character special tokens.  A string of ordinary characters becomes 
  224.     a single token.  The space character, however, is never part of a token 
  225.     except when in a quoted string or when backslash escaped.  The space 
  226.     character is a token separator.  Thus the string AB become one token "AB", 
  227.     while the string A B becomes two tokens "A", "B".  A space before or after 
  228.     a special character, however, is completely superfluous.  Thus user @ host 
  229.     is tokenized as "user","@","host", exactly as would be user@host 
  230.  
  231.     The function cataddr() sounds simple.  Just concatenate all the tokens to 
  232.     form a new string.  This is almost what it does.  But you have to make a 
  233.     special case where there are two ordinary tokens.  If 'A  B' is tokenized 
  234.     as "A","B", then just concatenating the strings would produce the 
  235.     incorrect 'AB'.  Instead, when cataddr() discovers two consecutive 
  236.     ordinary tokens, in inserts between them the space substitute character 
  237.     defined on the 'OB' line of 'sendmail.cf'.  In most versions of 
  238.     'sendmail.cf' this character is the period '.' leading to the effect that 
  239.     the original 'A B' was tokenized to "A","B", then is untokenized to 'A.B' 
  240.     If you don't like this, you can define the space substitute as a blank.  
  241.     If you do so, but forward the message to another 'sendmail' it will 
  242.     probably be converted to a period again.  (One problem with defining the 
  243.     space substitute as a blank is that this can easily become invisible in 
  244.     'sendmail.cf', and if it is accidently deleted you might find you are 
  245.     accidently defining the space substitute to be '\n' or '\0'). 
  246.  
  247.  
  248. 6.  THE C-FLAG PROCESSING.
  249.  
  250.     Certain mailers have the C flag set in their mailer definition.  If 
  251.     effects processing of addresses as follows:
  252.  
  253.     After an address has been rewritten by ruleset 3, a check is done to see 
  254.     if the address now contains an "@".  If it already contains an "@", then 
  255.     C-FLAG processing has no effect.  If there is no "@", the 'receiving 
  256.     mailer' is checked.  (The determination of the receiving mailer is 
  257.     described below).  If the receiving mailer has the C-FLAG defined, and if 
  258.     the sender address in $f contains an '@', everything from the '@' onward 
  259.     in $f is appended to the end of the address as outputted by ruleset 3, and 
  260.     the modified address is now reprocessed by ruleset 3.  The actual check 
  261.     for the '@' in $f is done while the sender address is still tokenized, so 
  262.     there is no additional call to prescan() in the C-FLAG processing.
  263.  
  264.  
  265. 7.  Mailer-specific rulesets.  A typical mailer definition looks something 
  266.     like the following:
  267.  
  268.     Mlocal, P=/bin/mail, F=MFlusr, S=10, R=12, A=mail -d $u
  269.  
  270.     Here the S= and R= operands specify address rewrite rulesets to be used 
  271.     for mail sent by this mailer.  The S= operand is for sender addresses, and 
  272.     the R= is for recipient addresses.  We shall refer to these as the mailer-
  273.     specific rulesets.  In the IDA version of sendmail, these can optionally 
  274.     be specified as say S=13/15, etc.  This would use ruleset 13 for envelope 
  275.     sender addresses and ruleset 15 for header sender addresses.  The simple 
  276.     definition S=10 is equivalent to S=10/10.
  277.  
  278.     If the mailer specific ruleset is omitted, or is defined as 0, this means 
  279.     that there is no mailer-specific ruleset.  Ruleset 0 itself is never used 
  280.     as a mailer-specific ruleset.
  281.  
  282. 8.  A MORE DETAILED LOOK AT SENDMAIL PROCESSING.
  283.  
  284. 8a. Parsing the sender address.
  285.  
  286.     One of the first steps is to parse the envelope sender address.  This 
  287.     follows the procedure of address parsing as described above.
  288.  
  289.     prescan()
  290.     rewrite with ruleset 3.
  291.     rewrite with ruleset 0.
  292.     rewrite the user address portion with rulesets 2, the mailer specific 
  293.     ruleset, and ruleset 4.
  294.     process the output of ruleset 4 with cataddr()
  295.  
  296.     If the address proves unparseable a message is written to the log, and the 
  297.     address 'Postmaster' is parsed in its place.  One effect is that should 
  298.     the mail be undeliverable, and the sender address is unparseable, any 
  299.     bounced mail will in this case be delivered to Postmaster.
  300.  
  301.     The mailer returned from ruleset 0 is called the receiving mailer, and is 
  302.     examined for the presence of a C flag as discussed above in our 
  303.     description of C-FLAG processing.
  304.  
  305.     If the receiving mailer is the local mailer, the sender is assumed local.  
  306.     In that case the user address is looked up in the password file to find 
  307.     the full name (for possible use on the 'From:' header) and the home 
  308.     directory (in case the message should be stored in dead.letter).
  309.  
  310. 8b. Defining $f.
  311.  
  312.     The sender address is processed with
  313.  
  314.     prescan()
  315.     rulesets 3,1,4
  316.  
  317.     Search for an '@' in the address, and save a copy of the portion of the 
  318.     tokenized address starting with the '@', in case needed for C-FLAG 
  319.     processing.
  320.     
  321.     apply cataddr() to the output of ruleset 4, and save as the value of $f
  322.  
  323.     NOTE:  Even if the original address was determined to be unparseable in 
  324.     step 8a, and replaced by Postmaster, it is still the original address and 
  325.     not 'Postmaster' which is used for defining $f.  However there is one 
  326.     anomoly here.  If the message cannot be delivered immediately but must be 
  327.     queued, and if the original sender address was unparseable, the original 
  328.     sender address is not saved in the queue file, so the sender will become 
  329.     'Postmaster' in that case. 
  330.  
  331. 8c. Building the recipient list.
  332.  
  333.     Each envelope recipient address is now added to an internal list of 
  334.     recipients.  Before an address is added to the recipient list, it goes 
  335.     through the following procedures: 
  336.  
  337.     prescan()
  338.     rewrite with ruleset 3
  339.     rewrite with ruleset 0
  340.      The mailer and host returned are saved.  The user portion is further
  341.     processed:
  342.     rewrite with ruleset 2
  343.     rewrite with the mailer specific ruleset (for the mailer returned by 
  344.        ruleset 0)
  345.     rewrite with ruleset 4.
  346.     cataddr()
  347.  
  348.     Next the recipient list is searched to see if this address already 
  349.     appears.  The search is based on a comparison of the mailer returned by 
  350.     ruleset 0, the host returned by ruleset 0 (except the host is ignored if 
  351.     the 'l' flag is set for the mailer), and the user name as output from 
  352.     cataddr().  If the address is a duplicate it is not actually added to the 
  353.     recipient list.
  354.  
  355.     Next the mailer is checked to see if the local mailer.  If so, the address 
  356.     is looked up in the aliases database.  If there is an aliases entry the 
  357.     current address is flagged QDONTSEND so that mail will not be sent to it, 
  358.     and each entry in the alias expansion recursively goes through the same 
  359.     process for adding to the recipient list.  An additional flag is set for 
  360.     aliases to indicate they are indeed aliases. 
  361.  
  362.     Next, if the mailer is the local mailer, and if the QDONTSEND flag is not 
  363.     set, there is a test to see if the user address begins with '|' after 
  364.     removal of quotes.  If so, and if the address is from an alias expansion, 
  365.     the mailer is changed to the 'prog' mailer, and the initial '|' is 
  366.     removed. 
  367.  
  368.     Next, if the mailer is local, the name is looked up in /etc/passwd, the 
  369.     home directory searched for a '.forward' file which, if found, is treated 
  370.     to similar processing as an aliases entry.
  371.  
  372.     If at any stage something goes wrong, the address is flagged as bad for a 
  373.     later bounce message.
  374.  
  375. 8d. Beginning the delivery phase.
  376.  
  377.     Once the recipient list is complete, sendmail is ready to attempt 
  378.     delivery.  This involves running down the recipient list.  As an address 
  379.     is selected for a delivery attempt, it is marked QDONTSEND which is 
  380.     approximately the equivalent of deleting it from the recipient list.  This 
  381.     is to ensure it will not be sent twice.
  382.  
  383.     Once an address is found for a delivery attempt, a check is made to see if 
  384.     the 'm' flag is set in the mailer.  If so, sendmail will attempt to send 
  385.     to as many recipients with the same mailer/host combination as possible in 
  386.     a single operation.
  387.  
  388.     If delivery requires sending to several hosts, the next few steps will be 
  389.     repeated several times.
  390.  
  391. 8e. Determining the envelope sender for delivery.
  392.  
  393.     Start with the expansion of $f
  394.     prescan()
  395.     rewrite with rulesets 3, C-FLAG processing, 1, the mailer specific 
  396.     ruleset, and 4.
  397.     cataddr()
  398.     The result is assigned to $g
  399.  
  400.     Note that, because of the way $f was originally determined, this means the 
  401.     original incoming address has been processed by 3,1,4,3,1,mailer 
  402.     specific,4 
  403.  
  404. 8f. Determining the command. 
  405.  
  406.     The command (the P= and A= operands) from the mailer definition are now 
  407.     expanded, with $h evaluating to the host.  If there are multiple 
  408.     recipients, and $u is in the last argument, multiple such arguments are 
  409.     created, one for each recipient for this delivery transaction.  If there 
  410.     is no $u in the argument list, the SMTP protocol is used instead.
  411.  
  412.     For SMTP use only, the recipient address is now processed by
  413.     prescan(), ruleset 3, C-FLAG processing, 2, mailer specific, 4, cataddr(). 
  414.     The IDA versions, however, do not do this additional rewriting step which 
  415.     seems superfluous, and which could conceivably cause mailing loops because 
  416.     of the C-FLAG processing. 
  417.  
  418. 8g. Header rewriting.
  419.  
  420.     The headers are now sent to the mailer program as part of the message.  
  421.     Before sending them they are subject to any rewriting.  If the required 
  422.     'From:' header does not exist it is created from the definition in 
  423.     'sendmail.cf'.  If the required 'To:' is missing an 'Apparently-To:' 
  424.     header is created. 
  425.  
  426.     A special word on the 'From:' header.  If the incoming message has a 
  427.     'From:' header whose contents are identical in all respects (except 
  428.     leading and trailing white space) to the envelope header, that 'From:' 
  429.     header is deleted.  The assumption is that it will be recreated with a 
  430.     chance of adding the full name.
  431.  
  432. 8h. Header sender rewriting.
  433.  
  434.     The address is extracted from the 'From:' header and other similar headers 
  435.     such as 'Reply-To:' and 'Resent-From:', carefully saving the comments for 
  436.     later use.  The address is processed with
  437.     prescan(), 3, C-FLAG processing, 1, Mailer specific, 4, cataddr().
  438.  
  439.     The IDA versions use ruleset 5 in place of ruleset 1.  This is part of the 
  440.     IDA strategy of allowing a distinction between the formatting of headers 
  441.     and the formatting of the envelope.
  442.  
  443.     If there was no "From:", or if it was deleted and must be recreated, the 
  444.     usual definition of "From:" in most version of 'sendmail.cf' begins with 
  445.     $g, or with $q which is defined in terms of $g.  In that case, and 
  446.     remembering how $f and then $g are determined, the address on the 'From:' 
  447.     goes through the following steps: 
  448.  
  449.     incoming envelope sender
  450.     prescan(), rulesets 3,1,4, cataddr()
  451.     prescan(), rulesets 3, C-FLAG, 1, Mailer specific, 4, cataddr()
  452.     prescan(), rulesets 3, C-FLAG, 1, Mailer specific, 4, cataddr()
  453.  
  454.     You will note the large amount of redundancy.  If designing rulesets you 
  455.     must keep this in mind.  In particular you should be wary of approaches 
  456.     which give different results depending on how many times the address is 
  457.     passed through rulesets 3,1,Mailer-specific,4.  In the current IDA/NIU 
  458.     rulesets, the $q variable is defined in terms of $f instead of $g, in 
  459.     order to eliminate the most troublesome one of these extra rewrites, in 
  460.     which a header address is rewritten with a mailer specific ruleset 
  461.     intended for envelope addresses only. 
  462.  
  463. 8i. Recipient header rewriting.
  464.  
  465.     Each recipient address on a "To:" or "Cc:" or "Apparently-To:" or 
  466.     "Resent-To:" or "Resent-Cc:" header goes through the following steps: 
  467.  
  468.     prescan(), rulesets 3, C-FLAG, 2, Mailer specific, 4, cataddr().
  469.  
  470.     In the above, the IDA versions use ruleset 6 in place of ruleset 2.  Again 
  471.     this is to allow header addresses to be formatted differently from 
  472.     envelope addresses.
  473.  
  474. 9.  GENERAL COMMENTS ON DESIGNING RULESETS.
  475.  
  476.     If you plan on designing your own 'sendmail.cf', or modifying an existing 
  477.     one to add more functionality, here are some things to keep in mind:
  478.  
  479. 9a. Remember the C-FLAG.
  480.  
  481.     Because of the C-FLAG processing, it is desirable that every address which 
  482.     contains a host name should contain an '@' by the end of ruleset 3, and 
  483.     addresses without hostname should not have one added in ruleset 3. 
  484.  
  485.     This also means that if you want to rewrite 'user' as 
  486.     'user@your.full.domain' you should not do it in ruleset 3, but should do 
  487.     it somewhat later. 
  488.  
  489.     This means that an address like 'uunet!seismo!harry' needs to be converted 
  490.     to something like 'seismo!harry@uunet.UUCP' in ruleset 3, so as to ensure 
  491.     that there is an '@' in the address and C-FLAG processing doesn't 
  492.     incorrectly add another domain level. 
  493.  
  494. 9b. Make major rewriting steps reversible.
  495.  
  496.     Ideally any address processed by ruleset 3 followed by ruleset 4 should 
  497.     finish up in its original form.  Anything non-reversible done in ruleset 3 
  498.     can never be fully compensated for later.  This is difficult to do in 
  499.     practice, however.  In many versions of sendmail.cf, both 'uunet!john' and 
  500.     'john@uunet.uucp' will be rewritten as 'john<@uunet.UUCP>' in ruleset 3, 
  501.     so the original form cannot always be recovered by use of ruleset 4.  What 
  502.     is probably more critical is that using rulesets 3,4,3,4 should yield the 
  503.     same result as just using 3,4.  If your rulesets don't manage at least 
  504.     this degree of consistency you are likely to run into major problems.
  505.  
  506.     The IDA/NIU rulesets are pretty close to the ideal that ruleset 4 
  507.     completely reverse ruleset 3.  But to achieve this they use in internal 
  508.     form which only vaguely looks like the original address.  Thus in these 
  509.     ruleset 3 would rewrite 'uunet!john' as '<@uunet.UUCP>!john' while they 
  510.     would rewrite 'john@uunet.UUCP' as '<@uunet.UUCP>,john'.  And, of course, 
  511.     ruleset 4 is rather more complex also.  (This approach in IDA/NIU is not 
  512.     simply a matter of purism.  It has to do with the need to be able to 
  513.     unambiguously merge two addresses in the pathalias file lookup.) 
  514.  
  515. 9c. Allow for the fact that sender addresses may be rewritten multiple times.
  516.  
  517.     The habit of sendmail of reprocessing sender addresses can cause some 
  518.     problems and result in incorrect addresses if you do not properly allow 
  519.     for it.
  520.  
  521. 9d. Be particularly cautious with how you handle envelope recipients. 
  522.  
  523.     Basically if you mess these up, the mail probably won't go anywhere, or 
  524.     won't go where you want it.
  525.  
  526.     As an example, suppose I have a uucp neighbor 'uuhost'.  Suppose my 
  527.     neighbor wants all mail to leave in the format 
  528.     'uuhost!user@my.full.domain'.  Now it might be that I become a little too 
  529.     vigorous in my changes, and I even rewrite the addresses that way in mail 
  530.     sent to 'uuhost'.  If this happens to a header address the problem is not 
  531.     very serious.  At the worst, when someone on 'uuhost' sends a reply, the 
  532.     reply will be sent first to my system, then back to 'uuhost'.  But if I 
  533.     make the same transformation to the envelope, I will cause a mailing loop.  
  534.     In other words, if mail I see destined for 'uuhost!user' is sent to 
  535.     'uuhost' with the user address of 'uuhost!user@my.full.domain', the mailer 
  536.     on 'uuhost' is likely to just send it back.  Then the same thing happens 
  537.     over and over again.
  538.  
  539.  
  540. -- 
  541. =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  542.   Neil W. Rickert, Computer Science               <rickert@cs.niu.edu>
  543.   Northern Illinois Univ.
  544.   DeKalb, IL 60115                                   +1-815-753-6940
  545.