This topic discusses the changes that can be made in conf.c.
Not all header semantics are defined in the configuration file. Header lines that should only be included by certain mailers (as well as other more obscure semantics) must be specified in the HdrInfo table in conf.c. This table contains the header name (which should be in all lower case) and a set of header control flags. The flags are:
Normally when the check is made to see if a header line is compatible with a mailer, sendmail(1M) will not delete an existing line. If this flag is set, then sendmail will delete even existing header lines. That is, if this bit is set and the mailer does not have flag bits set that intersect with the required mailer flags in the header definition in sendmail.cf, the header line is always deleted.
If this header field is set, treat it like a blank line, for example, it will signal the end of the header and the beginning of the message text.
Add this header entry even if one existed in the message before. If a header entry does not have this bit set, sendmail will not add another header line if a header line of this name already existed. This would normally be used to stamp the message by everyone who handled it.
If set, this is a timestamp (trace) field. If the number of trace fields in a message exceeds a preset amount the message is returned on the assumption that it has an aliasing loop.
If set, this field contains recipient addresses. This is used by the -t flag to determine who to send messages to when it is collecting recipients from the message.
This flag indicates that this field specifies a sender. The order of these fields in the HdrInfo table specifies the sendmail preference for which field to return error messages to.
Addresses in this header should receive error messages.
This header is a Content-Transfer-Encoding header.
This header is a Content-Type header.
Strip the value from the header (for Bcc:
).
struct hdrinfo HdrInfo[] = { /* originator fields, most to least significant */ "resent-sender", H_FROM, "resent-from", H_FROM, "sender", H_FROM, "from", H_FROM, "full-name", H_ACHECK, "errors-to", H_FROM|H_ERRORSTO, /* destination fields */ "to", H_RCPT, "resent-to", H_RCPT, "cc", H_RCPT, "bcc", H_RCPT|H_STRIPVAL, /* message identification and control */ "message", H_EOH, "text", H_EOH, /* trace fields */ "received", H_TRACE|H_FORCE, /* miscellaneous fields */ "content-transfer-encoding", H_CTE, "content-type", H_CTYPE,This structure indicates that theNULL, 0, };
To:
, Resent-To:
,
and Cc:
fields all specify recipient addresses. Any
Full-Name:
field will be deleted unless the required mailer
flag (indicated in the configuration file) is specified. The
Message:
and Text:
fields will terminate the
header; these are used by random dissenters around the network world.
The Received:
field will always be added, and can be used
to trace messages.
There are a number of important points here. First, header fields
are not added automatically just because they are in the
HdrInfo structure; they must be specified in the
configuration file in order to be added to the message. Any header
fields mentioned in the configuration file but not mentioned in the
HdrInfo structure have default processing performed;
that is, they are added unless they were in the message already.
Second, the HdrInfo structure only specifies cliched
processing; certain headers are processed specially by ad hoc code
regardless of the status specified in HdrInfo. For
example, the Sender:
and From:
fields are
always scanned on ARPANET mail to determine the sender;
this is used to perform the ``return to sender'' function. The
From:
and Full-Name:
fields are used to
determine the full name of the sender if possible; this is stored
in the macro $x.
If it is necessary to restrict mail through a relay, the checkcompat routine can be modified. This routine is called for every recipient address. It returns an exit status indicating the status of the message. The status EX_OK accepts the address, EX_TEMPFAIL queues the message for a later try, and other values (commonly EX_UNAVAILABLE) reject the message. It is up to checkcompat to print an error message (using usrerr) if the message is rejected. For example, checkcompat could read:
int checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { register STAB *s;This would reject messages greater than 50000 bytes unless they were local. The EF_NORETURN flag can be set ins = stab("private", ST_MAILER, ST_FIND); if (s != NULL && e->e_from.q_mailer != LocalMailer && to->q_mailer == s->s_mailer) { usrerr("No private net mail allowed through this machine"); return (EX_UNAVAILABLE); } if (MsgSize > 50000 && bitnset(M_LOCALMAILER, to->q_mailer)) { usrerr("Message too large for non-local delivery"); e->e_flags |= EF_NORETURN; return (EX_UNAVAILABLE); } return (EX_OK); }
e->e_flags
to suppress the return of the actual body
of the message in the error return. The actual use of this routine
is highly dependent on the implementation, and use should be limited.
The routine getla should return an approximation of the current system load average as an integer. There are several versions of the load average computation system. See the description of the LA_TYPE option in ``Parameters in src/conf.h''.
New key maps can be added by creating a class initialization function and a lookup function. These are then added to the routine setupmaps.
The initialization function is called as
xxx_map_init(MAP *map, char *mapname, char *args)The map is an internal data structure. The mapname is the name of the map (used for error messages). The args is a pointer to the rest of the configuration file line; flags and filenames can be extracted from this line. The initialization function must return TRUE if it successfully opened the map, FALSE otherwise.
The lookup function is called as
xxx_map_lookup(MAP *map, char buf[], int bufsize, char **av, int *statp)The map defines the map internally. The parameters buf and bufsize have the input key. This may be (and often is) used destructively. The av is a list of arguments passed in from the rewrite line. The lookup function should return a pointer to the new value. If the map lookup fails, *statp should be set to an exit status code; in particular, it should be set to EX_TEMPFAIL if recovery is to be attempted by the higher level code.
The routine shouldqueue is called to decide if a message should be queued or processed immediately. Typically this compares the message priority to the current load average. The default definition is:
bool shouldqueue(pri, ctime) long pri; time_t ctime; { if (CurrentLA < QueueLA) return (FALSE); return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); }If the current load average (global variable CurrentLA, which is set before this function is called) is less than the low threshold load average (option x, variable QueueLA), shouldqueue returns FALSE immediately (that is, it should not queue). If the current load average exceeds the high threshold load average (option X, variable RefuseLA), shouldqueue returns TRUE immediately. Otherwise, it computes the function based on the message priority, the queue factor (option q, global variable QueueFactor), and the current and threshold load averages.
An implementation wishing to take the actual age of the message into account can also use the ctime parameter, which is the time that the message was first submitted to sendmail(1M). Note that the pri parameter is already weighted by the number of times the message has been tried (although this tends to lower the priority of the message with time); the expectation is that the ctime would be used as an escape clause to ensure that messages are eventually processed.
The function refuseconnections returns TRUE if incoming SMTP connections should be refused. The current implementation is based exclusively on the current load average and the refuse load average option (option X, global variable RefuseLA):
bool refuseconnections() { return (RefuseLA > 0 && CurrentLA >= RefuseLA); }