21.6 Macro Conditionals: $?, $|, and $.

Occasionally, it is necessary to test a sendmail macro to see whether a value has been assigned to it. To perform such a test, a special prefix and two operators are used. The general form is:

    if       else      endif  
    $?x text1 $| text2 $.
if x is defined    if x is not defined 

This expression yields one of two possible values: text1 if the macro named x has a value, text2 if it doesn't. The entire expression, starting with the $? and ending with the $., yields a single value, which can contain multiple tokens.

The following, for example, includes the configuration-file version in the SMTP greeting message but does so only if that version (in $Z; see $Z) is defined:

O SmtpGreetingMessage=$j Sendmail ($v/$?Z$Z$|generic$. ) ready at $b

Here, the parenthetical version information is expressed one way if $Z has a value (such as 1.4):


but is expressed differently if $Z lacks a value:


The else part ($|) of this conditional expression is optional. If it is omitted, the result is the same as if the text2 were omitted:


Both of the preceding yield the same result. If x has a value, text1 becomes the value of the entire expression. If x lacks a value, the entire expression lacks a value (produces no tokens).

Note that it is not advisable to use the $? conditional expression in rules. Such a use can have other than the intended effect because macro conditionals are expanded when the configuration file is read.

21.6.1 Conditionals Can Nest

V8 sendmail allows conditionals to nest. To illustrate, consider the following expression:

$?x $?y both $| xonly $. $| $?y yonly $| none $. $.

This is just like the example in the previous section:

$?x text1 $| text2 $.

except that text1 and text2 are both conditionals:

text1 = $?y both $| xonly $.
text2 = $?y yonly $| none $.

The grouping when conditionals nest is from the outside in. In the following example, parentheses have been inserted to show the groupings (they are not a part of either expression):

($?x  (text1)  $|  (text2)  $. )  
($?x  ($?y  both $| xonly $. )  $|  ($?y  yonly $| none $. )  $. )  

Interpretation is from left to right. The logic of the second line is therefore this: if both $x and $y have values, the result is both. If $x has a value but $y lacks one, the result is xonly. If $x lacks a value but $y has one, the result is yonly. And if both lack values, the result is none.

The sendmail program does not enforce or check for balance in nested conditionals. Each $? should have a corresponding $. to balance it. If they do not balance, sendmail will not detect the problem. Instead, it might interpret the expression in a way that you did not intend.

The depth to which conditionals can be nested is limited only by our ability to easily comprehend the result. More than two deep is not recommended, and more than three deep is vigorously discouraged.

21.6.2 Macro Translations

Some macros are assigned values from text that is supplied by outside connecting hosts. Such text cannot necessarily be trusted in rule sets, or as keys in database-map lookups.

To protect itself, sendmail modifies such text by translating whitespace characters (spaces and tabs), nonprinting characters (such as newlines and control characters), and the following list of special characters:

< > ( ) " +

Translation is the replacement of each special character with its corresponding hexadecimal value (based on U.S. ASCII), where each new hexadecimal value is prefixed with a plus character.[10] For example:

[10] This is also called xtext translation and is documented in RFC1891.

(some text)      becomes     +28some+20text+29

Only four macros are subject to this encoding at this time. They are listed in Table 21-4.

Table 21-4. Macros subject to xtext encoding






Distinguished name of certificate signer



Distinguished name of certificate (owner)



Common name of certificate signer



Common name of certificate

    Part I: Build and Install
    Part II: Administration
    Part III: The Configuration File
    Chapter 21. The D (Define a Macro) Configuration Command
    Chapter 24. The O (Options) Configuration Command