/usr/share/doc/amavisd-new/README.postfix.html is in amavisd-new 1:2.7.1-2ubuntu3.
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 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 | <html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Integrating amavisd-new in Postfix</title><link rel="stylesheet" href="screen.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.71.1"><meta name="keywords" content="amavisd, amavisd-new, amavisd-new Postfix, configuring amavisd-new Postfix, amavisd-new Postfix configuration, amavisd-new Postfix HOWTO"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="README.postfix"></a>Integrating amavisd-new in Postfix</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Patrick</span> <span class="othername">Ben</span> <span class="surname">Koetter</span></h3><code class="email"><<a href="mailto:patrick.koetter@state-of-mind.de">patrick.koetter@state-of-mind.de</a>></code></div><div class="author"><h3 class="author"><span class="firstname">Mark</span> <span class="surname">Martinec</span></h3><code class="email"><<a href="mailto:Mark.Martinec+amavis@ijs.si">Mark.Martinec+amavis@ijs.si</a>></code></div></div></div><div><div class="legalnotice"><a name="d0e42"></a><p>License: GNU GENERAL PUBLIC LICENSE, Version 2, June 1991</p></div></div><div><div class="revhistory"><table border="1" width="100%" summary="Revision history"><tr><th align="left" valign="top" colspan="3"><b>Revision History</b></th></tr><tr><td align="left">Revision 141</td><td align="left">11. Mar 2008</td><td align="left">PK</td></tr><tr><td align="left" colspan="3">Updated parameters that override Postfix defaults for the
amavisdfeed and the reentry smtpd servers</td></tr><tr><td align="left">Revision 139</td><td align="left">11. Mar 2008</td><td align="left">PK</td></tr><tr><td align="left" colspan="3">Added corrections sent in from Chris Pepper</td></tr><tr><td align="left">Revision 122</td><td align="left">15. Jun 2007</td><td align="left">PK</td></tr><tr><td align="left" colspan="3">Added Section on Advanced Configuration</td></tr><tr><td align="left">Revision 108</td><td align="left">22. Apr 2007</td><td align="left">PK</td></tr><tr><td align="left" colspan="3">Initial publication</td></tr></table></div></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#requirements">1. Requirements</a></span></dt><dd><dl><dt><span class="section"><a href="#requirements_postfix_version">1.1. Which Postfix version is required?</a></span></dt><dt><span class="section"><a href="#requirements_catching_errors">1.2. Catching errors during integration</a></span></dt></dl></dd><dt><span class="section"><a href="#basics">2. Basic Postfix and amavisd-new configuration</a></span></dt><dd><dl><dt><span class="section"><a href="#basics_amavisd-new">2.1. Configuring amavisd-new for Postfix</a></span></dt><dt><span class="section"><a href="#basics_transport">2.2. Configuring the transport from Postfix to amavisd-new</a></span></dt><dt><span class="section"><a href="#basics_smtpd-daemon">2.3. Configuring a dedicated SMTP-server for message
reinjection</a></span></dt><dt><span class="section"><a href="#basics_testing">2.4. Testing basic configuration</a></span></dt></dl></dd><dt><span class="section"><a href="#filter">3. Message filtering examples</a></span></dt><dd><dl><dt><span class="section"><a href="#filter_global">3.1. Filtering E-mail globally</a></span></dt><dt><span class="section"><a href="#filter_service_global">3.2. Filtering E-mail by Postfix service</a></span></dt><dt><span class="section"><a href="#filter_by_recipient">3.3. Filtering E-Mails per Recipient Domain</a></span></dt><dt><span class="section"><a href="#filter_by_sender">3.4. Filtering E-Mails by Sender-Domain</a></span></dt><dt><span class="section"><a href="#filter_by_content">3.5. Filtering E-mail per Content</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e974">4. Advanced Postfix and amavisd-new configuration</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e1044">4.1. Multiple cleanup service architecture</a></span></dt><dt><span class="section"><a href="#d0e1116">4.2. Configuring two cleanup services</a></span></dt></dl></dd><dt><span class="section"><a href="#tuning">5. Tuning</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e1237">5.1. Maximum Number of Concurrent Processes</a></span></dt><dt><span class="section"><a href="#d0e1294">5.2. Additional Tips for Tuning</a></span></dt></dl></dd></dl></div><div class="abstract"><p class="title"><b>Abstract</b></p><p>This document describes how amavisd-new can be integrated into the
Postfix SMTP delivery process. It lists the necessary requirements,
explains how Postfix and amavisd-new need to be configured to basically
work together and it gives filter-examples to show how amavisd-new can be
called from Postfix.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="requirements"></a>1. Requirements</h2></div></div></div><p>The following requirements must be met before integration can
begin:</p><div class="orderedlist"><ol type="1"><li><p>amavisd-new has already been installed and successfully
tested.</p></li><li><p>Postfix has been installed, configured for basic operations and
tested successfully.</p></li></ol></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Independently of the configuration examples shown in this
document, it is advisable to set
<em class="parameter"><code>strict_rfc821_envelopes</code></em> = <code class="option">yes</code> in
<code class="filename">/etc/postfix/main.cf</code>. Postfix will reject any
message from envelope-senders, whose address can't be used to send a
reply to.</p><p>This avoids accepting e-mails from erroneous envelope-senders that
can't be informed of problems, which finally would result in deleting
the message - even if Postfix claimed successful delivery in the
first.</p></td></tr></table></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="requirements_postfix_version"></a>1.1. Which Postfix version is required?</h3></div></div></div><p>Integrating amavisd-new into the Postfix delivery process requires
that Postfix is able to delegate messages to external content filters.
The minimum version that provides content filtering is Postfix
release-20010228.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="requirements_catching_errors"></a>1.2. Catching errors during integration</h3></div></div></div><p>Chances are that configuration errors during implementation cause
Postfix to bounce legitimate messages. Setting the
<em class="parameter"><code>soft_bounce</code></em> parameter during integration and
reloading the Postfix configuration afterwards prevents Postfix from
bouncing legitimate mail during that time:</p><pre class="programlisting"># <strong class="userinput"><code>postconf -e "soft_bounce = yes"</code></strong>
# <strong class="userinput"><code>postfix reload</code></strong></pre><p>As soon as <em class="parameter"><code>soft_bounce</code></em> has been activated
Postfix will treat all delivery errors as temporary errors - any client
that wants to send messages to Postfix will keep mail in the mailqueue
and it will suspend delivery until the
<em class="parameter"><code>soft_bounce</code></em> parameter has been removed or set to
<code class="option">no</code>.</p><p>Once the integration of amavisd-new into the Postfix delivery
process has been completed successfully
<em class="parameter"><code>soft_bounce</code></em> must be removed or Postfix will not
generate bounce messages for legitimate mail.</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="basics"></a>2. Basic Postfix and amavisd-new configuration</h2></div></div></div><p>There are several moments at which Postfix can hand messages over to
amavisd-new (before it accepts a message from a client or after) and there
are different filter approaches (globally, per recipient (domain), per
network interface, etc.) that can trigger Postfix to transport a message
to amavisd-new.</p><p>The transport methods - transporting a message from Postfix to
amavisd-new and back - however always remain the same. They will be
described in this section first. The section that follows will deal with
different filtering approaches.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip: Integration procedure"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Integration procedure</th></tr><tr><td align="left" valign="top"><p>The following examples have been structured to cause minimum
trouble on an online mail system. The order of steps ensures that
filtering will be enabled at the very last moment. Several tests will
have been conducted to verify the delivery chain works before the filter
is enabled. Once enabled the complete system should work at once.</p></td></tr></table></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="basics_amavisd-new"></a>2.1. Configuring amavisd-new for Postfix</h3></div></div></div><p>Configuring amavisd-new to work with Postfix answers the following
two questions:</p><div class="orderedlist"><ol type="1"><li><p>Which port should the amavisd-new daemon listen to for
incoming connections from Postfix?</p></li><li><p>Which IP-address and port should the amavisd-new SMTP client
use to (re)inject filtered messages (and notifications about message
status) into the Postfix SMTP delivery system?</p></li></ol></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e175"></a>2.1.1. Configuring amavisd-new for incoming connections</h4></div></div></div><p>The <em class="parameter"><code>$inet_socket_port</code></em> parameter in
<code class="filename">/etc/amavisd.conf</code> sets the port number where
amavisd-new will listen for incoming (E)SMTP connections. The
following example explicitly configures amavisd-new to bind to port
<code class="systemitem">10024</code> (default setting
<code class="option">undef</code>):</p><pre class="programlisting">$inet_socket_port = 10024;</pre></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e194"></a>2.1.2. Configuring the reinjection path</h4></div></div></div><p>Two parameters, <em class="parameter"><code>$forward_method</code></em> and
<em class="parameter"><code>$notify_method</code></em>, need to be configured (usually
identically) to reinject messages into the Postfix mail system.</p><p>The first parameter, <em class="parameter"><code>$forward_method</code></em>,
specifies where amavisd-new should transport scanned messages to,
while the second parameter, <em class="parameter"><code>$notify_method</code></em>,
specifies where notifications about scanned messages should be
transported to.</p><p>By default amavisd uses <code class="systemitem">127.0.0.1</code> on port <code class="systemitem">10025</code> to contact a SMTP server for
reinjection of filtered messages. Unless a different IP address or
port should be used, no modifications must be applied and this section
can be skipped.</p><p>In case a different IP address or port should be used, the
parameters <em class="parameter"><code>$notify_method</code></em> and
<em class="parameter"><code>$forward_method</code></em> need to be adjusted to reflect
these requirements. The following example edits these parameters in
<code class="filename">/etc/amavisd.conf</code> and uses <code class="systemitem">192.0.2.1</code> as IP address and port
<code class="systemitem">20025</code>:</p><pre class="programlisting">$notify_method = 'smtp:[192.0.2.1]:20025';
$forward_method = 'smtp:[192.0.2.1]:20025';</pre></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="basics_transport"></a>2.2. Configuring the transport from Postfix to amavisd-new</h3></div></div></div><p>Both amavisd-new and Postfix are able to use either SMTP- or
LMTP-communication to transport a message from Postfix to amavisd-new.
Both variants will be described in this section.</p><h4><a name="d0e245"></a>Why configure a dedicated service?</h4><p>Theoretically it's possible to transport messages from Postfix to
amavisd-new using the existing smtp-, lmtp, or even the relay-service in
<code class="filename">/etc/postfix/master.cf</code>.</p><p>In practice transporting messages to amavisd-new requires imposing
transport limits on the transporting service. Imposing such limits on a
globally available service would impose these limits on the complete
Postfix mail system - it would slow down the system significantly and
should be avoided.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The number of Postfix clients that may connect simultaneously to
amavisd-new instances must be limited to the maximum number of daemon
child processes amavisd-new starts.</p><p>If the Postfix transport client was allowed to open more
connections than amavisd-new can handle, amavisd-new would start to
queue incoming Postfix connections. Postfix in turn would interpret
such behaviour as “<span class="quote">unresponsive remote MTA</span>” and would
itself begin to queue mail that should be filtered. All this would
possibly throttle down the complete system and all further filtering
attempts would suffer.</p></td></tr></table></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="basics_transport_lmtp-client"></a>2.2.1. Configuring a dedicated lmtp-client</h4></div></div></div><p>The following example creates a new, dedicated lmtp-transport
named <code class="systemitem">amavisfeed</code> in
<code class="filename">/etc/postfix/master.cf</code>. Its configuration details
are explained following the listing:</p><pre class="programlisting"># ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
...
amavisfeed unix - - n - 2 lmtp
-o lmtp_data_done_timeout=1200
-o lmtp_send_xforward_command=yes
-o lmtp_tls_note_starttls_offer=no</pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>A noteworthy quote from the Postfix documentation:
“<span class="quote">...do not specify whitespace around the ‘<span class="quote">=</span>’. In
parameter values, either avoid whitespace altogether, ...</span>”.
Further details on <code class="filename">master.cf</code> configuration
syntax can be found in <code class="filename">master.cf</code> or
<span class="citerefentry"><span class="refentrytitle">master</span>(5)</span>.</p></td></tr></table></div><p>Here's a quick rundown on the settings that differ from other
services defaults:</p><div class="variablelist"><dl><dt><span class="term"><em class="parameter"><code>maxproc</code></em></span></dt><dd><p>The maximum number of concurrent Postfix amavis-service
processes has been limited to <code class="option">2</code> (default:
<em class="parameter"><code>default_process_limit</code></em> =
<code class="option">100</code>). This value reflects the default of
<code class="option">2</code> amavisd-daemon children processes and is a
good setting to start from. The value may be raised later, when
the system works stable and still can take a higher load. It
should not exceed the number of simultaneous amavisd child
processes.</p></dd><dt><span class="term"><em class="parameter"><code>lmtp_data_done_timeout</code></em></span></dt><dd><p>Setting <em class="parameter"><code>lmtp_data_done_timeout</code></em> to
<code class="option">1200</code> (seconds) doubles the default time span a
regular Postfix client waits after message delivery for the
server to reply <code class="computeroutput">DONE</code> to claim
successful delivery. It must be larger than amavisd setting
<em class="parameter"><code>$child_timeout</code></em> (default
<code class="option">8</code>*<code class="option">60</code> seconds) and should add a
sufficient safety margin, for example to cater for periods of
automatic database maintenance (e.g. bayes database on non-SQL
database types) which can take a long time in some cases.</p><p>If the server does not reply within the configured time
span, the Postfix client will quit the connection, put the
message into the deferred queue, log a delivery failure and
retry later to transport the message to amavisd-new.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Raising this value serves a trick amavisd uses to avoid
message loss in case of power outage etc. The trick consists
in keeping the incoming connection as long open as it takes to
filter the message and take appropriate action (reinjection,
notification, quarantine, etc.).</p><p>Only when the message (or notifications etc.) has been
reinjected amavisd will send
<code class="computeroutput">DONE</code> to the client and the
client will close the connection. This way Postfix will always
keep the message in its own mail queue, where it can be
reactivated after a system failure.</p></td></tr></table></div></dd><dt><span class="term"><em class="parameter"><code>lmtp_send_xforward_command</code></em></span></dt><dd><p>Enabling <em class="parameter"><code>lmtp_send_xforward_command</code></em>
configures the Postfix lmtp-client to forward the original
clients HELO name and IP address to amavisd-new. amavisd-new in
turn can use this information for</p><div class="itemizedlist"><ul><li><p>logging and notifications (macro
<code class="varname">%a</code>)</p></li><li><p>switching policy banks (<code class="constant">MYNETS</code>,
<em class="parameter"><code>@mynetworks_maps</code></em>)</p></li><li><p>pen pals functionality</p></li><li><p>p0f fingerprinting</p></li></ul></div></dd><dt><span class="term"><em class="parameter"><code>lmtp_tls_note_starttls_offer</code></em></span></dt><dd><p>Starting with version 2.6 amavisd-new can offer TLS to a
<code class="systemitem">smtp</code>- or
<code class="systemitem">lmtp</code>-client. This option cuts down
unnecessary logging by Postfix, just in case logging TLS session
offers has been enabled globally setting <em class="parameter"><code>
lmtp_tls_note_starttls_offer</code></em> in Postfix
<code class="filename">main.cf</code> configuration file.</p></dd></dl></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="basics_transport_smtp-client"></a>2.2.2. Configuring a dedicated smtp-client</h4></div></div></div><p>Configuring a dedicated smtp-client is almost identical to
configuring a dedicated lmtp-client. The syntax differences in detail
are that the names of parameters start with
<em class="parameter"><code>smtp_</code></em> instead of <em class="parameter"><code>lmtp_</code></em>
and that the command at the end of the service invokes the smtp- and
not lmtp-client. The same reasons given for differing lmtp client
options apply to the dedicated smtp client configuration.</p><p>Here's an example of a dedicated smtp client given the service
name <em class="parameter"><code>amavisfeed</code></em>:</p><pre class="programlisting"># ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
...
amavisfeed unix - - n - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o smtp_tls_note_starttls_offer=no</pre></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="basics_smtpd-daemon"></a>2.3. Configuring a dedicated SMTP-server for message
reinjection</h3></div></div></div><p>The second service that needs to be added to the Postfix mail
system is a dedicated SMTP-server. It will exist only to accept filtered
messages and notifications from amavisd-new to transported them closer
to their final destination.</p><p>This dedicated smtpd server will differ in many aspects from the
default smtpd daemon. The most important difference is that it
configures an empty <em class="parameter"><code>content_filter</code></em> parameter,
thus overriding any global external content filtering settings in
Postfix.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Delegating messages to an external content filter in Postfix is
done using the <em class="parameter"><code>content_filter</code></em> parameter. If the
dedicated smtpd-daemon would not override any global
<em class="parameter"><code>content_filter</code></em> settings, the reinjected message
would be sent of to the external content filter again - the mail would
end in an endless loop.</p></td></tr></table></div><p>The following Postfix example uses amavisd-new default settings
taken from the <em class="parameter"><code>$forward_method</code></em> and
<em class="parameter"><code>$notify_method</code></em> parameters. These settings
configure amavisd-new to forward filtered messages and notifications to
<code class="systemitem">127.0.0.1</code> on port <code class="systemitem">10025</code>; the Postfix smtpd daemon will be
configured to bind to that IP address and listen on the specified port
for incoming connections:</p><pre class="programlisting"># ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
...
127.0.0.1:10025 inet n - n - - smtpd
-o content_filter=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o smtpd_restriction_classes=
-o mynetworks=127.0.0.0/8
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
-o local_header_rewrite_clients=
-o smtpd_milters=
-o local_recipient_maps=
-o relay_recipient_maps=</pre><p>Here's a quick rundown on the settings that differ from smtpd
defaults:</p><div class="variablelist"><dl><dt><span class="term"><em class="parameter"><code>content_filter</code></em></span></dt><dd><p>The empty <em class="parameter"><code>content_filter</code></em> overrides
other, globally set <em class="parameter"><code>content_filter</code></em>
delegations.</p></dd><dt><span class="term"><em class="parameter"><code>..._maps</code></em></span></dt><dd><p>Empty <em class="parameter"><code>..._maps</code></em> override any other
globally set map lookups. Procedures to enforce settings specified
in such maps have already taken place when Postfix accepted the
message from the external client. Doing them again will not
produce new results but only waste resources.</p></dd><dt><span class="term"><em class="parameter"><code>..._restrictions_...</code></em></span></dt><dd><p>There's no need to apply any already enforced
<em class="parameter"><code>..._restrictions_...</code></em> another time. It would
also only waste resources.</p></dd><dt><span class="term"><em class="parameter"><code>mynetworks</code></em></span></dt><dd><p>To avoid abuse from remote hosts, the dedicated smtpd-daemon
will only allow clients from <code class="systemitem">127.0.0.0/8</code> to relay
messages.</p></dd><dt><span class="term"><em class="parameter"><code>local_header_rewrite_clients</code></em></span></dt><dd><p>By default this option would “<span class="quote">rewrite message header
addresses in mail from these clients and update incomplete
addresses with the domain name</span>”. If such action has already
been taken by Postfix before the message went off to amavis, it
should not be done a second time when it reenters the Postfix mail
system. Leaving this option empty disables local header rewrites
and saves resources.</p></dd><dt><span class="term">remaining options</span></dt><dd><p>All remaining options either configure the dedicated
smtpd-daemon to be more failure tolerant or exist to avoid
unnecessary use of resources.</p></dd></dl></div><p>Running the postfix reload will activate the new transports
(Postfix will not yet send regular mail to amavisd). Combined with the
tail command problems can easily be detected:</p><pre class="screen"># <strong class="userinput"><code>postfix reload && tail -f /var/log/maillog</code></strong></pre><p>If there are no problems reported, basic configuration can be
tested.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="basics_testing"></a>2.4. Testing basic configuration</h3></div></div></div><p>Testing basic configuration consists of three separate tests,
starting at the end of the new delivery chain and working to it's
beginning. Their goal is to answer the following questions:</p><div class="orderedlist"><ol type="1"><li><p>Will amavisd-new accept connections at the specified IP
address and port?</p></li><li><p>Will the new dedicated smtpd-daemon accept connections at the
specified IP address and port?</p></li><li><p>Will a test message, injected into amavisd-new, be filtered,
sent to Postfix and delivered into a mailbox?</p></li></ol></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e542"></a>2.4.1. Testing amavisd's host and port</h4></div></div></div><p>A test, using the telnet command, serves to verify that amavisd
listens on the specified IP address and port. A successful connection
looks like this:</p><pre class="screen">$ <strong class="userinput"><code>telnet localhost 10024</code></strong>
220 [127.0.0.1] ESMTP amavisd-new service ready
<strong class="userinput"><code>EHLO localhost</code></strong>
250-[127.0.0.1]
250-VRFY
250-PIPELINING
250-SIZE
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 XFORWARD NAME ADDR PROTO HELO
<strong class="userinput"><code>QUIT</code></strong>
221 2.0.0 [127.0.0.1] amavisd-new closing transmission channel</pre><p>If the test fails, the following questions may help to debug the
problem:</p><div class="itemizedlist"><ul><li><p>Is the amavisd-new daemon running?</p></li><li><p>Does amavisd-new write an error to the log?</p></li><li><p>Do the IP address and port number specified in the
amavisd-new configuration match the values used during the
test?</p></li><li><p>Does a firewall intercept connections?</p></li></ul></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e573"></a>2.4.2. Testing the dedicated Postfix smtpd-daemon</h4></div></div></div><p>When Postfix was reloaded, the new, dedicated smtpd-daemon
(127.0.0.1:10025) should have been activated. A successful connection
looks like this:</p><pre class="screen">$ <strong class="userinput"><code>telnet 127.0.0.1 10025</code></strong>
220 mail.example.com ESMTP Postfix (2.3.2)
<strong class="userinput"><code>EHLO localhost</code></strong>
250-mail.example.com
250-PIPELINING
250-SIZE 40960000
250-ETRN
250-STARTTLS
250-AUTH PLAIN CRAM-MD5 LOGIN DIGEST-MD5
250-AUTH=PLAIN CRAM-MD5 LOGIN DIGEST-MD5
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
<strong class="userinput"><code>QUIT</code></strong>
221 2.0.0 Bye</pre><p>If the test fails, the following questions may help to debug the
problem:</p><div class="itemizedlist"><ul><li><p>Is the Postfix master daemon running?</p></li><li><p>Does Postfix write an error to the log?</p></li><li><p>Do the IP address and port number specified in the new
services configuration match the values used during the
test?</p></li><li><p>Does a firewall intercept connections?</p></li></ul></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e604"></a>2.4.3. Testing the new transport chain</h4></div></div></div><p>This test proves amavisd accepts e-mail as specified in <a href="#basics_amavisd-new" title="2.1. Configuring amavisd-new for Postfix">Section 2.1, “Configuring amavisd-new for Postfix”</a>, filters it and finally hands it over
to Postfix' dedicated smtpd-daemon as specified in <a href="#basics_smtpd-daemon" title="2.3. Configuring a dedicated SMTP-server for message
 reinjection">Section 2.3, “Configuring a dedicated SMTP-server for message
reinjection”</a>.</p><p>The following example uses the content of
<code class="filename">test-messages/sample-nonspam.txt</code> from the amavisd
test-messages to send an e-mail:</p><pre class="screen">$ <strong class="userinput"><code>telnet localhost 10024</code></strong>
220 [127.0.0.1] ESMTP amavisd-new service ready
<strong class="userinput"><code>HELO localhost</code></strong>
250 [127.0.0.1]
<strong class="userinput"><code>MAIL FROM: <></code></strong>
250 2.1.0 Sender OK
<strong class="userinput"><code>RCPT TO: <postmaster></code></strong>
250 2.1.5 Recipient postmaster OK
<strong class="userinput"><code>DATA</code></strong>
354 End data with <CR><LF>.<CR><LF>
<strong class="userinput"><code>From: virus-tester
To: undisclosed-recipients:;
Subject: amavisd test - simple - no spam test pattern
This is a simple test message from the amavisd-new test-messages.
.</code></strong>
250 2.6.0 Ok, id=30897-02, from MTA([127.0.0.1]:10025): 250 2.0.0 Ok: queued as 079474CE44
<strong class="userinput"><code>QUIT</code></strong>
221 2.0.0 [127.0.0.1] amavisd-new closing transmission channel</pre><p>The maillog shows the delivery path. Here's an excerpt from a
successful delivery process:</p><pre class="programlisting">Nov 1 11:28:10 mail postfix/smtpd[30986]: connect from localhost[127.0.0.1] <a name="mailflow_1"></a><img src="images/callouts/1.png" alt="1" border="0">
Nov 1 11:28:10 mail postfix/smtpd[30986]: 079474CE44: client=localhost[127.0.0.1]
Nov 1 11:28:10 mail postfix/cleanup[30980]: 079474CE44: message-id=<20061101102810.079474CE44@mail.example.com>
Nov 1 11:28:10 mail postfix/qmgr[20432]: 079474CE44: from=<>, size=822, nrcpt=1 (queue active)
Nov 1 11:28:10 mail amavis[30897]: (30897-02) Passed BAD-HEADER, <> -> <postmaster>, quarantine: badh-le5gjszxowBk, mail_id: le5gjszxowBk, Hits: -1.76, queued_as: 079474CE44, 39505 ms <a name="mailflow_2"></a><img src="images/callouts/2.png" alt="2" border="0">
Nov 1 11:28:10 mail postfix/smtpd[30986]: disconnect from localhost[127.0.0.1]
Nov 1 11:28:10 mail postfix/local[30987]: 079474CE44: to=<postmaster@example.com>, relay=local, delay=0.27, delays=0.14/0.05/0/0.08, dsn=2.0.0, status=sent (delivered to mailbox: postmaster) <a name="mailflow_3"></a><img src="images/callouts/3.png" alt="3" border="0">
Nov 1 11:28:10 mail postfix/qmgr[20432]: 079474CE44: removed</pre><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><a href="#mailflow_1"><img src="images/callouts/1.png" alt="1" border="0"></a> </td><td valign="top" align="left"><p>amavisd connects with Postfix dedicated smtpd-daemon and
hands over the e-mail that had been sent during the telnet
session. smtpd gives a queue-id of 079474CE44 that can be tracked
throughout the maillog.</p></td></tr><tr><td width="5%" valign="top" align="left"><a href="#mailflow_2"><img src="images/callouts/2.png" alt="2" border="0"></a> </td><td valign="top" align="left"><p>amavisd notices it has checked and sent an e-mail to
<postmaster>.</p></td></tr><tr><td width="5%" valign="top" align="left"><a href="#mailflow_3"><img src="images/callouts/3.png" alt="3" border="0"></a> </td><td valign="top" align="left"><p>Postfix' local-service logs it successfully delivered an
e-mail with queue-id 079474CE44 to the mailbox of
postmaster.</p></td></tr></table></div><p>If the test fails, the following questions may help to debug the
problem:</p><div class="itemizedlist"><ul><li><p>Does amavisd-new log errors?</p></li><li><p>Does running amavisd-new in debug-mode report errors?</p></li></ul></div></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="filter"></a>3. Message filtering examples</h2></div></div></div><p>Postfix can use various criteria to decide whether a message should
be sent to amavisd-new for examination. Combinations of criteria may serve
to create different configurations. The following section describes the
following configurations:</p><div class="itemizedlist"><ul><li><p>Filtering e-mail globally</p></li><li><p>Filtering e-mail globally by service</p></li><li><p>Filtering e-mail per recipient domain</p></li><li><p>Filtering e-mail per sender domain</p></li><li><p>Filtering e-mail by content</p></li></ul></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="filter_global"></a>3.1. Filtering E-mail globally</h3></div></div></div><p>In most cases email policies require global filtering - every
inbound and every outbound e-mail must be filtered by amavisd-new -
before it may be sent closer to its final destination.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note: Why check outgoing mail traffic?"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Why check outgoing mail traffic?</th></tr><tr><td align="left" valign="top"><p>Some reasons for checking mail coming from internal networks or
from authenticated roaming users are:</p><div class="itemizedlist"><ul><li><p>detect an internal infected PC which is sending
viruses</p></li><li><p>detect an internal zombiized PC (or an internal open relay
or proxy) which is sending or relaying spam</p></li><li><p>let the SpamAssassin Bayes autolearning feature see a
balanced view of all mail, including useful samples of non-spam
originating from inside</p></li><li><p>make it possible for pen pals feature to function (if
enabled)</p></li></ul></div></td></tr></table></div><p>In Postfix global settings for its services are written to
<code class="filename">main.cf</code>. The <em class="parameter"><code>content_filter</code></em>
parameter, the parameter configuring that messages are sent to
amavisd-new, must therefore be placed in
<code class="filename">main.cf</code>.</p><p>The <em class="parameter"><code>content_filter</code></em> parameter requires a
triplet, consisting of the transport service's name (here: amavisfeed,
given in <a href="#basics_transport_lmtp-client" title="2.2.1. Configuring a dedicated lmtp-client">Section 2.2.1, “Configuring a dedicated lmtp-client”</a>), the target
hosts IP address and the port where amavisd-new listens for incoming
connections. Following the values used in this documents examples the
<em class="parameter"><code>content_filter</code></em> configuration results in
this:</p><pre class="programlisting">content_filter=amavisfeed:[127.0.0.1]:10024</pre><p>The new external content filter will be activated once Postfix has
been reloaded. Sending a test-mail verifies the system works.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="filter_service_global"></a>3.2. Filtering E-mail by Postfix service</h3></div></div></div><p>Postfix is able to filter messages per service. Such configuration
requires the <em class="parameter"><code>content_filter</code></em> not to be applied
globally to all services in <code class="filename">main.cf</code> (see: <a href="#filter_global" title="3.1. Filtering E-mail globally">Section 3.1, “Filtering E-mail globally”</a>), but selectively, per service in
<code class="filename">master.cf</code>.</p><p>The following example presumes Postfix runs on a system offering
three IP addresses. In this example these are: <code class="systemitem">192.0.2.1</code> (WAN), <code class="systemitem">127.0.0.1</code> (localhost) and <code class="systemitem">10.0.0.254</code> (LAN). The goal is to filter
only e-mail that enters from the WAN interface.</p><p>This requires to create three dedicated smtpd-daemon instances,
each binding to one of the given IP addresses and deactivating the
global smtp service calling the smtpd command.</p><p>Additionally the WAN interface (here: 192.0.2.1:25) is configured
to use <em class="parameter"><code>content_filter</code></em>
<code class="option">=amavisfeed:[127.0.0.1]:10024</code> - it will delegate any
message that enters the Postfix mail system at this service to the
external amavisd content filter.</p><pre class="programlisting"># ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
# smtp inet n - n - - smtpd
...
192.0.2.1:25 inet n - n - - smtpd
-o content_filter=amavisfeed:[127.0.0.1]:10024
-o receive_override_options=no_address_mappings
10.0.0.254:25 inet n - n - - smtpd
127.0.0.1:10025 inet n - n - - smtpd
-o content_filter=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o smtpd_restriction_classes=
-o mynetworks=127.0.0.0/8
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
-o local_header_rewrite_clients=
-o smtpd_milters=
-o local_recipient_maps=
-o relay_recipient_maps=</pre></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="filter_by_recipient"></a>3.3. Filtering E-Mails per Recipient Domain</h3></div></div></div><p>Postfix is able to filter e-mails per recipient domain. In order
to do this the <em class="parameter"><code>content_filter</code></em> parameter must not
be set globally (see: <a href="#filter_global" title="3.1. Filtering E-mail globally">Section 3.1, “Filtering E-mail globally”</a>). Instead the
<em class="parameter"><code>content_filter</code></em> parameter has to be associated
with one or more recipient domains listed in a lookup table
(map).</p><div class="caution" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Caution"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="images/caution.png"></td><th align="left">Caution</th></tr><tr><td align="left" valign="top"><p>This filter method is not selective! It will send
<span class="emphasis"><em>any</em></span> mail with a recipient domain listed in the
lookup table to amavis even if the mail contains another recipient
that <span class="emphasis"><em>should not</em></span> be examined by the amavis
framework.</p><p>If fully selective rules are required all mail should be sent to
amavis and amavis' own rule sets should be configured to decide
whether a message for a given recipient should be examined or
not.</p></td></tr></table></div><p>When Postfix searches the lookup table and finds the recipients
domain listed as key, it will take the action associated with that
domain. The action will send the message to a <code class="option">FILTER
amavisfeed:[127.0.0.1]:10024</code>.</p><p>The following map
<code class="filename">/etc/postfix/filter_recipient_domains</code> specifies to
send messages to the <code class="option">FILTER amavisfeed</code> whenever a
message for any recipient at example.com enters the Postfix
mailqueues:</p><pre class="programlisting">example.com FILTER amavisfeed:[127.0.0.1]:10024</pre><p>Once the table has been created the <span><strong class="command">postmap</strong></span>
command must be used to create an indexed map Postfix can read:</p><pre class="screen"># <strong class="userinput"><code>postmap /etc/postfix/filter_recipient_domains</code></strong></pre><p>Once the map has been indexed, the <span><strong class="command">postmap</strong></span>
command is used to test the map. In the following example the
<span><strong class="command">postmap</strong></span> command queries for the domain example.com
and returns the associated action:</p><pre class="screen"># <strong class="userinput"><code>postmap -q "example.com" /etc/postfix/filter_recipient_domains</code></strong>
FILTER amavisfeed:[127.0.0.1]:10024</pre><p>The tested map must be added to <code class="filename">main.cf</code>,
before Postfix can make use of the new filter policy. Setting the
<em class="parameter"><code>check_recipient_access</code></em> parameter in the list of
<em class="parameter"><code>smtpd_recipient_restrictions</code></em> triggers evaluation
of entries in the map - <em class="parameter"><code>check_recipient_access</code></em> is
triggered by the envelope-recipient(s) given by a SMTP-client in a
SMTP-session with Postfix.</p><p>The following example puts the
<em class="parameter"><code>check_recipient_access</code></em> rule before
<em class="parameter"><code>permit_mynetworks</code></em> - all clients
envelope-recipient(s) will be filtered:</p><pre class="programlisting">smtpd_recipient_restrictions =
...
<strong class="userinput"><code>check_recipient_access hash:/etc/postfix/filter_recipient_domains</code></strong>
...
permit_mynetworks
reject_unauth_destination
...</pre><h4><a name="d0e866"></a>Filtering E-Mails per Recipient Domain only from External
Clients</h4><p>This example puts the
<em class="parameter"><code>check_recipient_access</code></em> rule after
<em class="parameter"><code>permit_mynetworks</code></em> - only messages sent from
clients that are not in Postfix <em class="parameter"><code>$mynetworks</code></em> list
(external or untrusted clients) will be filtered:</p><pre class="programlisting">smtpd_recipient_restrictions =
...
permit_mynetworks
reject_unauth_destination
<strong class="userinput"><code>check_recipient_access hash:/etc/postfix/filter_recipient_domains</code></strong>
...</pre></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="filter_by_sender"></a>3.4. Filtering E-Mails by Sender-Domain</h3></div></div></div><p>In general it doesn't make sense to filter e-mails by
sender-domain, as anyone can fake a sender-domain during a SMTP-session.
Filtering by sender-domain will probably only make sense, if messages
are not filtered globally, but e-mails from ones own domain should be
checked for spam or viruses before they leave the network.</p><p>Most of the configuration steps are identical with the ones noted
in <a href="#filter_by_recipient" title="3.3. Filtering E-Mails per Recipient Domain">Section 3.3, “Filtering E-Mails per Recipient Domain”</a>, except for the parameter that
triggers evaluation of the indexed map. In this scenario
envelope-senders should trigger map evaluation. The map, named
<code class="filename">/etc/postfix/filter_sender_domains</code> this time,
contains the sender domain (example.com) and associates it with the
required FILTER:</p><pre class="programlisting">example.com FILTER amavisfeed:[127.0.0.1]:10024</pre><p>Once the map has been converted and tested with the
<span><strong class="command">postmap</strong></span> command (see: <a href="#filter_by_recipient" title="3.3. Filtering E-Mails per Recipient Domain">Section 3.3, “Filtering E-Mails per Recipient Domain”</a>) it must be added to the list of
<em class="parameter"><code>smtpd_recipient_restrictions</code></em> using the
<em class="parameter"><code>check_sender_access</code></em> parameter:</p><pre class="programlisting">smtpd_recipient_restrictions =
...
<strong class="userinput"><code>check_sender_access hash:/etc/postfix/filter_sender_domains</code></strong>
...
permit_mynetworks
reject_unauth_destination
...</pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>The map must be listed before
<em class="parameter"><code>permit_mynetworks</code></em>, because only then it will be
applied to all clients - even the ones Postfix trusts, which are very
likely the ones from example.com.</p></td></tr></table></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="filter_by_content"></a>3.5. Filtering E-mail per Content</h3></div></div></div><p>Postfix is able - with deliberate limitations (see:
<code class="filename">BUILTIN_FILTER_README</code>) - to search for strings in
headers, the body and MIME-headers. If a string matches, Postfix may
call appropriate action.</p><p>The following example configures Postfix to look for the string
<code class="literal">offer</code> in Subject:-headers and delegate the message to
an external content filter if if finds a matching string.</p><p>A map, consisting of the search string noted as regexp-expression,
associates the search pattern with a FILTER action:</p><pre class="programlisting">/^Subject:.*offer/ FILTER amavisfeed:[127.0.0.1]:10024</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note: Indexing regexp- or pcre-maps?"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Indexing regexp- or pcre-maps?</th></tr><tr><td align="left" valign="top"><p>regexp- or pcre-maps are and must be plaintext files. They
<span class="emphasis"><em>must not</em></span> and cannot be converted to an indexed
map using the <span><strong class="command">postmap</strong></span> command. They can be tested
using the <span><strong class="command">postmap</strong></span> command using the
<code class="option">-q</code> command line option.</p></td></tr></table></div><p>Once the map has been created, Postfix must be configured to use
it. The following example uses the <em class="parameter"><code>header_checks</code></em>
parameter (not <em class="parameter"><code>body_checks</code></em> or
<em class="parameter"><code>mime_header_checks</code></em> as they apply to other message
parts) to implement the map into the Postfix delivery process:</p><pre class="programlisting">header_checks = regexp:/etc/postfix/filter_header</pre><p>Once Postfix has been reloaded it will send every e-mail that
contains the word <code class="literal">offer</code> in the Subject:-header off to
the external amavisd content filter.</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="d0e974"></a>4. Advanced Postfix and amavisd-new configuration</h2></div></div></div><p>In a post-queue content filtering setup, a mail message passes
through <code class="systemitem">smtpd</code> and
<code class="systemitem">cleanup</code> Postfix services twice, once before a
content filter, and the second time when an approved message is reinjected
from a content filter into the Postfix mail system. This is because checks
and transformations that have been configured in
<code class="filename">main.cf</code> are globally active and will be loaded and
run by any instance of these two services. To avoid wasting resources,
options that control runtime behavior of these services should not be
applied globally in <code class="filename">main.cf</code>, but selectively to
separate instances of these services in
<code class="filename">master.cf</code>.</p><p>Checks and transformations which are performed by a
<code class="systemitem">smtpd</code> Postfix service itself, e.g. access
controls, recipient validation, milters etc., can be controlled by adding
options (<code class="option">-o</code>) to appropriate
<code class="systemitem">smtpd</code> services. This has been shown in the basic
configuration examples (see: <a href="#basics_smtpd-daemon" title="2.3. Configuring a dedicated SMTP-server for message
 reinjection">Section 2.3, “Configuring a dedicated SMTP-server for message
reinjection”</a>).</p><p>Checks and transformations which are performed by a <code class="systemitem">cleanup</code> Postfix service are trickier because
in a normal Postfix setup there is only one
<code class="systemitem">cleanup</code> service, unlike
<code class="systemitem">smtpd</code> services of which there are many. Some of
the more important <code class="systemitem">cleanup</code> settings are
dynamically controllable by a <code class="systemitem">smtpd</code> service
through the use of its <em class="parameter"><code>receive_override_options</code></em>
option.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip: Transformations and checks"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Transformations and checks</th></tr><tr><td align="left" valign="top"><p>Any transformation should preferably only be performed once,
either before or after content filtering. When to transform depends on
the desired effect, for example whether a content filter should see
unchanged or modified mail messages. Typical transformations are:</p><div class="itemizedlist"><ul><li><p>rewrite addresses</p></li><li><p>add BCC recipients</p></li><li><p>modify mail header.</p></li></ul></div><p>Most checks should also be performed only once, preferably only on
the first passage, when the mail enters the Postfix mail system the
first time. This way messages can be rejected early - if needed - and
will not tie up downstream resources. Checking early also avoids bounces
in case of negative check results on a second passage after content
filtering.</p></td></tr></table></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1044"></a>4.1. Multiple cleanup service architecture</h3></div></div></div><p>To gain more control over a <code class="systemitem">cleanup</code>
service than offered by <em class="parameter"><code>receive_override_options</code></em>,
two (or more) <code class="systemitem">cleanup</code> services, each with its
own set of options, must be run. A Postfix setup with more than one
<code class="systemitem">cleanup</code> service is possible either with two
separate Postfix instances, or through a specification of services and
their options in <code class="filename">master.cf</code> file of a single Postfix
instance.</p><p>The following diagram illustrates a setup with two cleanup
services in a single Postfix instance:</p><div class="mediaobject"><pre class="literallayout"> .......................................
: Postfix :
----->smtpd \ :
: -pre-cleanup-\ /local---->
---->pickup / -queue- :
: -cleanup-/ | \smtp----->
: bounces/ ^ v :
: and locally | v :
: forwarded smtpd amavisfeed :
: messages 10025 | :
...........................|...........
^ |
| v
............|...............................
: | $inet_socket_port=10024 :
: | :
: $forward_method='smtp:[127.0.0.1]:10025' :
: $notify_method ='smtp:[127.0.0.1]:10025' :
: :
: amavisd-new :
............................................</pre></div><div class="procedure"><a name="d0e1072"></a><p class="title"><b>Procedure 1. Message flow with two cleanup services</b></p><ol type="1"><li><p>Messages enter the Postfix system at the regular
<code class="systemitem">smtpd</code> or <code class="systemitem">pickup</code>
service.</p></li><li><p>The <code class="systemitem">pre-cleanup</code> cleanup service
performs transformations and checks on these messages.</p></li><li><p>The <code class="systemitem">qmgr</code> service schedules the
messages to be sent to the amavisd-new content filter.</p></li><li><p><code class="systemitem">amavisd-new</code> performs various tests on
the messages.</p></li><li><p>Messages are re-injected into the Postfix mail system, sending
them to a dedicated, local <code class="systemitem">smtpd</code>
service.</p></li><li><p>The <code class="systemitem">cleanup</code> cleanup service performs
transformations and checks that must be done at this stage,
<span class="emphasis"><em>but</em></span> omits the ones that have already been
carried out in step 2.</p></li></ol></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1116"></a>4.2. Configuring two cleanup services</h3></div></div></div><p>Configuring Postfix <code class="systemitem">smtpd</code> services to use
two separate, dedicated <code class="systemitem">cleanup</code> services
requires the following steps:</p><div class="procedure"><ol type="1"><li><p>Create a second <code class="systemitem">cleanup</code>
instance</p></li><li><p>Modify the existing <code class="systemitem">cleanup</code>
service</p></li><li><p>Configure <code class="systemitem">smtpd</code> services to use
either of the two <code class="systemitem">cleanup</code> services.</p></li></ol></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1149"></a>4.2.1. Creating a second cleanup instance</h4></div></div></div><p>The following example adds a cleanup daemon named
<code class="systemitem">pre-cleanup</code>. It will handle messages before a
content filter.</p><pre class="programlisting"># ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
# smtp inet n - n - - smtpd
...
pre-cleanup unix n - n - 0 cleanup
-o virtual_alias_maps= </pre><p>The above leaves canonicalization address rewriting enabled so
that a content filter will see canonicalized (external) sender mail
addresses, but it disables globally configured virtual alias
transformations.</p><p>Such transformations will be done later by the second
<code class="systemitem">cleanup</code> service, so that a content filter
will see original (external) recipient mail addresses. Other options
may also be used as needed.</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1166"></a>4.2.2. Modifying the existing cleanup service</h4></div></div></div><p>The already existing cleanup service - having the service name
<code class="systemitem">cleanup</code> - will be used to process messages
that re-enter the Postfix mail system (also for delivery notifications
and forwarding as generated internally by Postfix).</p><p>Cleanup jobs that already have been performed by the
<code class="systemitem">pre-cleanup</code> service should not be run again.
The following example disables typical checks that have been run
before or are not needed for internally generated
notifications:</p><pre class="programlisting"># ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
# smtp inet n - n - - smtpd
...
cleanup unix n - n - 0 cleanup
-o mime_header_checks= <a name="cleanup-mime_header_checks"></a><img src="images/callouts/1.png" alt="1" border="0">
-o nested_header_checks= <a name="cleanup-nested_header_checks"></a><img src="images/callouts/2.png" alt="2" border="0">
-o body_checks= <a name="cleanup-body_checks"></a><img src="images/callouts/3.png" alt="3" border="0">
-o header_checks= <a name="cleanup-header_checks"></a><img src="images/callouts/4.png" alt="4" border="0"></pre><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><a href="#cleanup-mime_header_checks"><img src="images/callouts/1.png" alt="1" border="0"></a> <a href="#cleanup-nested_header_checks"><img src="images/callouts/2.png" alt="2" border="0"></a> <a href="#cleanup-body_checks"><img src="images/callouts/3.png" alt="3" border="0"></a> <a href="#cleanup-header_checks"><img src="images/callouts/4.png" alt="4" border="0"></a> </td><td valign="top" align="left"><p>The specified options disable header and body checks as
these would already be performed by a
<code class="systemitem">pre-cleanup</code> service.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note: always_bcc"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">always_bcc</th></tr><tr><td align="left" valign="top"><p>This <code class="systemitem">cleanup</code> service would also be
the appropriate one for specifying <em class="parameter"><code>always_bcc</code></em>
option - doing it globally would apply to both
<code class="systemitem">cleanup</code> services and would result in
<span class="emphasis"><em>two copies of each message</em></span> to be sent to the
specified address.</p></td></tr></table></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1212"></a>4.2.3. Configuring smtpd services</h4></div></div></div><p>Finally existing <code class="systemitem">smtpd</code> services on
ports 25 and 587 (<code class="systemitem">submission</code>), and the
<code class="systemitem">pickup</code> service must be configured to send
messages to the new <code class="systemitem">pre-cleanup</code> service
instead of a default <code class="systemitem">cleanup</code> service:</p><pre class="programlisting"># ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
# smtp inet n - n - - smtpd
...
pickup fifo n - n 60 1 pickup
-o cleanup_service_name=pre-cleanup
smtp inet n - n - - smtpd
-o cleanup_service_name=pre-cleanup
submission inet n - n - - smtpd
-o cleanup_service_name=pre-cleanup</pre></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="tuning"></a>5. Tuning</h2></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1237"></a>5.1. Maximum Number of Concurrent Processes</h3></div></div></div><p>The most important settings to tune and optimize in Postfix and
amavisd workflow are the maximum number of concurrent processes. The
maximum number of concurrent processes on both sides must be chosen with
care.</p><p>If the number is too low, hardware resources aren't used
efficiently and delivery time will be unnecessarily prolonged.
Experience tells that raising the number of processes a little, will not
raise the overall throughput in the same proportion.</p><p>As the system resources are nearing saturation with each increase
of the number of processes, an increase in throughput becomes marginal,
and eventually even negative when the number of processes exceeds its
near-optimum value. E-mail throughput will decrease, because processes
need to wait for each other. At worst e-mail delivery stalls.</p><p>Best practice is to start with a (conservative) maximum number of
2 concurrent processes. Everyday use has shown that this value may be
raised to a value between 10 and 30 concurrent Postfix client and
amavisd server processes. This also depends on the overall resources the
system may provide, how amavisd has been integrated into the Postfix
delivery process and on the anti-virus and anti-spam software being
loaded and used by amavisd-new.</p><p>Regardless of the maximum number of concurrent processes, both
sides - Postfix and amavisd - should be synchronized. To synchronize
both sides edit, the <em class="parameter"><code>$max_servers</code></em> parameter for
amavisd-new (see: <code class="filename">amavisd.conf</code>) and the number of
processes in <code class="filename">master.cf</code> listed in the dedicated
transports <em class="parameter"><code>maxproc</code></em> column for Postfix.</p><p>Both values should be identical for two reasons: If amavisd-new
offers more processes than Postfix will ever use, amavisd-new wastes
resources. On the other hand, if Postfix starts more dedicated
transports than amavisd can handle simultaneously, e-mail transport will
be refused and logged as error.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note: Controlling the maximum number of concurrent processes in
 main.cf"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Controlling the maximum number of concurrent processes in
main.cf</th></tr><tr><td align="left" valign="top"><p>Instead of controlling the maximum number of concurrent
processes of Postfix' dedicated transport in
<code class="filename">master.cf</code> it is also possible to keep the default
setting <code class="option">-</code> in <code class="filename">master.cf</code> and set
the following parameter and option in
<code class="filename">main.cf</code>:</p><pre class="programlisting">amavisfeed_destination_concurrency_limit = 2</pre><p>The name of the parameter starts with the service in
<code class="filename">master.cf</code> (here: amavisfeed) that should be
controlled and goes on with the suffix
<em class="parameter"><code>_destination_concurrency_limit</code></em>. Here also
<code class="option">2</code> is set as initial (conservative) value.</p></td></tr></table></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1294"></a>5.2. Additional Tips for Tuning</h3></div></div></div><p>Further Tuning-Tips can be found in
<code class="filename">README.performance</code> and the slides from <a href="http://www.ijs.si/software/amavisd/amavisd-new-magdeburg-20050519.pdf" target="_blank">amavisd-new,
advanced configuration and management</a>.</p></div></div></div></body></html>
|