D.1 How checkcompat( ) Works
When sendmail prepares to deliver mail, it first
checks the size of the mail message and rejects (bounces) it if it is
larger than the limit imposed by the M= delivery
agent equate (see M=). V8.8 and above
sendmail then call the
check_compat rule set (see Section 7.1.4). After that, all versions of
sendmail call the
checkcompat( ) routine.
The checkcompat( ) routine lies in a unique
position within the sendmail code. It is the one
place where both the sender and already aliased recipient addresses
are available at the same time. Because it is invoked immediately
before actual delivery, all the information needed for delivery is
available to you for checking.
If checkcompat( ) returns EX_OK, as defined in
<sysexits.h>, the mail message is
considered OK and delivered. Otherwise the message is bounced. If you
wish the message to be requeued instead of bounced, you can return
EX_TEMPFAIL.
Again note that the checkcompat( ) routine is
called once for each already aliased recipient.
D.1.1 Arguments Passed to checkcompat( )
The checkcompat( ) is found in the C-language
source file sendmail/conf.c. Inside that file
you will find it declared like this:
checkcompat(to, e)
register ADDRESS *to;
register ENVELOPE *e;
Here, to is a pointer to a structure of
typedef ADDRESS which contains information about
the recipient. And e is a pointer to a structure
of typedef ENVELOPE which contains information
about the current envelope. (Actually, both are linked lists of
structures.)
The members of the ADDRESS *to structure are shown
in Table D-1. Note that these members are correct
for V8.12 sendmail only. Also note that the
table shows only those members that can be useful in a
checkcompat( ) routine (see
sendmail.h for the other members of
*to).
Table D-1. ADDRESS *to members
struct address *
|
q_alias
|
The alias that yielded this address
|
char *
|
q_finalrcpt
|
This is a Final-Recipient: DSN header
|
unsigned long
|
q_flags
|
Address flags (see Table 16-3)
|
char *
|
q_fullname
|
The (GECOS) full name of q_ruser, if known
|
gid_t
|
q_gid
|
The gid of the q_ruser, if
known
|
char *
|
q_home
|
The home directory (path), if F=w delivery-agent
flag is set
|
char *
|
q_host
|
The host part ($@) from rule set 0 (seeSection 19.5)
|
struct mailer *
|
q_mailer
|
The delivery agent ($#) from rule set 0 (see Section 19.5)
|
char *
|
q_message
|
Message regarding address (not always an error)
|
struct address *
|
q_next
|
Link to the next ADDRESS in the chain
|
char *
|
q_orcpt
|
The ORCPT parameter from RCPT TO: line was set
|
char *
|
q_owner
|
The owner of q_alias
|
char *
|
q_paddr
|
The address in a form suitable for printing
|
int
|
q_qdir
|
Queue directory inside group
|
int
|
q_qgrp
|
Index into queue groups
|
char *
|
q_ruser
|
The login name for this user, if known
|
time_t
|
q_statdate
|
The date of the status change
|
short
|
q_state
|
The state of the address
|
char *
|
q_statmta
|
Which MTA generated q_rstatus
|
uid_t
|
q_uid
|
The uid of the q_ruser, if
known
|
char *
|
q_user
|
The user part ($:) from rule set 0 (seeSection 19.5)
|
The members of the ENVELOPE *e structure are shown
in Table D-2. Note that these members are correct
for V8.12 sendmail only. Also note that the
table shows only those members that can be useful in a
checkcompat( ) routine (see
sendmail.h for other members of
*e).
Table D-2. ENVELOPE *e members
char *
|
e_auth_param
|
The parameters set by AUTH=
|
char *
|
e_bodytype
|
The type of message body
|
short
|
e_class
|
The message class (priority,
junk, etc.)
|
time_t
|
e_ctime
|
The time this message was accepted
|
long
|
e_deliver_by
|
The DELIVERYBY BY= interval
|
int
|
e_dlvr_flag
|
The DELIVERYBY BY= flags
|
SM_FILE_T *
|
e_dfp
|
The datafile
|
int
|
e_dfqgrp
|
The datafile's queue group index
|
int
|
e_dfqdir
|
The datafile's queue directory index
|
time_t
|
e_dtime
|
The time of the last delivery attempt
|
char *
|
e_envid
|
Envelope ID from MAIL FROM:
|
short
|
e_errormode
|
The error return mode
|
ADDRESS *
|
e_errorqueue
|
The queue for error responses
|
unsigned long
|
e_flags
|
Envelope flags (see Table 16-6)
|
ADDRESS
|
e_from
|
The sender address structure
|
char **
|
e_fromdomain
|
The domain part of the sender
|
HDR *
|
e_header
|
Linked list of headers
|
short
|
e_hopcount
|
The hop count for the message
|
char *
|
e_id
|
The ID for this entry
|
char *
|
e_message
|
The error message
|
char *
|
e_msgid
|
The message ID (for logging)
|
long
|
e_msgpriority
|
The adjusted priority of this message
|
long
|
e_msgsize
|
The size of the message in bytes
|
int
|
e_nrcpts
|
The number of recipients
|
int
|
e_ntries
|
The number of delivery attempts
|
int
|
e_qgrp
|
The queue group (index into queues)
|
int
|
e_qdir
|
The index into queue directories
|
char *
|
e_sender
|
Sender address with comments stripped
|
ADDRESS *
|
e_sendqueue
|
Linked list of recipients
|
char *
|
e_statmsg
|
The status message (changes per delivery)
|
char *
|
e_status
|
The DSN status for this message
|
short
|
e_timeoutclass
|
The message timeout class
|
The checkcompat( ) routine is a powerful
internal hook inside sendmail. It is so internal
and powerful, in fact, that if you are truly clever you can even use
checkcompat( ) to modify rewrite rules at
runtime (scary, but possible).
D.1.2 Global Variables
V8.8 sendmail
uses more than 100 variables. They are all listed in
sendmail.h and conf.c with
"lite" comments. Global variables
store information such as
sendmail's option values, file
descriptor values, macro values, class lists, and database access
information. Any can be modified inside
checkcompat, but before attempting to do so,
study the sendmail C source code to anticipate
any unexpected side effects.
In general you can use almost any of the global variables when
designing your own checkcompat( ) routine. The
four most interesting are:
- RealHostAddr
-
The IP address of the sending host. This is a union of several
sockaddr_ types depending on your selection of
protocol types. This can be zero for locally submitted mail.
- RealHostName
-
A string containing the definitive canonical name of the sending
host. If it can't be resolved to a name, it will
contain the host's IP number in text form,
surrounded by square brackets.
- LogLevel
-
This variable determines the amount of logging that
sendmail does, and is set using the
LogLevel option (LogLevel).
You can use this LogLevel variable to decide how
much, if anything, you wish to log about what you are doing inside
the checkcompat( ) function.
- CurrentLA
-
An integer representation of the current load average. You might want
to use checkcompat( ) to defer mail between
selected senders and recipients when the load is very high.
- Verbose
-
An integer that, if it is nonzero, means that you can allow
checkcompat( ) to show (print to the standard
output) what it is doing.
|