/usr/share/doc/courier-doc/htmldoc/modules.html is in courier-doc 0.68.2-1ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content=
"text/html; charset=utf-8" />
<meta name="MSSmartTagsPreventParsing" content="TRUE" />
<meta name="Author" content="Sam Varshavchik" />
<!-- Copyright 2000-2009 Double Precision, Inc. See COPYING for -->
<!-- distribution information. -->
<title>Transport Modules</title>
<link rel="icon" href="icon.gif" type="image/gif" />
</head>
<body>
<h2>Transport Modules</h2>The directory
<code>${COURIER_HOME}/lib/modules</code> contains shared
libraries and programs which provide input and output modules to
<em>Courier</em>. The actual module itself can actually be installed and
invoked anywhere else, the SMTP module, in fact, is installed in
bin. The shared library in lib, however, may include functions
which rewrite addresses for messages submitted from the input
module. All files for module named MODULE are stored in the
directory <code>${COURIER_HOME}/lib/modules/MODULE</code>.
<h3>The <code>modules.ctl</code> file</h3>The file
<code>${COURIER_HOME}/lib/modules/modules.ctl</code> contains a
list of all the modules that <em>Courier</em> loads.
<code>modules.ctl</code> is only used if <em>Courier</em> is compiled with
shared library support. If <em>Courier</em> is compiled with static
linkage only (by choice, or by necessity), all the module
libraries are statically linked into <em>Courier</em>, and
<code>modules.ctl</code> is not used. Each line in modules.ctl is
in the following form:
<em>priority</em><SP><i>name</i><SP><i>filename</i>,
where <code><SP></code> designates the space character. The
lines are sorted in increasing priority order! "priority" is
taken from the module's config file, and <em>filename</em> is the
filename of the shared library.
<h3>Contents of <code>${COURIER_HOME}/lib/modules/name</code>
directory</h3>The following files will be found in a module
subdirectory under lib. The name of the subdirectory is the name
field from the <code>modules.ctl</code> file.
<h4>config</h4>This is the module configuration file. Blank lines
in the config file are ignored, also lines that start with the #
character, which can be used for comments. The module
configuration is specified using the <code>NAME=VALUE</code>
notation, where <code>NAME</code> is the name of the
configuration parameter, and <code>VALUE</code> is its value.
<h4>librewrite</h4>This is the shared library that's loaded by
<code>submit</code> and <code>courierd</code>. The shared library
provides code to rewrite addresses to and from the canonical
format for messages to or from this module. If <em>Courier</em> is
compiled with static linkage, this file does not exist - the
library is statically linked.
<p>The actual name of the library may vary, and is specified in
the <code>config</code> file.</p>
<p>If this shared library does not exist, an attempt is made to
load <code>librewrite-old</code>. This allows an updated version
of the shared library to be installed in a live, running, system
by renaming the current one to <code>librewrite-old</code>, then
renaming the new one to <code>librewrite</code>.</p>
<p>Although submit will pick up new rewriting rules immediately,
<code>courierd</code> must be SIGHUPed in order to reload the new
shared library.</p>
<h4>Parameters in config</h4><code>NAME=name</code> - specifies
the name of this module. Should be the same as the directory
name.
<p><code>LIBRARY=filename</code> - specifies the name of the
shared library to load. Not used if <em>Courier</em> was compiled with
static libraries.</p>
<p><code>VERSION=version</code> - version of the module
interface. Not the actual version of the module, but version of
the interface between the module, and <em>Courier</em>. The current
version is version 0.</p>
<p><code>PRIORITY=n</code> - priority of the output module.
<em>Courier</em> calls all the modules' <code>rewritedel</code> functions
in the increasing priority order until it finds one which accepts
messages addressed to the recipient's address.</p>
<p><code>PROG=pathname</code> - pathname to the output module
program. Must be a full path, unless the module itself is in the
<code>lib/MODULE</code> directory. If the <code>PROG</code>
parameter is missing, this module is an input only module. If the
attempt to execute <code>PROG</code> fails, <em>Courier</em> will attempt
to execute <code>PROG-old</code>, which allows an updated output
module to be inserted into a live system by renaming the current
one <code>PROG-old</code>, then renaming the new output module as
<code>PROG</code>.</p>
<p><code>MAXDELS=n</code> - maximum concurrent deliveries for
this module. No more than these many instances of
<code>PROG</code> will be started at any given time.</p>
<p><code>MAXHOST=n</code> - maximum instances of
<code>PROG</code> that will be started with the same
<code>HOST</code> parameter.</p>
<p><code>MAXRCPT=n</code> - maximum number of addresses that will
be given to any single instance of <code>PROG</code>.</p>
<p>Please note that although these parameters are reread by
<code>courierd</code> when it restarts, the individual output
module may impose its own restrictions on the valid limits for
these parameters.</p>
<h3>Module library functions</h3>The module library contains the
following functions. In each case, <code>XXXX</code> is used to
represent the name of the function in the library for module
<code>XXXX</code>. For example, in the "local" module, the
<code>rw_install</code> function is called
<code>local_rw_install</code>.
<p><code>struct rw_list *XXXX_rw_install(const struct
rw_install_info *info);</code></p>
<p>The <code>rw_install()</code> function is called after the
shared library is open. It receives a pointer to the following
structure:</p>
<pre>
struct rw_install_info {
int rw_verlo;
int rw_verhi;
const char *courier_home;
} ;
</pre><code>rw_verlo/rw_verhi</code> - reserved for future
expansion. Currently set to 0. <code>rw_install</code> function of
modules compatible with this <em>Courier</em> interface must check that
<code>rw_verlo</code> is set to 0, and ignore
<code>rw_verhi</code>.
<p><code>courier_home</code> - <em>Courier</em>'s home directory, the
shared library can use this to find its files.</p>
<h3>The <code>rw_search</code> function</h3>
<pre>
struct rw_list *rw_search(const char *);
</pre>The <code>rw_search</code> function can be called by a
library function in order to return the rw_list (see below)
structure of a function in another library. <code>rw_search</code>
may NOT be called form <code>XXXX_rw_install</code>, because the
library containing this function may not've been installed yet.
<code>rw_search</code> may be called from the
<code>XXXX_rw_init</code> function.
<p><code>const char *XXXX_rw_init()</code></p>
<p>After all modules are installed, each module's
<code>rw_init()</code> function is called, which can complete any
additional setup. <code>rw_init</code> should return a null
pointer. Otherwise, <code>rw_init</code> should return the error
message text. <em>Courier</em> will refuse to start if
<code>rw_init</code> does not return a null pointer.</p>
<p>The library's <code>rw_install</code> function must return a
pointer to the following structure. If <code>rw_install</code>
returns a NULL pointer, <em>Courier</em> will refuse to start.</p>
<pre>
struct rw_list {
int rw_version;
void (*rewrite)(struct rw_info *info, void (*func)(struct rw_info *));
void (*rewrite_del)(struct rw_info *info, void (*func)(struct rw_info *),
void (*delfunc)(struct rw_info *info, const struct rfc822token *host,
const struct rfc822 *addr));
int (*filter_msg)(const char *,
int,
const char *,
const char *,
const char *,
char *,
unsigned);
} ;
</pre><code>rw_version</code> - shared libraries compatible with
this module interface must set rw_version to zero.
<p><code>rewrite</code> - this function is called to rewrite a
single address. The first argument points to the following
structure:<br />
</p>
<pre>
<code>struct rw_info {
int mode;
struct rfc822token *ptr;
void (*err_func)(int, const char *, struct rw_info *);
const struct rfc822token *sender;
const char *smodule;
void *udata;
} ;</code>
</pre><code>mode</code> contains the following values, ORed into a
bitmask: <code>RW_ENVSENDER</code> - rewrite envelope sender,
<code>RW_ENVRECIPIENT</code> - rewrite envelope recipient,
<code>RW_HEADER</code> - rewrite header. When calling
<code>rewrite()</code>, one of these three bits will be set.
Additional bits that may be set: <code>RW_OUTPUT</code> -
<code>rewrite</code>() should convert canonical format to the
transport format. If this bit is not set, rewrite should convert
from the transport format to the canonical format. In fact, the
main <code>courierd</code> does not call rewrite with the
<code>RW_OUTPUT</code> bit set, because that function is performed
by the dedicated output module, which may handle rewriting on its
own. Also, the <code>RW_SUBMIT</code> can be set together with
<code>RW_ENVSENDER</code> or <code>RW_ENVRECIPIENT</code>,
indicating that this call is as a result of a message being
submitted for delivery (as opposed to address verification for
<code>EXPN/VRFY</code> functionality).
<p>It is possible that none of those bits are set, when invoked
by another rewrite function.</p>
<p><code>ptr</code> is the address to rewrite, as rfc822
tokens.</p>
<p><code>udata</code> contains an arbitrary pointer, for usage by
rewrite's caller.</p>
<p>When mode has <code>RW_ENVRECIPIENT</code> set,
<code>sender</code> points to the envelope sender format in the
canonical format (previous result of <code>RW_ENVSENDER</code>),
otherwise this field is unused. If <code>sender</code> is NULL,
this should be interpreted as an empty envelope sender (or if
<code>rewrite</code> is being called in test mode.</p>
<p><code>smodule</code> is initialized when mode has the
<code>RW_SUBMIT</code> bit set. It will point to the name of the
module argument to submit - the module sending the message.</p>
<p><code>err_func</code> is the function to call in case of an
error.</p>
<p><code>rewrite</code> is expected to call either
<code>func</code>, (it's second argument), or
<code>err_func</code>, before returning. If rewriting succeeds,
<code>func</code> is called. If rewriting failed,
<code>rewrite</code> must call the <code>err_func</code> is
function. <code>errcode</code> will be the RFC822-style error
number, <code>errmsg</code> is the error message, which may be
multiline (includes newlines). The text in <code>errmsg</code> is
NOT prefixed by the error number.</p>
<p>After calling <code>func</code>, or <code>err_func</code>,
<code>rewrite</code> is expected to immediately terminate.
<code>rewrite</code> may alter the 'ptr' link list in any form or
fashion it wants, except that it may NOT malloc or free any node,
or a part thereof. However, it can relink portions of the link
list, or modify the link pointers to include tokens created by
<code>rewrite</code> internally.</p>
<p>After <code>func</code> or <code>err_func</code> terminates,
<code>rewrite</code> may deallocate everything it allocated, then
terminate itself.</p>
<p>This interface allows rewrite to execute very quickly, without
allocating or deallocating any memory. If new RFC822 tokens are
required, they can be allocated on the stack, and linked into the
original list.</p>
<p>The <code>rewrite_del</code> function is called to determine
if the module can accept delivery of a message to this address.
The <code>rewrite_del</code> of all installed libraries are
called until one of them calls the <code>delfunc</code> function.
If <code>rewrite_del</code> cannot accept delivery of a message,
it should call <code>func</code>. The <code>rewrite_del</code>
function should call the <code>delfunc</code> function to
indicate that this module can accept mail addressed to the
address specified by <code>info->ptr</code>.
<code>rewrite_del</code> receives the pointer to the rw_info
structure, then the <code>host</code> and the
<code>address</code> information for the output module, as
rfc822token lists. If the mode field has the
<code>RW_SUBMIT</code> bit set, rewrite_del can find the
message's envelope sender address in canonical format) in
<code>info->sender</code>.</p>
<p>Like <code>rewrite</code>, <code>rewrite_del</code> may make
arbitrary changes to <code>info->ptr</code>, except that it
may not deallocate memory used for the existing list.
<code>rewrite_del</code> may modify the link list, and allocate
memory for new rfc822 tokens. After calling either
<code>func</code> or <code>delfunc</code>,
<code>rewrite_del</code> should terminate immediately, and
deallocate any allocated memory. <code>rewrite_del</code> must
keep track of any allocated memory separate, and cannot assume
that <code>info->ptr</code> hasn't changed.</p>
<p>When <code>RW_SUBMIT</code> bit is set,
<code>rewrite_del</code> can be used to perform additional
recipient-specific code, which may be too expensive to run every
time courier goes through the queue. The <code>udata</code> field
contains a pointer to caller-specific data. The
<code>sender</code> field contains a pointer to the envelope
sender, in canonical format. Like <code>rewrite</code>,
<code>rewrite_del</code> may muck around with the
<code>rfc822token</code> list in <code>ptr</code>.
<code>rewrite_del</code> functions are called in order according
to the configured module priority. By setting a higher priority,
it is possible to have <code>rewrite_del</code> rewrite the
address so that it would be accepted by another module's
<code>rewrite_del</code>, down the chain.<br /></p>
<p>The last function, <code>rw_filter_msg</code>, is called to
run an arbitrary spam filter which can be used to selectively
reject messages. <code>rw_filter_msg</code> will be called after
<code>rewrite_del</code> accepted the message for delivery. The
arguments are as follows:</p>
<ul>
<li>The name of the module that is submitting this message for
delivery.</li>
<li>Either a read-only file descriptor, containing the copy of
the message, or -1.</li>
<li>The 'host' return value from <code>rewrite_del</code>, as a
text string.</li>
<li>The 'addr' return value from <code>rewrite_del</code>, as a
text string.</li>
<li>The message envelope return address.</li>
<li>A pointer to a buffer where the error message can be
saved.</li>
<li>How large the buffer is, in bytes.</li>
</ul>This function is called twice: once when submit receives the
recipient address (file descriptor is -1), and the second time
after the message is received, but before it is accepted.
Therefore, this function should execute quickly. Also note that
ESMTP does not have a well-defined way to selectively reject
messages to individual recipients once the contents of the
message are received. If a message is addressed to multiple
recipients, and at at least one recipient's filter rejects the
message, <em>Courier</em> replies with a rejection code, and the sending
mail server will assume that the message to all recipients has
failed.
<p><code>rw_filter_msg</code> should return 0 if the message is
acceptable, a negative value to permanently reject the message to
this recipient, and a positive value for a temporary
rejection.<br />
</p>
<h4>Running <code>PROG</code></h4><code>PROG</code> is the output
module that will be started by <em>Courier</em> when it comes up. PROG can
be a shell command, it is executed via "<code>$SHELL -c</code>".
It will be started under userid mail, group mail, in
<code>${COURIER_HOME}/lib/modules/NAME</code>. <em>Courier</em> will
communicate with <code>PROG</code> on standard input and output.
<p>If <code>PROG</code> succesfully initializes, it should fork,
and the parent should exit with status of 0. <em>Courier</em> waits until
<code>PROG</code> exits. If it exits with a non-0 exit code,
<em>Courier</em> will fail starting up. The child process will then
continue to read and write from standard output.</p>
<p><code>COURIER_HOME</code>, <code>MAXDELS</code>,
<code>MAXHOST</code>, and <code>MAXRCPTS</code> will be placed in
the environment, prior to executing <code>PROG</code>.</p>
<p>Tip: if the environment variables are not set,
<code>PROG</code> can presume that it's being run in test mode,
from the command line, and forego the fork.</p>
<p>If <code>PROG</code> terminates, <em>Courier</em> will consider it a
fatal error (<em>Courier</em> detects the input channel being closed).</p>
<p>If <code>PROG</code> gets an end-of-file indication, it can
assume that <em>Courier</em> is being shut down, so it should promptly
cease all activities, without waiting for pending messages to be
delivered.</p>
<p>To start delivery for a particular message, <code>PROG</code>
will receive a newline-terminated command, specifying the
message, and the recipients, and the delivery ID. Once
<code>PROG</code> finishes delivering messages, <code>PROG</code>
should write the results of the delivery into the message's
control file, then print the delivery ID on its standard output,
terminated by newline. If the module's config file
specifies that the module can handle multiple deliveries at the
same time, <code>PROG</code> may receive additional deliveries
before it finishes delivering the first message.</p>
<p>The command that prog receives is a newline-terminated line
that looks like this:</p>
<p>
msgnum<tab>sender<tab>delid<tab>host<tab>num1<tab>addr1<tab>num2<tab>addr2...</p>
<p><tab> represents the ASCII tab character. This is
basically a list of tab-separated fields. The first field is the
message id number (the inode number).</p>
<p>sender is the message envelope sender, after it's rewritten to
the module format, by the module shared library.</p>
<p>delid is the "delivery ID", which is a small integer,
representing this delivery. After <code>PROG</code> finishes
delivering the message, it should print the message's delivery ID
on standard output after saving the delivery status of each
recipient in the control file.</p>
<p>The host field specifies the host where the message should be
delivered to, as determined by the module's output rewrite rule.
Following the host, there will be one or more num/address pairs.
address is the recipient's address as determined by the output
rewrite rule, and num is the recipient's number in the message's
list of recipients (this is used to save the delivery status in
the control file). Note that the address can be an empty string,
so there will be two consecutive tabs there.<br />
</p>
</body>
</html>
|