/*++
/* NAME
/*	cleanup 8
/* SUMMARY
/*	canonicalize and enqueue Postfix message
/* SYNOPSIS
/*	\fBcleanup\fR [generic Postfix daemon options]
/* DESCRIPTION
/*	The \fBcleanup\fR(8) daemon processes inbound mail, inserts it
/*	into the \fBincoming\fR mail queue, and informs the queue
/*	manager of its arrival.
/*
/*	The \fBcleanup\fR(8) daemon performs the following transformations:
/* .IP \(bu
/*	Insert missing message headers: (\fBResent-\fR) \fBFrom:\fR,
/*	\fBTo:\fR, \fBMessage-Id:\fR, and \fBDate:\fR.
/* .br
/*	This is enabled with the \fBlocal_header_rewrite_clients\fR and
/*	\fBalways_add_missing_headers\fR parameter settings.
/* .IP \(bu
/*	Transform envelope and header addresses to the standard
/*	\fIuser@fully-qualified-domain\fR form that is expected by other
/*	Postfix programs.
/*	This task depends on the \fBtrivial-rewrite\fR(8) daemon.
/* .br
/*	The header transformation is enabled with the
/*	\fBlocal_header_rewrite_clients\fR parameter setting.
/* .IP \(bu
/*	Eliminate duplicate envelope recipient addresses.
/* .br
/*	This is enabled with the \fBduplicate_filter_limit\fR
/*	parameter setting.
/* .IP \(bu
/*	Remove message headers: \fBBcc\fR, \fBContent-Length\fR,
/*	\fBResent-Bcc\fR, \fBReturn-Path\fR.
/* .br
/*	This is enabled with the message_drop_headers parameter
/*	setting.
/* .IP \(bu
/*	Optionally, rewrite all envelope and header addresses according
/*	to the mappings specified in the \fBcanonical\fR(5) lookup tables.
/* .br
/*	The header transformation is enabled with the
/*	\fBlocal_header_rewrite_clients\fR parameter setting.
/* .IP \(bu
/*	Optionally, masquerade envelope sender addresses and message
/*	header addresses (i.e. strip host or domain information below
/*	all domains listed in the \fBmasquerade_domains\fR parameter,
/*	except for user names listed in \fBmasquerade_exceptions\fR).
/*	By default, address masquerading does not affect envelope recipients.
/* .br
/*	The header transformation is enabled with the
/*	\fBlocal_header_rewrite_clients\fR parameter setting.
/* .IP \(bu
/*	Optionally, expand envelope recipients according to information
/*	found in the \fBvirtual_alias_maps\fR lookup tables.
/* .PP
/*	The \fBcleanup\fR(8) daemon performs sanity checks on the content of
/*	each message. When it finds a problem, by default it returns a
/*	diagnostic status to the cleanup service client, and leaves
/*	it up to the client
/*	to deal with the problem. Alternatively, the client can request
/*	the \fBcleanup\fR(8) daemon to bounce the message back to the sender
/*	in case of trouble.
/* STANDARDS
/*	RFC 822 (ARPA Internet Text Messages)
/*	RFC 2045 (MIME: Format of Internet Message Bodies)
/*	RFC 2046 (MIME: Media Types)
/*	RFC 2822 (Internet Message Format)
/*	RFC 3463 (Enhanced Status Codes)
/*	RFC 3464 (Delivery status notifications)
/*	RFC 5322 (Internet Message Format)
/*	RFC 8689 (TLS-Required: message header)
/* DIAGNOSTICS
/*	Problems and transactions are logged to \fBsyslogd\fR(8)
/*	or \fBpostlogd\fR(8).
/* BUGS
/*	Table-driven rewriting rules make it hard to express \fBif then
/*	else\fR and other logical relationships.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/*	Changes to \fBmain.cf\fR are picked up automatically, as
/*	\fBcleanup\fR(8)
/*	processes run for only a limited amount of time. Use the command
/*	"\fBpostfix reload\fR" to speed up a change.
/*
/*	The text below provides only a parameter summary. See
/*	\fBpostconf\fR(5) for more details including examples.
/* COMPATIBILITY CONTROLS
/* .ad
/* .fi
/* .IP "\fBundisclosed_recipients_header (see 'postconf -d' output)\fR"
/*	Message header that the Postfix \fBcleanup\fR(8) server inserts when a
/*	message contains no To: or Cc: message header.
/* .PP
/*	Available in Postfix version 2.1 only:
/* .IP "\fBenable_errors_to (no)\fR"
/*	Report mail delivery errors to the address specified with the
/*	non-standard Errors-To: message header, instead of the envelope
/*	sender address (this feature is removed with Postfix version 2.2, is
/*	turned off by default with Postfix version 2.1, and is always turned on
/*	with older Postfix versions).
/* .PP
/*	Available in Postfix version 2.6 and later:
/* .IP "\fBalways_add_missing_headers (no)\fR"
/*	Always add (Resent-) From:, To:, Date: or Message-ID: headers
/*	when not present.
/* .PP
/*	Available in Postfix version 2.9 and later:
/* .IP "\fBenable_long_queue_ids (no)\fR"
/*	Enable long, non-repeating, queue IDs (queue file names).
/* HEADER FORMATTING CONTROLS
/* .ad
/* .fi
/* .PP
/*	Available in Postfix version 3.0 and later:
/* .IP "\fBmessage_drop_headers (bcc, content-length, resent-bcc, return-path)\fR"
/*	Names of message headers that the \fBcleanup\fR(8) daemon will remove
/*	after applying \fBheader_checks\fR(5) and before invoking Milter applications.
/* .PP
/*	Available in Postfix version 3.3 and later:
/* .IP "\fBheader_from_format (standard)\fR"
/*	The format of the Postfix-generated \fBFrom:\fR header.
/* .PP
/*	Available in Postfix version 3.10 and later:
/* .IP "\fBfull_name_encoding_charset (utf-8)\fR"
/*	The character set name (also called "charset") that Postfix
/*	will output when it automatically generates an RFC 2047 encoded
/*	full name.
/* .IP "\fBnon_empty_end_of_header_action (fix_quietly)\fR"
/*	How the \fBcleanup\fR(8) daemon will process a message when the primary
/*	message header is terminated with a non-empty line.
/* BUILT-IN CONTENT FILTERING CONTROLS
/* .ad
/* .fi
/*	Postfix built-in content filtering is meant to stop a flood of
/*	worms or viruses. It is not a general content filter.
/* .IP "\fBbody_checks (empty)\fR"
/*	Optional lookup tables for content inspection as specified in
/*	the \fBbody_checks\fR(5) manual page.
/* .IP "\fBheader_checks (empty)\fR"
/*	Optional lookup tables for content inspection of primary non-MIME
/*	message headers, as specified in the \fBheader_checks\fR(5) manual page.
/* .PP
/*	Available in Postfix version 2.0 and later:
/* .IP "\fBbody_checks_size_limit (51200)\fR"
/*	How much text in a message body segment (or attachment, if you
/*	prefer to use that term) is subjected to body_checks inspection.
/* .IP "\fBmime_header_checks ($header_checks)\fR"
/*	Optional lookup tables for content inspection of MIME related
/*	message headers, as described in the \fBheader_checks\fR(5) manual page.
/* .IP "\fBnested_header_checks ($header_checks)\fR"
/*	Optional lookup tables for content inspection of non-MIME message
/*	headers in attached messages, as described in the \fBheader_checks\fR(5)
/*	manual page.
/* .PP
/*	Available in Postfix version 2.3 and later:
/* .IP "\fBmessage_reject_characters (empty)\fR"
/*	The set of characters that Postfix will reject in message
/*	content.
/* .IP "\fBmessage_strip_characters (empty)\fR"
/*	The set of characters that Postfix will remove from message
/*	content.
/* .PP
/*	Available in Postfix version 3.9, 3.8.5, 3.7.10, 3.6.14,
/*	3.5.24, and later:
/* .IP "\fBcleanup_replace_stray_cr_lf (yes)\fR"
/*	Replace each stray <CR> or <LF> character in message
/*	content with a space character, to prevent outbound SMTP smuggling,
/*	and to make the evaluation of Postfix-added DKIM or other signatures
/*	independent from how a remote mail server handles such characters.
/* BEFORE QUEUE MILTER CONTROLS
/* .ad
/* .fi
/*	As of version 2.3, Postfix supports the Sendmail version 8
/*	Milter (mail filter) protocol. When mail is not received via
/*	the smtpd(8) server, the cleanup(8) server will simulate
/*	SMTP events to the extent that this is possible. For details
/*	see the MILTER_README document.
/* .IP "\fBnon_smtpd_milters (empty)\fR"
/*	A list of Milter (mail filter) applications for new mail that
/*	does not arrive via the Postfix \fBsmtpd\fR(8) server.
/* .IP "\fBmilter_protocol (6)\fR"
/*	The mail filter protocol version and optional protocol extensions
/*	for communication with a Milter application; prior to Postfix 2.6
/*	the default protocol is 2.
/* .IP "\fBmilter_default_action (Postfix >= 3.11: shutdown; Postfix < 3.11: tempfail)\fR"
/*	The default action when a Milter (mail filter) response is
/*	unavailable (for example, bad Postfix configuration or Milter
/*	failure).
/* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
/*	The {daemon_name} macro value for Milter (mail filter) applications.
/* .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR"
/*	The {v} macro value for Milter (mail filter) applications.
/* .IP "\fBmilter_connect_timeout (30s)\fR"
/*	The time limit for connecting to a Milter (mail filter)
/*	application, and for negotiating protocol options.
/* .IP "\fBmilter_command_timeout (30s)\fR"
/*	The time limit for sending an SMTP command to a Milter (mail
/*	filter) application, and for receiving the response.
/* .IP "\fBmilter_content_timeout (300s)\fR"
/*	The time limit for sending message content to a Milter (mail
/*	filter) application, and for receiving the response.
/* .IP "\fBmilter_connect_macros (see 'postconf -d' output)\fR"
/*	The macros that are sent to Milter (mail filter) applications
/*	after completion of an SMTP connection.
/* .IP "\fBmilter_helo_macros (see 'postconf -d' output)\fR"
/*	The macros that are sent to Milter (mail filter) applications
/*	after the SMTP HELO or EHLO command.
/* .IP "\fBmilter_mail_macros (see 'postconf -d' output)\fR"
/*	The macros that are sent to Milter (mail filter) applications
/*	after the SMTP MAIL FROM command.
/* .IP "\fBmilter_rcpt_macros (see 'postconf -d' output)\fR"
/*	The macros that are sent to Milter (mail filter) applications
/*	after the SMTP RCPT TO command.
/* .IP "\fBmilter_data_macros (see 'postconf -d' output)\fR"
/*	The macros that are sent to version 4 or higher Milter (mail
/*	filter) applications after the SMTP DATA command.
/* .IP "\fBmilter_unknown_command_macros (see 'postconf -d' output)\fR"
/*	The macros that are sent to version 3 or higher Milter (mail
/*	filter) applications after an unknown SMTP command.
/* .IP "\fBmilter_end_of_data_macros (see 'postconf -d' output)\fR"
/*	The macros that are sent to Milter (mail filter) applications
/*	after the message end-of-data.
/* .PP
/*	Available in Postfix version 2.5 and later:
/* .IP "\fBmilter_end_of_header_macros (see 'postconf -d' output)\fR"
/*	The macros that are sent to Milter (mail filter) applications
/*	after the end of the message header.
/* .PP
/*	Available in Postfix version 2.7 and later:
/* .IP "\fBmilter_header_checks (empty)\fR"
/*	Optional lookup tables for content inspection of message headers
/*	that are produced by Milter applications.
/* .PP
/*	Available in Postfix version 3.1 and later:
/* .IP "\fBmilter_macro_defaults (empty)\fR"
/*	Optional list of \fIname=value\fR pairs that specify default
/*	values for arbitrary macros that Postfix may send to Milter
/*	applications.
/* MIME PROCESSING CONTROLS
/* .ad
/* .fi
/*	Available in Postfix version 2.0 and later:
/* .IP "\fBdisable_mime_input_processing (no)\fR"
/*	Turn off MIME processing while receiving mail.
/* .IP "\fBmime_boundary_length_limit (2048)\fR"
/*	The maximal length of MIME multipart boundary strings.
/* .IP "\fBmime_nesting_limit (100)\fR"
/*	The maximal recursion level that the MIME processor will handle.
/* .IP "\fBstrict_8bitmime (no)\fR"
/*	Enable both strict_7bit_headers and strict_8bitmime_body.
/* .IP "\fBstrict_7bit_headers (no)\fR"
/*	Reject mail with 8-bit text in message headers.
/* .IP "\fBstrict_8bitmime_body (no)\fR"
/*	Reject 8-bit message body text without 8-bit MIME content encoding
/*	information.
/* .IP "\fBstrict_mime_encoding_domain (no)\fR"
/*	Reject mail with invalid Content-Transfer-Encoding: information
/*	for the message/* or multipart/* MIME content types.
/* .PP
/*	Available in Postfix version 2.5 and later:
/* .IP "\fBdetect_8bit_encoding_header (yes)\fR"
/*	Automatically detect 8BITMIME body content by looking at
/*	Content-Transfer-Encoding: message headers; historically, this
/*	behavior was hard-coded to be "always on".
/* AUTOMATIC BCC RECIPIENT CONTROLS
/* .ad
/* .fi
/*	Postfix can automatically add BCC (blind carbon copy)
/*	when mail enters the mail system:
/* .IP "\fBalways_bcc (empty)\fR"
/*	Optional address that receives a "blind carbon copy" of each message
/*	that is received by the Postfix mail system.
/* .PP
/*	Available in Postfix version 2.1 and later:
/* .IP "\fBsender_bcc_maps (empty)\fR"
/*	Optional BCC (blind carbon-copy) address lookup tables, indexed
/*	by envelope sender address.
/* .IP "\fBrecipient_bcc_maps (empty)\fR"
/*	Optional BCC (blind carbon-copy) address lookup tables, indexed by
/*	envelope recipient address.
/* ADDRESS TRANSFORMATION CONTROLS
/* .ad
/* .fi
/*	Address rewriting is delegated to the \fBtrivial-rewrite\fR(8) daemon.
/*	The \fBcleanup\fR(8) server implements table driven address mapping.
/* .IP "\fBempty_address_recipient (MAILER-DAEMON)\fR"
/*	The recipient of mail addressed to the null address.
/* .IP "\fBcanonical_maps (empty)\fR"
/*	Optional address mapping lookup tables for message headers and
/*	envelopes.
/* .IP "\fBrecipient_canonical_maps (empty)\fR"
/*	Optional address mapping lookup tables for envelope and header
/*	recipient addresses.
/* .IP "\fBsender_canonical_maps (empty)\fR"
/*	Optional address mapping lookup tables for envelope and header
/*	sender addresses.
/* .IP "\fBmasquerade_classes (envelope_sender, header_sender, header_recipient)\fR"
/*	What addresses are subject to address masquerading.
/* .IP "\fBmasquerade_domains (empty)\fR"
/*	Optional list of domains whose subdomain structure will be stripped
/*	off in email addresses.
/* .IP "\fBmasquerade_exceptions (empty)\fR"
/*	Optional list of user names that are not subjected to address
/*	masquerading, even when their addresses match $masquerade_domains.
/* .IP "\fBpropagate_unmatched_extensions (canonical, virtual)\fR"
/*	What address lookup tables copy an address extension from the lookup
/*	key to the lookup result.
/* .PP
/*	Available before Postfix version 2.0:
/* .IP "\fBvirtual_maps (empty)\fR"
/*	Optional lookup tables with a) names of domains for which all
/*	addresses are aliased to addresses in other local or remote domains,
/*	and b) addresses that are aliased to addresses in other local or
/*	remote domains.
/* .PP
/*	Available in Postfix version 2.0 and later:
/* .IP "\fBvirtual_alias_maps ($virtual_maps)\fR"
/*	Optional lookup tables that are often searched with a full email
/*	address (including domain) and that apply to all recipients: \fBlocal\fR(8),
/*	virtual, and remote; this is unlike alias_maps that are only searched
/*	with an email address localpart (no domain) and that apply
/*	only to \fBlocal\fR(8) recipients.
/* .PP
/*	Available in Postfix version 2.2 and later:
/* .IP "\fBcanonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient)\fR"
/*	What addresses are subject to canonical_maps address mapping.
/* .IP "\fBrecipient_canonical_classes (envelope_recipient, header_recipient)\fR"
/*	What addresses are subject to recipient_canonical_maps address
/*	mapping.
/* .IP "\fBsender_canonical_classes (envelope_sender, header_sender)\fR"
/*	What addresses are subject to sender_canonical_maps address
/*	mapping.
/* .IP "\fBremote_header_rewrite_domain (empty)\fR"
/*	Rewrite or add message headers in mail from remote clients if
/*	the remote_header_rewrite_domain parameter value is non-empty,
/*	updating incomplete addresses with the domain specified in the
/*	remote_header_rewrite_domain parameter, and adding missing headers.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
/* .IP "\fBduplicate_filter_limit (1000)\fR"
/*	The maximal number of addresses remembered by the address
/*	duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
/*	for \fBshowq\fR(8) queue displays.
/* .IP "\fBheader_size_limit (102400)\fR"
/*	The maximal amount of memory in bytes for storing a message header.
/* .IP "\fBhopcount_limit (50)\fR"
/*	The maximal number of Received:  message headers that is allowed
/*	in the primary message headers.
/* .IP "\fBin_flow_delay (1s)\fR"
/*	Time to pause before accepting a new message, when the message
/*	arrival rate exceeds the message delivery rate.
/* .IP "\fBmessage_size_limit (10240000)\fR"
/*	The maximal size in bytes of a message, including envelope information.
/* .PP
/*	Available in Postfix version 2.0 and later:
/* .IP "\fBheader_address_token_limit (10240)\fR"
/*	The maximal number of address tokens are allowed in an address
/*	message header.
/* .IP "\fBmime_boundary_length_limit (2048)\fR"
/*	The maximal length of MIME multipart boundary strings.
/* .IP "\fBmime_nesting_limit (100)\fR"
/*	The maximal recursion level that the MIME processor will handle.
/* .IP "\fBqueue_file_attribute_count_limit (100)\fR"
/*	The maximal number of (name=value) attributes that may be stored
/*	in a Postfix queue file.
/* .PP
/*	Available in Postfix version 2.1 and later:
/* .IP "\fBvirtual_alias_expansion_limit (1000)\fR"
/*	The maximal number of addresses that virtual alias expansion produces
/*	from each original recipient.
/* .IP "\fBvirtual_alias_recursion_limit (1000)\fR"
/*	The maximal nesting depth of virtual alias expansion.
/* .PP
/*	Available in Postfix version 3.0 and later:
/* .IP "\fBvirtual_alias_address_length_limit (1000)\fR"
/*	The maximal length of an email address after virtual alias expansion.
/* SMTPUTF8 CONTROLS
/* .ad
/* .fi
/*	Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
/* .IP "\fBsmtputf8_enable (yes)\fR"
/*	Enable preliminary SMTPUTF8 support for the protocols described
/*	in RFC 6531, RFC 6532, and RFC 6533.
/* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR"
/*	Detect that a message requires SMTPUTF8 support for the specified
/*	mail origin classes.
/* .PP
/*	Available in Postfix version 3.2 and later:
/* .IP "\fBenable_idna2003_compatibility (no)\fR"
/*	Enable 'transitional' compatibility between IDNA2003 and IDNA2008,
/*	when converting UTF-8 domain names to/from the ASCII form that is
/*	used for DNS lookups.
/* TLS SUPPORT
/* .ad
/* .fi
/*	Available in Postfix version 3.10 and later:
/* .IP "\fBtls_required_enable (yes)\fR"
/*	Enable support for the "TLS-Required: no" message header, defined
/*	in RFC 8689.
/* .IP "\fBrequiretls_esmtp_header (yes)\fR"
/*	Record the ESMTP REQUIRETLS request in a "Require-TLS-ESMTP:
/*	yes" message header.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/*	The default location of the Postfix main.cf and master.cf
/*	configuration files.
/* .IP "\fBdaemon_timeout (18000s)\fR"
/*	How much time a Postfix daemon process may take to handle a
/*	request before it is terminated by a built-in watchdog timer.
/* .IP "\fBdelay_logging_resolution_limit (2)\fR"
/*	The maximal number of digits after the decimal point when logging
/*	delay values.
/* .IP "\fBdelay_warning_time (0h)\fR"
/*	The time after which the sender receives a copy of the message
/*	headers of mail that is still queued.
/* .IP "\fBipc_timeout (3600s)\fR"
/*	The time limit for sending or receiving information over an internal
/*	communication channel.
/* .IP "\fBmax_idle (100s)\fR"
/*	The maximum amount of time that an idle Postfix daemon process waits
/*	for an incoming connection before terminating voluntarily.
/* .IP "\fBmax_use (100)\fR"
/*	The maximal number of incoming connections that a Postfix daemon
/*	process will service before terminating voluntarily.
/* .IP "\fBmyhostname (see 'postconf -d' output)\fR"
/*	The internet hostname of this mail system.
/* .IP "\fBmyorigin ($myhostname)\fR"
/*	The domain name that locally-posted mail appears to come
/*	from, and that locally posted mail is delivered to.
/* .IP "\fBprocess_id (read-only)\fR"
/*	The process ID of a Postfix command or daemon process.
/* .IP "\fBprocess_name (read-only)\fR"
/*	The process name of a Postfix command or daemon process.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
/*	The location of the Postfix top-level queue directory.
/* .IP "\fBsoft_bounce (no)\fR"
/*	Safety net to keep mail queued that would otherwise be returned to
/*	the sender.
/* .IP "\fBsyslog_facility (mail)\fR"
/*	The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
/*	A prefix that is prepended to the process name in syslog
/*	records, so that, for example, "smtpd" becomes "prefix/smtpd".
/* .PP
/*	Available in Postfix version 2.1 and later:
/* .IP "\fBenable_original_recipient (yes)\fR"
/*	Enable support for the original recipient address after an
/*	address is rewritten to a different address (for example with
/*	aliasing or with canonical mapping).
/* .PP
/*	Available in Postfix 3.3 and later:
/* .IP "\fBservice_name (read-only)\fR"
/*	The master.cf service name of a Postfix daemon process.
/* .PP
/*	Available in Postfix 3.5 and later:
/* .IP "\fBinfo_log_address_format (external)\fR"
/*	The email address form that will be used in non-debug logging
/*	(info, warning, etc.).
/* .PP
/*	Available in Postfix 3.9 and later:
/* .IP "\fBforce_mime_input_conversion (no)\fR"
/*	Convert body content that claims to be 8-bit into quoted-printable,
/*	before header_checks, body_checks, Milters, and before after-queue
/*	content filters.
/* FILES
/*	/etc/postfix/canonical*, canonical mapping table
/*	/etc/postfix/virtual*, virtual mapping table
/* SEE ALSO
/*	trivial-rewrite(8), address rewriting
/*	qmgr(8), queue manager
/*	header_checks(5), message header content inspection
/*	body_checks(5), body parts content inspection
/*	canonical(5), canonical address lookup table format
/*	virtual(5), virtual alias lookup table format
/*	postconf(5), configuration parameters
/*	master(5), generic daemon options
/*	master(8), process manager
/*	postlogd(8), Postfix logging
/*	syslogd(8), system logging
/* README FILES
/* .ad
/* .fi
/*	Use "\fBpostconf readme_directory\fR" or
/*	"\fBpostconf html_directory\fR" to locate this information.
/* .na
/* .nf
/*	ADDRESS_REWRITING_README Postfix address manipulation
/*	CONTENT_INSPECTION_README content inspection
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*
/*	Wietse Venema
/*	Google, Inc.
/*	111 8th Avenue
/*	New York, NY 10011, USA
/*
/*	Wietse Venema
/*	porcupine.org
/*--*/

/* System library. */

#include <sys_defs.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

/* Utility library. */

#include <msg.h>
#include <vstring.h>
#include <dict.h>

/* Global library. */

#include <mail_conf.h>
#include <cleanup_user.h>
#include <mail_proto.h>
#include <mail_params.h>
#include <record.h>
#include <rec_type.h>
#include <mail_version.h>

/* Single-threaded server skeleton. */

#include <mail_server.h>

/* Application-specific. */

#include "cleanup.h"

/* cleanup_service - process one request to inject a message into the queue */

static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
{
    VSTRING *buf = vstring_alloc(100);
    CLEANUP_STATE *state;
    int     flags;
    int     type = 0;
    int     status;

    /*
     * Sanity check. This service takes no command-line arguments.
     */
    if (argv[0])
	msg_fatal("unexpected command-line argument: %s", argv[0]);

    /*
     * Open a queue file and initialize state.
     */
    state = cleanup_open(src);

    /*
     * Send the queue id to the client. Read client processing options. If we
     * can't read the client processing options we can pretty much forget
     * about the whole operation.
     */
    attr_print(src, ATTR_FLAG_NONE,
	       SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
	       SEND_ATTR_STR(MAIL_ATTR_QUEUEID, state->queue_id),
	       ATTR_TYPE_END);
    if (attr_scan(src, ATTR_FLAG_STRICT,
		  RECV_ATTR_INT(MAIL_ATTR_FLAGS, &flags),
		  ATTR_TYPE_END) != 1) {
	state->errs |= CLEANUP_STAT_BAD;
	flags = 0;
    }
    cleanup_control(state, flags);

    /*
     * XXX Rely on the front-end programs to enforce record size limits.
     * 
     * First, copy the envelope records to the queue file. Then, copy the
     * message content (headers and body). Finally, attach any information
     * extracted from message headers.
     */
    while (CLEANUP_OUT_OK(state)) {
	if ((type = rec_get_raw(src, buf, 0, REC_FLAG_NONE)) < 0) {
	    state->errs |= CLEANUP_STAT_BAD;
	    break;
	}
	if (REC_GET_HIDDEN_TYPE(type)) {
	    msg_warn("%s: record type %d not allowed - discarding this message",
		     state->queue_id, type);
	    state->errs |= CLEANUP_STAT_BAD;
	    break;
	}
	CLEANUP_RECORD(state, type, vstring_str(buf), VSTRING_LEN(buf));
	if (type == REC_TYPE_END)
	    break;
    }

    /*
     * Keep reading in case of problems, until the sender is ready to receive
     * our status report.
     */
    if (CLEANUP_OUT_OK(state) == 0 && type > 0) {
	while (type != REC_TYPE_END
	       && (type = rec_get_raw(src, buf, 0, REC_FLAG_NONE)) > 0) {
	    if (type == REC_TYPE_MILT_COUNT) {
		int     milter_count = atoi(vstring_str(buf));

		/* Avoid deadlock. */
		if (milter_count >= 0)
		    cleanup_milter_receive(state, milter_count);
	    }
	}
    }

    /*
     * Log something to make timeout errors easier to debug.
     */
    if (vstream_ftimeout(src))
	msg_warn("%s: read timeout on %s",
		 state->queue_id, VSTREAM_PATH(src));

    /*
     * Finish this message, and report the result status to the client.
     */
    status = cleanup_flush(state);		/* in case state is modified */
    attr_print(src, ATTR_FLAG_NONE,
	       SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
	       SEND_ATTR_STR(MAIL_ATTR_WHY,
			     (state->flags & CLEANUP_FLAG_SMTP_REPLY)
			     && state->smtp_reply ? state->smtp_reply :
			     state->reason ? state->reason : ""),
	       ATTR_TYPE_END);
    cleanup_free(state);

    /*
     * Cleanup.
     */
    vstring_free(buf);
}

/* pre_accept - see if tables have changed */

static void pre_accept(char *unused_name, char **unused_argv)
{
    const char *table;

    if ((table = dict_changed_name()) != 0) {
	msg_info("table %s has changed -- restarting", table);
	exit(0);
    }
}

MAIL_VERSION_STAMP_DECLARE;

/* main - the main program */

int     main(int argc, char **argv)
{

    /*
     * Fingerprint executables and core dumps.
     */
    MAIL_VERSION_STAMP_ALLOCATE;

    /*
     * Clean up an incomplete queue file in case of a fatal run-time error,
     * or after receiving SIGTERM from the master at shutdown time.
     */
    signal(SIGTERM, cleanup_sig);
    msg_cleanup(cleanup_all);

    /*
     * Pass control to the single-threaded service skeleton.
     */
    single_server_main(argc, argv, cleanup_service,
		       CA_MAIL_SERVER_INT_TABLE(cleanup_int_table),
		       CA_MAIL_SERVER_BOOL_TABLE(cleanup_bool_table),
		       CA_MAIL_SERVER_NBOOL_TABLE(cleanup_nbool_table),
		       CA_MAIL_SERVER_STR_TABLE(cleanup_str_table),
		       CA_MAIL_SERVER_TIME_TABLE(cleanup_time_table),
		       CA_MAIL_SERVER_PRE_INIT(cleanup_pre_jail),
		       CA_MAIL_SERVER_POST_INIT(cleanup_post_jail),
		       CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
		       CA_MAIL_SERVER_IN_FLOW_DELAY,
		       CA_MAIL_SERVER_UNLIMITED,
		       0);
}
