sendmail Overview For the Advanced User


Contents

About this document
      Related documentation
Changing sendmail behavior
macros(D), classes(C) and options(O)
Processing of the sendmail.cf file
Parsing and identifying tokens
Introduction to rule sets
A sample rule set
How rules are evaluated
sendmail's configuration commands
Rule sets S0 - S6
The LHS operators
Designing rules using LHS operators
The RHS operators

About this document

This document discusses the functionality of sendmail, a compiled executable with plenty of built-in flexibility. This flexibility makes sendmail unique and versatile but at the same time, it can be difficult to understand. As a result, the information in this document is intended for system administrators, programmers, and technical support personnel who already have a solid understanding of sendmail.

This information applies to the following AIX and sendmail versions.

   AIX 4.2.0     sendmail 8.7
   AIX 4.2.1     sendmail 8.7
   AIX 4.3.0     sendmail 8.7
   AIX 4.3.1     sendmail 8.8.8
   AIX 4.3.2     sendmail 8.8.8
   AIX 4.3.3     sendmail 8.9.3

Related documentation

For further information on this subject, the following references are recommended:

Changing sendmail behavior

The best known interface to the executable is the sendmail.cf configuration file through which you can change the behavior of sendmail. Even if the sendmail.cf file is not altered, the executable reads certain information from the system, DNS lookup, alias lookup, or a combination of these.

Compare sendmail with IBM's RPG. Both sendmail and RPG are Fixed Logic Executables, and the flow and cycle they go through cannot be changed. However, some modifications can be made. Like RPG, there are several state indicators. Depending on the prescribed states, the executable modifies its logic and flow on a micro level. On an overall level, the behavior never changes. This is also true for sendmail, which has classes, macros, aliases and rule sets. These indicators of possible values are dependent on the version and make of the sendmail executable. You must know which indicator to modify to obtain the desired effect.


macros(D), classes(C) and options(O)

How macros work

sendmail.cf contains a macro definition called Dw, which stands for the host name. D means "define", equivalent to #define in C the language. In C, #define can be local or global. If it is local, #define is active only within the subroutine; if it is global, it is active everywhere within the executable. sendmail's Dw is global; therefore, this macro is active throughout. sendmail also has local macros, discussed later in this document, that are active only within the module. The Mailer module of sendmail, actually a subroutine, is local.

Dw is the host name of the system. If you quote this out as #Dw, it still obtains the host name by actually running the command hostname, and puts the name in the place of Dw. sendmail gets this information either from the /etc/hosts file or actually doing a DNS query.

Dm is the domain name of the system, and as with Dw, sendmail gets the information even if you do not supply it. If DNS and /etc/hosts have conflicting entries, sendmail will be confused. In older versions of sendmail, the program actually incorporates these values in the modified executable while it is compiled along with sendmail.cf. In sendmail Version 8.8.7, compiling the configuration file is not required. Instead, the values are incorporated automatically while the daemon (the modified executable) is turned up.

The first part of the configuration file consists of definitions like #define in C. sendmail's configuration file contains macros, options, and so on. What actually occurs is that a variable is read from the configuration file and passed on to the executable to take effect. You must know what the variable is supposed to do. Do not assume that the meaning of a macro name in one sendmail will be the same with any other, even across releases. The information is usually provided as comments within the configuration file.

There are a few other interesting items. For example, CP means top level domain and is usually set to "." (period), the root domain of all addresses. Consider what would happen if . were changed to something like .com.

Another interesting macro is DM, found in Version 8.8.7 and later of sendmail. It stands for "domain to masquerade". This macro overrides your actual domain of the system and puts a mask on it to indicate it is running on another domain.

The DS macro is very useful. This macro defines the host to which all mail is forwarded. It stands for "define smart relay" and the format is [mailer]:[relayhostname], where mailer can be smtp, esmtp or uucp. This definition will be active only for non-local domain. For example, if sendmail domain Dm=bttb.net gets mail for bttb.net, it will be distributed locally, but for x@hotmail.com, the mail will be forwarded to the firewall (relay host) for sendmail to handle. The receiver will see the mail coming from bttb.net if the DM is not set. For example, if DM=naughty.com, the receiver will see that the mail is coming from naughty.com instead of bttb.net.

The difference between a macro and an option

There are a few differences between a macro and an option. A macro can be referenced but an option cannot. For example, Dm=bttb.net is a macro. Once it is defined, it can be referenced as $m, and it will have the value bttb.net. It is important to reference a macro in the rule sets. You can compare this macro with $1, $2 and so on of the UNIX shell command line parameter passing, which is similar. Options are actually constants once they are defined.

Following are examples of an option, a class, and a macro:

Option
"O DeliveryMode=background"
Mail is delivered in the background.

Class
"CO @ % !"
Local user name cannot contain these characters.

Macro
"Dm bttb.net"
Local domain name.

Comparing sendmail with C, sendmail's option defines a constant. Class defines a variable class such as integer, character or floating point and macro defines or associates a string with a variable.

Referencing macros(D) and options(O)

To illustrate how macro definitions can be referenced, take the definition Dm bttb.net, for example. The definition is global and may now be referenced with $m. The machine name may be expressed as dns.bttb.net or dns.$m.

Another macro definition, DH dns, which is host name, may be referenced as $H.$m. In comparing with C, the C statement #define H 'dns' is the same as the definition DH dns. Also, as #define can be either local or global, so can a macro in sendmail. macros are expanded while reading the sendmail.cf file.

Now, with the class definition Cw firewall dns, the strings firewall and dns are assigned to the class w. From this point on, in this example, using the reference $=w will obtain the values firewall and dns just like an array. (Remember, in this example, $w references the macro which obtains the value dns.)


Processing of the sendmail.cf file

sendmail reads the sendmail.cf file from left to right. In effect, while it is reading, sendmail acts as a lexical parser; while it is turning on the daemon, it acts as a compiler. As a result, sendmail has debugging capabilities which will be discussed later.

As a parser, sendmail has a work space and it creates tokens from the values found in the configuration file while it is reading it. For macros, sendmail expands it to the value you set or the value it reads from the system. Options, headers and others are treated similarly. For classes, sendmail sets up assignments and creates tokens from the values.


Parsing and identifying tokens

In this section, various examples are used to illustrate how sendmail parses and creates tokens. The previously introduced string dns.bttb.net is used for the first example. From a previous section, we know this string can be called with $w.$m when Dw dns and Dm bttb.net is declared.

Parsing scans the dns.bttb.net from left to right. The string is also interpreted as the following tokens in exactly this sequence.

These tokens are referenced just like in a UNIX shell. dns can be referenced as $1, bttb as $2, and net as $3. So, from within this workspace, the string dns.bttb.net can be stated as $1.$2.$3.

The string dns.$m presents a more complex example. If you recall, $m is the domain name as defined by Dm bttb.net. Since Dm is a macro, it is expanded to bttb.net. As a result, sendmail creates the three tokens dns, ., and bttb.net. Similarly, since macros are like constants when they are expanded, these tokens can be referenced as $1 = dns and $2 = bttb.net. Now, the second portion of the string (bttb.net) can no longer be referred to separately.

In the next example, the string dns.$=m is used. Assume the following declarations: Dw dns, Dm bttb.net, and Cw bttb.net. $=m is a class macro. As in the previous example, the parser scans the string as dns, . , bttb.net. The tokens can also be referenced as $1 = dns and $2 = bttb.net.

A class is a special type of macro, similar to the #define array in C, and this is where there is a difference from the previous example. With class macros, string arrays are never expanded like in D macros, so it is actually available in the workspace when it is parsed.

For the final example, the string dns.$=m is being parsed, where Cm bttb.net my.domain is declared. In this case, the reference $1 has the value of dns and $2 has the value of either bttb.net or my.domain. This sort of coding is used in rule sets, which is covered in the next section. Depending on a comparison of the rules, the $2 reference will be assigned only one of the values.


Introduction to rule sets

Because different mailers use different formats to deliver mail messages, sendmail receives addresses in a number of different formats. sendmail changes the addresses to the format needed to route the message for the mailer program being used. To perform this translation, sendmail uses a set of rewrite rules, or rule sets, that are defined in the /etc/sendmail.cf configuration file.

A sample rule set

This section makes use of the fictitious rule below to illustrate the rule set concept.
##################################
#Rule Set 100 - A sample rule set 
##################################
S100
R_if_A=10_then         B=15        If value of A meets criteria, set value of B as stated (rule no 1)
R_if_C=110_then        A=1         If value of C meets criteria, set value of A as stated (rule no 2)
################################
#End of Rule Set 100
################################

In this example, S100 defines the set number. Let's assume that before S100 is entered, the values for the variables are: A=2, B=0, C=110. In simplified terms, rules can be considered, If Then Else statements.

This is how the rule works. sendmail processes the rules from left to right only once. It is not recursive. There are three parts to a rule: the lefthand side (LHS), the righthand side (RHS), and the comments, which are ignored. In the example, the values are

   LHS = "R_if_A=10_then"
   RHS = "B=15"
   Comment = "If value of A meets criteria, set value of B as stated (rule no 1)" 

The general logic used in processing rules is:

   If LHS is true then execute RHS; 
   else process the next rule until all rules are exhausted within the set;
   return;

Looking at the example again, in rule 1, the LHS is not true (A=/10). The RHS statement will therefore not be executed. The flow will go to the next immediate rule, rule 2. Here, the LHS is true so the RHS statement is executed. The assignment A=1 is set.

There are no more rules (or instructions), so the flow will return to the calling module if S100 was called by one. If it was not called by a module as a subroutine, like in the C language, the flow will continue to the next set.

Using sets as a subroutine

Sets can also be used as subroutines. To illustrate, let's assume another rule set, S31, calls rule set S100. When S100 has finished executing, control returns to the statement in S31 that made the call to S100.

The normal flow is to go through the sets from top to bottom within the file. The following example illustrates this flow.

   ###########################
   S1
   Rxxxx      yyyy
   S31
   R_CALL_S100  jjjjjjj
   Raaa     bbb
   S40
   S100
   Rdddd      ffffff
   ###########################

Flow control starts with S1 then goes to S31 where S100 is called and returns to the statement R_CALL_S100 jjjjjjj. This statement executes only if LHS evaluates to true. Control then goes to the next rule Raaa bbb to carry out the given instructions and continues until it finds the null set S40 where it does nothing and does not produce errors. The control then flows to S100 again.

To prevent S100 from executing again, place an END statement in S40. By doing so, S40 will act as the end of flow and all subroutines can be placed after the S40. The flow is non-recursive so control will not return to a set unless it is explicitly called.


How rules are evaluated

Recall the flow logic within a rule set:
   If LHS is true then execute RHS; 
   else process the next rule until all rules are exhausted within the set;
   return;

This is how each rule, that is, each R_statement, is evaluated, line by line. The sendmail binary evaluates the tokens, one by one. An example may best illustrate this concept.

Example of how a rule is evaluated

The following R_statement will be examined in this example:
   Reric.allman                nancy.allman
   ____________    _________   _____________ 
   LHS             TAB         RHS

The rule statement requests the LHS to be compared with the workspace to check if the LHS contains eric.allman. If it evaluates to true, the workspace should be replaced with nancy.allman. The workspace is a working buffer area of the sendmail binary where all the tokens are kept by address tags. Through the workspace, the sendmail binary knows where to find a variable's value. It is similar to pointers in the C language.

If the workspace contains the value eric.allman, the LHS evaluates to true because it is an exact match, token for token. The tokens being eric, ., allman . The sendmail binary replaces the previous value, eric.allman, with the new value, nancy.allman. The workspace now contains the tokens nancy, ., allman.

Rather than the control passing on to the next rule, the same rule is evaluated again comparing the LHS with the new workspace value, nancy.allman. This time, the LHS evaluates to false and control is passed on to the next rule in the set.

It is important to exercise caution in declaring rules as they can end up in perpetual loops. For example, assume the workspace contains the value eric.allman and the rule is:

   Reric.allman	eric.allman
In this case, the LHS always evaluates to true causing the sendmail binary to hang in a loop. Now, assume that the workspace contains the value nothing.there before entering the same, preceding rule. Since the LHS evaluates to false, control immediately passes on to the next rule in the set. The logic within rules and within sets can be summarized as follows:

Logic within a rule
While LHS is true, do RHS

Logic rules follow within a set
If LHS is true then execute RHS;
else process the next rule until all rules are exhausted within the set;
return;


sendmail's configuration commands

Commands like S and R, presented earlier are called configuration, or config, commands on sendmail. The following list contains the more widely used commands.

S - The Set config command defines the rule sets. The syntax is S# where # can be a number in decimal or hex digits. This is one of the ways in which sendmail can be made cryptic. sendmail uses the subroutine atoi() to convert the value to the actual number it stores. In the header definitions, there is limit on the maximum value allowed for #. This limit may cause an error if a rule is defined with a very high # such as S200, for example, depending on the version of sendmail.

R - The Rule config command defines the instruction to be performed. Several operators such as $@, $+, are used in its syntax. These are discussed later in the document.

D - The Macro config command. Macros can take three forms, namely, a single value, an association of strings (the C config command), or a database containing either single values and/or an association of strings (the F config command). These three types of macros can be thought of as constant, strings, and database.

O - The Options config command. Various options can be defined through this command. Options set a single value to a global variable in sendmail. In other words, the default value that is preassigned in the sendmail binary is changed. If nothing is changed, it still assigns value to the default.

P - The Preference config command sets mail delivery priority and other options. This command differs from other config commands in the sense that it inputs values to actual functions in sendmail on which certain calculations are based.

H - The Header config command is used to modify/define the Sender/Recipient header information in sendmail.

T - The Trusted config command defines the valid users or UIDs (user IDs) for sendmail.

M - The Mailer config command defines the mailer for sendmail.


Rule sets S0 - S6

sendmail reserves and defines this series of sets to perform very specific tasks. Taken together, this basic combination of sets control sendmail logic and flow. Their specific tasks are listed next.

S0 - This rule set resolves to a triple. That is, it must resolve the recipient user, the recipient host and the transferring mailer, such as smtp, to send mail.

S3 - This rule set preprocesses all addresses used in sendmail. It converts addresses received in different formats from various mailers to a format needed to route the message for the mailer program being used.

S1, S= - This pair rule set is called S one and S equate. Its function is similar to that of the S3. It rewrites sender address information received in various formats into a format suitable for processing by sendmail and to conform to certain Requests for Comments (RFCs). It converts such envelope header information as From:.

S2, R= - This pair rule set is called S two and R equate. It rewrites recipient addresses into a valid sendmail format which conforms to RFCs. It converts such envelope header information as To:, cc:, and bcc:.

S4 - This rule set reverses the changes of the S3 rule set since sendmail must return the message in the original format submitted by the mailer before sending. Then, it transmits the message.

NOTE: Without exception, all addresses are processed first by S3 and last by S4. Also, sendmail processes recipient addresses first and then sender addresses. It is possible to have more than one sender in sendmail.

Actual flow of logic within these sets

Following is a diagram of the flow of logic.
                    ----------> S0 -------------------> MTA  -------> Xmit msg.
                    |
                    |
                    |
                    |
Inputs --->S3 ----->S2 --------> R= ------|
                    |                                |
                    |                                |
                    |                                |----> S4 ----> Returns to called module
                    |                                |
                    -----> S1 --------> S= -----|

The recipient address will be traced first. It first enters S3 and then S0 which resolves the triple. From within S0, it calls the path S2, R= and S4 from which it gathers necessary information to send the message. sendmail processes one address at a time; the recipient address is processed first.

The sender address enters S3 then S0 which calls S1, S=, and S4. Through this path, it gathers necessary information to send the message. Upon completion of these steps, sendmail sends the message out using the mailer resolved by the triple.

S= and R= - These are defined in the sendmail.cf file. For example, if the values assigned are S=10 and R=20, the code calls the subroutine S10 for S=10 and S20 for R=20. This is a valid way to insert more user-defined sets to perform additional tasks on the flow.

S5 and S6 - In mail transfer agents (MTAs) such as SMTP, S1 and S2 process the sender and recipient envelope addresses respectively. The UUCP MTA consists of a two part address: the envelope and header. S5 and S6 process the header portion of the address. S5 processes the sender header address whereas S6 processes the recipient header address.

Below is a diagram depicting a UUCP-based transmission.

                          ------------------> S0 -------------------------> MTA  -------> Xmit msg.
                          |
                          |
                          |
                          |
Inputs --->S3 ----->|------------------> S2 -------------> Re= ---------|
                          |                                                         |
                          |                                                         |
                          |                                                         |----------> S4 -------> Returns to called module
                          |                                                         |
                          -------------------> S1 --------------> Se= --------|
                          |                                                         |
                          |                                                         |
                          |                                                         |
                          |-------------------> S5 -------------->Sh= ---------|
                          |                                                          |
                          |                                                          |
                          |                                                          |
                          |-------------------> S6 ---------------> Rh= -------|
As stated earlier, S5 and S6 handle the sender header and the recipient header respectively as denoted by the lowercase h. Similarly, S1 and S2 handle the envelope as denoted by the lowercase e.

The mailer

To illustrate the use of the mailer configuration command, an example of a mailer definition is displayed below. It is defined for local delivery and is taken from sendmail for AIX Version 4.2.
   Mlocal,	P=/bin/bellmail, F=lsDFMAw5:/|@mn, S=10/30, R=20/40,
   		T=DNS/RFC822/X-Unix,
		A=mail -F $g $u
The syntax follows:

M defines the mail delivery agent called local which, once defined, may also be referenced elsewhere. P= (P equate) contains the path of the program which will be used for this purpose defined by Mlocal in the example. This program, defined as /bin/bellmail in the example, wil be called for delivery of local mail.

F= (F equate) are the flags which define the agent more specifically.

A= (A equate) defines the command line arguments specified for each program. It is similar to the C language argv().

R= and S= definitions. S=10/30 tells the mailer to use rule set S10 for sender envelope processing and S30 for sender header processing. Similarly, R=20/40 instructs the mailer to use rule set S20 for recipient envelope and S40 for recipient header processing.

If the example was not a UUCP-based transmission, the mailer definition could look something like the following:

   Mlocal,		P=/bin/bellmail, S=10, R=20
In this case, only the envelope portion of the address is handled.

The rules

First, a simple example illustrates the use of rules once again. A workspace that contains the value here is rewritten to the value there given the rule Rhere      there.

The next example uses the operator $+, which matches one or more tokens. This is an LHS operator. Recall that the LHS compares and the RHS rewrites. As a result, LHS and RHS have different operators. See the sections "The LHS operators" and "The RHS operators" in this document. In the example, the workspace contains the value smm@ibm. The rule reads:

   R$+@ibm        smm@internet
The workspace separated into tokens now looks like the following:
   smm     @     ibm

The rule R$+@ibm asks the parser to look for one or more tokens in front of the absolute address @ibm. It is absolute since it does not have any operators looking for @ibm. The parser scans the workspace from left to right and finds the smm token and then the @ token. The pattern specified by the rule is found, that is, it finds one or more tokens in front of the @ and ibm tokens. It then is able to match $+ to smm and rewrites the workspace as the value in RHS.

With the same rule, now suppose the workspace contains smm.bd@ibm. Again, it checks the tokens in front of @ibm. It finds smm.bd and sets $+ to this value. Additionally, when an operator is matched, a positional value is assigned. For example, a positional value of $1 is assigned to smm in the first case and a value of smm.bd is assigned in the second case.

As the parser scans from left to right, it finds the $+ operator and uses $1 to refer to it if a match is found. If there were a second operator, it would similarly assign $2 to it if a match was found. These positional assignments may be used in the RHS with the same effect but with added flexibility. So, the first rule may also be written as:

   R$+@ibm        $1@internet

The LHS operators

This section discusses a set of operators used on LHS. A summary of the operators can be found below.
   LHS Operator	   Function
   ---------------------------------------------------
      $+           Matches one or more tokens.
      $-           Matches exactly one token.
      $*           Matches zero or more tokens.
      $@           Matches exactly zero tokens.
      $=           Matches any in a class macro.  
      $~           Matches any not in a class macro.
   ---------------------------------------------------
An example will best illustrate the use of these operators in rules. Assume the workspace contains smm.ibm.bd@sg.ibm.com, the basic form is user@domain@route. The rule should compare the string in the workspace for domain sg.ibm.com and rewrite this to a user@internet form.

The $+ operator
The parser scans the workspace from left to right looking for the pattern sg.ibm.com since this is the only domain that should be rewritten. This constitutes the absolute portion. sg.ibm.com should be tagged as the user portion of the user@internet form. To allow the user portion to contain more than one token, the $+ operator will be used, since this operator matches one or more tokens. If the pattern is matched, it will be tagged as $1 by the parser for use in the RHS.

The $- operator
For the second portion of the user@internet form, one exact token should be matched: internet. The $- operator, in this case, is suitable since it matches only one token. In effect, the $- operator restricts this portion of the form to only one token so the rule will discard addresses such as internet.bitnet. If matched, the parser will assign a tag of $2 to this pattern to be used in the RHS.

The rule can be written in either of the following ways to successfully meet these requirements:

   R$+@sg.ibm.com@$-        $1@$2
   R$+@sg.ibm.com@$-        $1@internet
   R$+@sg.ibm.com@internet  $1@internet

The $* operator
Now, let's assume the smm.ibm.bd@sg.ibm.com@internet form should be rewritten to the user@internet form for any domain. The absolute address sg.ibm.com no longer holds. The wildcard operator, $*, matches all tokens and functions as a broader version type of the $+ operator. It will be used to check the domain portion of the address. The rule can be written as follows:

   R$+@$*@$-        $1@$3
Here, the $* operator assumes the $2 tag. The token internet is given the $3 tag.

In the preceding example, assume that only one token should be allowed in the user portion. So the value smm.ibm.bd will be ignored by the rule. To rewrite the form user@anydomain@internet to the form user@internet, the $- operator will be used. The rule may be written in either of the following manners:

   R$-@$*@$-        $1@$3
   R$-@$*@$-        $1@internet
If the requirement changed to rewriting any address of the form user@anydomain@anyroute to user@anyroute, only the first rule, R$-@$*@$- $1@$3, would accomplish this. The second rule handles only one specific route by setting RHS=@1@internet. If this rule were used and an address like me@hotmail.com@bitnet were encountered, the rule would cause the message to be incorrectly routed to internet, potentially losing the message.

Designing rules using LHS operators

In this section, four examples are used to illustrate the designing of rules. Before attempting any of these examples, make a backup copy of the /etc/sendmail.cf file.

Example 1

A new set, S33, will be defined. Before doing so, ensure the sendmail.cf file does not already have an S33 set defined. The original file in AIX does not have an S33 set. Edit the sendmail.cf file by inserting the following lines at the top of the file:
   S33
   R$+@dns1.bttb.net        $1@bttb.net

This rule set scans the user portion of an address with the $+ operator, that is, this portion may consist of one or more tokens. If the operator finds a match, the RHS will rewrite the dns1.bttb.net to simply bttb.net. Essentially, this rule removes the dns1 host name.

Now, save the sendmail.cf file and enter into address test mode with the following command:

   sendmail -bt -v -d
Here is what the flags indicate in AIX Version 4.2, sendmail Version 8.8.7: -bt test mode, -v verbose, -d debug. After entering the preceding command, a large listing will display before ending in a ">" test prompt. At the prompt, enter the following command:
   >33   smm@dns1.bttb.net
The output will be rewritten as smm@bttb.net. None of the rule set is invoked intially in sendmail 8.8.7. This command asks sendmail to put the address smm@dns1.bttb.net through rule set S33 only.

Now, at the prompt enter the following:

   >33 mushtaq@dns2.bttb.net
The output will remain unchanged, mushtaq@dns2.bttb.net, because the LHS is not satisfied. Since the rule requested absolute matching of dns1.bttb.net for the LHS, if this value is not matched, the address will remain unchanged rather than be rewritten.

Example 2

The purpose of the following rule is to remove dns1 from the host portion for a single token prefix at the @ token.
   S33
   R$-@dns1.bcc.net        $1@bcc.net
The following command will output smm@bcc.net.
   >33     smm@dns1.bcc.net
Now enter the following:
   >33     smm.test@dns1.bcc.net
The $- operator requests only one token for a match. Since there is more than one token in smm.test, the rule will not rewrite and the output should remain unchanged.

Example 3

The intent of the following rule is to rewrite addresses of the form anyhost.bdmail.net to the form bdmail.net. In other words, the host portion should be removed, leaving only the domain portion consisting of one or more tokens. A single-token user portion before the first @ symbol should be present as well.
   R$-@$*.bdmail.net        $1@bdmail.net
At the prompt, enter:
   >33      user@anyhost.bdmail.net
The output produced is user@bdmail.net.

Example 4

The following example illustrates how masquerading can be achieved with a rule, similar to masquerading with the DM macro. The purpose of this rule is to show a domain name in the outgoing mail that is different than the actual domain name. For instance, the actual domain name may be bdmail.net but you would like the world to see mail.org. To do this, create the following rule set:
   S33
   R$+@$*.bdmail.net        $1@mail.org
Now enter the following command:
   >33      susan@server1.bdmail.net
The output should be susan@mail.org. This rule has the same effect as the macro definition DMmail.org. It masks the actual domain name to mail.org.

The RHS operators

This section discusses a set of operators used on the RHS. A summary of the operators is listed below.
   RHS Operator	   Function
   ---------------------------------------------------
      $digit       Copy by position
      $:           Rewrite once
      $@           Rewrite once and return
      $>set        Rewrite through another rule set
      $#           Specification of delivery agent
      $[$]         Canonicalize host name
      $($)         Database file lookup
      ${$}         NIS map lookup for Sun/OS
   ---------------------------------------------------

The following examples illustrate the use of some of the more commonly used operators.

The $: operator
To illustrate the use of the $: operator as well as demonstrating how to avoid perpetual loops, the following example will be used.

   S33
   R$+@dns1.bdmail.net        $1@bdmail.net
Assume the workplace contains the value smm.test@dns1.bdmail.net. Recall that the LHS and the RHS are usually in a loop unless sendmail is explicitly instructed to stop. Below are the steps sendmail takes in carrying out the preceding rule.
  1. Attempts to match @dns1.bdmail.net tokens in the workspace.
  2. If a match is made, it then looks for a prefix token to match for the $+ operator. One or more tokens may be matched; in the example, the tokens are smm.test.
  3. If a match is made for $+, sendmail assigns a positional value of $1 to the tokens. So $1=smm.test.
  4. It then goes to the RHS and rewrites $1@bdmail.net. In this case, it is rewritten as smm.test@bdmail.net.
  5. It returns to the LHS with the new workspace value of smm.test@bdmail.net.
  6. Now, the LHS does not match for dns1.bdmail.net.
  7. The rule falls through and control is transferred to the next rule in the set or it returns from the set if there are no more rules.

Now, assume the rule is modified to the following:

   S33
   R$+@dns1.bdmail.net        $1@dns1.bdmail.net
If the address input is, for example, shaikh@dns1.bdmail.net, the rule enters into a perpetual loop. To avoid such occurrences, sendmail has a few mechanisms in place. One of these is the $: RHS operator. This operator tells sendmail to rewrite the RHS only once and return. So while the previous example creates a loop, the following does not:
   S33
   R$+@dns1.bdmail.net        $:$1@dns1.bdmail.net
Now, with the same address input, shaikh@dns1.bdmail.net, this rule rewrites the RHS only once to shaikh@dns1@bdmail.net and exits. That is, sendmail will either go on to execute the next rule or return if there are no more rules in the set.

The $@ operator
The $@ operator behaves similarly to the $: operator with a few extra features. This operator exits from the set as well as the rule. In effect, it is similar to the return or exit statement of a subroutine. Like any other programming language, it is required to control the flow.

The following sample rule rewrites the RHS if it is satisfied and exits Set 33.

   S33
   R$+@dns1.bdmail.net        $@$1@bdmail.net
If the input address is smm@dns1.bdmail.net, it will rewrite the address to smm@bdmail.net and then exit the rule as well as Set 33 if the LHS is satisfied. In the following rule, assume the input is smm@deltanet.bdmail.net.
   S33
   R$+@dns1.bdmail.net        $@$1@bdmail.net
   R$+@delta.bdmail.net       $@$1@uucpbd.net
   R$+@padma.bdmail.net       $@$!@bdtel.net
Here is what Set 33 will do.
  1. R$+@dns1.bdmail.net is not satisfied, so the rule does not execute the RHS. It goes to the next rule.
  2. R$+@deltanet.bdmail.net is satisfied, so the rule executes the RHS. It exits the rule and Set 33. The rewritten address is smm@uucpbd.net.
  3. R$+@padma.bdmail.net is not evaluated.
Let's look at an example that combines the $: and the $@ operators.
   S33
   R$+@dns1.bdmail.net        $:$1@bdmail.net
   R$+@www.bdmail.net         $@$1@bdmail.net
The first rule, if the LHS is true, will execute the RHS once and move to the next rule. If the LHS is true in the next rule, it will execute the RHS once and exit the set. If the LHS is not satisfied, it will go to the next set.

The $> operator
This operator does the work through a second rule set. Look at the following rule sets:

   S33
   R$+@dns1.bdmail.net        $>S34
   S34
   R$+@dns1.bdmail.net        $:$1@bdmail.net
Assume the input is:
   >33       smm@dns1.bdmail.net
The output would be smm@bdmail.net. For S33 , when the LHS is satisfied, it goes to the RHS. The RHS passes it to S34 with a default return. That is, S34 executes and, if it does not encounter a $@ operator, it evaluates all of the rules in the set. It rewrites those rules that are satisfied and then returns. If no rules are satisfied, it simply returns upon exhaustion of the rules. It does not continue through.

In effect, even though S34 is not specified or called in the input, it is evaluated for execution and result. This feature of the $> operator allows you to perform repetitive tasks or to make the code structured.


Return to the beginning of the document


sendmail Overview For the Advanced User: ITEM: FAX
Dated: 2000/08/14~00:00 Category: com
This HTML file was generated 2001/03/08~16:06:12
Comments or suggestions? Contact us