Wish list: Things to do before the stable release: make pre-release-check, HTML validator check. Disable -DSNAPSHOT and -DNONPROD in makedefs. Alias htable(3) calls to equivalent binhash(3) calls, and obsolete the htable(3) module. FILTER_README needs some text on multi-instance implementations, and existing multi-instance references need to be updated. Fix code that still uses "long" for data_size and data_offset, and that uses "%ld" in sscanf(). A smart query service for live Postfix tables that outputs JSON? Add a pointer to http://mmogilvi.users.sourceforge.net/software/oauthbearer.html in documentation or on-line howtos. Read http://mmogilvi.users.sourceforge.net/software/oauthbearer.html and see how we can improve on the Postfix side. Add verp=+= to the qmgr "from=" logging. This is already implemented but not yet integrated. Need canonical Dovecot example that has virtual_mailbox_domains, (virtual_mailbox_maps or reject unverified_recipient), and virtual_transport. Make smtpd_relay_before_recipient_restrictions settable in smtpd_checks tests. Make the DNS resolver library pluggable, so that we can a) plug in a fake resolver library for DNS-related regression tests and make DNS tests hermetic (no external dependency; b) add support for non-libbind resolvers. Gracefully handle requests for unsupported functionality; return an error status, instead of terminating. Add a robust dnssec_probe regression test (success and fail) that does not break existing regression tests. smtp_sasl_tls_security_options = noanonymous, and make smtp_sasl_security_options the default dependent on the smtp_sasl_tls_security_options default (i.e. reverse the dependency). Or make them independent. Try to make the master throttle more distrusting. Currently, the master throttles a service after a child process cannot be created (fork() fails), or if a child process fails upon its first use. The master always unthrottles the service if a process handles a client successfully. This is sufficient to mitigate local errors that break all attempts to use a service. It also slows down stupid remote attacks as long as malicious traffic dominates benign traffic. Perhaps monitor a crashing percentage? If 50% of all connections to a service result in abnormal termination, that would be bad even under a non-attack scenario. More accurate address verification: do a quota check before reporting that a local(8) or virtual(8) recipient is deliverable. Eliminate duplicate mail submission permission checks from sendmail, so that they happen in postdrop only. Then, pass the result through the postdrop-to-sendmail protocol. This requires that postdrop reads all inputs before responding (the local_login_sender_maps check depends on the envelope sender). Then sendmail can save input to dead.letter (no setgid privilege, but it would still have to use safe_open() to avoid clobbering files). Consider removing compat_level_from_numbers() and aliases, because they are no longer used anywhere. Allow '}' at the beginning of a line. This would make multi-line configuration settings easier to enter. This may be true for main.cf, master.cf and similar files (such as database configuration files, but not necessarily elsewhere). So it may have to be a readlline flag. Understand what happens with DNSSEC related status fields in posttls-finger when resolv.conf points to a host that runs no DNS server. Hardening the half-dane behavior: some sites may rely on current behavior which allows original MX domain name for certificate matches. Requires a new (compatibility) parameter setting? Code deduplication: migrate multi_server applications to event_server, because the multi_server and event_server skeletons are much more similar than other skeletons. In addition to the default event_server accept() handler, also register a read event callback for handling post_accept events. But the currrent multi_server API fits typical usage better. When a secondary instance has no multi_instance_name set, postmulti -i won't be able to find it. nbbio: exercise the sanity checks with fake msg(3) functions. optreset (bsd-ism) how badly do we need it? transport policy protocol (clone of check_policy). See also postscreen event-driven client for policy delegation below. smtp_line_length_limit can insert a line break in the middle of a multi-byte character (which is not necessarily UTF-8, so we can't simply look at the 8th bit). Also, note that a multi-byte character may span queue file record boundaries, for example if line_length_limit == smtp_line_length_limit. The only way to fix this is to make the smtp_text_out() routine aware of every possible multi-byte encoding. Replace ad-hoc code for pipe(8) flags handling, with infrastructure that was built for smtp(8). Move map descriptions from postconf(1) to DATABASE_README and point there. The text in DATABASE_README is less complete than that in postconf(1). make tls_pre_jail_init() safe by design for use in programs that implement both clients and servers. In smtpd(8) and postscreen(8), set the ehlo_discard_mask to ~0 so that STARTTLS, BDAT, DSN, etc. work only for clients that send EHLO. Wordsmithing: "replace by X" -> "replace with X" unless X is "responsible" for making the substitution. In postscreen, don't fork after 'postfix reload' when psc_check_queue_length (and psc_post_queue_length?) is zero. After I/O error, store errno in VSTREAM object before errno may be overwritten. Add some tips for logging from container: https://www.projectatomic.io/blog/2016/10/playing-with-docker-logging/; syslog_name = $myhostname/postfix; mkdir queue and data dir; postfix check to create queue subdirectories. Add postwhite as a postscreen-related project. https://github.com/stevejenkins/postwhite/blob/master/README.md XFORWARD attributes in policy protocol? Document postsrsd and postforward for srs-ifying. Would more fine-grained smtp_generic_maps support help? Decide whether to deprecate database configuration pathnames that start with ".", for example, ldap:./file/name. These forms are documented for ldap:, memcache:, mysql:, pgsql:, and sqlite: maps. Postfix daemon processes will look up files relative to the queue directory, but with postmap command-line processes it would be more natural to interpret relative pathnames relative to the current directory of the calling process (it would be a surprise if "postmap hash:./foo" would access "/var/spool/postfix/foo", or if "postmap hash:foo" and or "postmap hash:./foo" would access different files). Convert postalias(1) to store external-form keys, and convert aliases(5) to perform external-first lookup with fallback to internal form, to make it consistent with the rest of Postfix. In several years we may remove the internal-form fallbacks with a compatibility_level safety net. In the bounce daemon, set util_utf8_enable if returning an SMTPUTF8 message. This is wrong; if SMTPUTF8 is disabled, then Postfix must not turn it on. Add a header_body_checks extension callback in smtp_proto.c that implements the PASS action. Propagate SMTPD_PEER_CODE_XXX from smtpd(8) to cleanup(8), so that {client_resolve} and {_} produce consistent results. NO_IP_CYRUS_SASL_AUTH should be a main.cf parameter. Modeline support in config files to enable/disable trailing #comment, and to give hints about how to handle an LHS or RHS. This will not preserve trailing comments in lines that are modified with "postconf -e" and the like. Maintainability: replace lengthy libmilter-API argument lists with named parameters, as with the libtls API. Fix buflen integer overflow detection in dict*sql.c. Fix "make test" bitrot. Move DNS-based tests from porcupine.org to postfix.org, or use a mock DNS library (a library that presents the same API as the real library, but that produces canned responses). Document dns_ncache_ttl_fix_enable use case in POSTSCREEN_README and RELEASE_NOTES. Remove this file from the stable release. Things to do after the stable release: Specify WARN_UNUSED_RESULT for all library functions that pass, deliver, bounce or defer a delivery request. Invent some kind of type-checking wrappers for htable(3), ctable(3) and other modules that take and return a void* pointer. We already did that for variadic functions. TLS certificate provenance: indicate whether a subject name/issuer are verified or not (for example, change the attribute name to unverified_ccert_subject etc.). This is relevant only for fingerprint-based authentication including DANE, and affects logging, SMTPD policy, and Milters. Generalize the daemon '-S' stand-alone mode, so that it can be used with custom configuration settings for request/reply regression testing. This would use the existing "-o name=value" support to override parameters. For example, queue_directory would point to a directory with sockets for fake versions of Postfix-internal services. Update the list of Sendmail macros that Postfix can send to Milters (auth_ssf and TLS-related). Update smtpd command count when rejecting or skipping input before command-table lookup. But then we need to count commands that are rejected (malformed UTF-8, tokenizer error, forbidden command), or skipped (noop). What is the best place to detect spaces in pathnames during installation/upgrade/packaging? postfix-install for early warning, and post-install as a safety net? When the service basename differs from the program file basename, either prepend the service name to the syslogname (as if syslog_name=postfix/service/program), or prepend the service name to the process name (perhaps too confusing). The service indication is desirable for mail delivery transports (smtp versus relay) as it identifies what scheduler parameters are in effect, but it is also desirable for mail receiving services (smtp versus submission verus smtps as configured in the stock master.cf file). This requires exceptions for some program names (exclude smtpd to avoid logging postfix/smtp/smtpd which could result in more confusion, and maybe other program names). UTF8 DNS[BW]L domain name. Consolidate maps flags in mail_params.h instead of having multiple copies scattered across programs. Try to allow UTF-8 myhostname/mydomain, at least in bounce template expansion. In the SMTP server, do not issue an enhanced status code when rejecting a connection before the HELO handshake is completed. Maybe don't whitelist a client that has maxed out its per-MTA connection count limit. Inline support for pcre:{/pattern/=action, ...} and ditto support for regexp: and cidr: tables. Factor out and reuse code that already exists in inline: and other tables. Log command=good/bad statistics in postscreen? smtpd_checks tests either must use a DNS dummy resolver (override the res_search API) or all names must be under test.postfix.org (but that does not work for address->name lookups, and cannot simulate some errors). Reporting the original Message-ID in a bounce message In-Reply-To: or References: header. In the cleanup daemon, grab a copy of the Message-ID and export it along with other header-extracted information at the top of the "extracted" queue file segment. In the queue manager, extract this along with other header-extracted information, and forward the Message-ID in the bounce server notification request. Clobber ORCPT when sender is owner-mumble? Add milter_mumble_macros to the list of per-macro features. The pickup daemon logs warnings only when the cleanup daemon dit not provide a "reason" attribute. Is this logic right? up-convert myhostname to UTF-8 in MIME boundary strings? Eliminate code duplication between pcf_print_master_field() and pcf_print_master_entry(). Error reporting: see if pcf_check_master_entry() and children can return error descriptions instead of terminating with a fatal error. Add a switch to consider postscreen deep protocol tests as "completed" when receiving "RSET" after "RCPT TO" and the session has passed all tests up to that point. RSET becomes like QUIT except perhaps that it does not hang up. apipe: map, splits results into address lists and performs lookups for the invidual addresses, converting back and forth between external and internal forms. Clarify that receive_override_options have no effect with smtpd_proxy_filter. Document the relative order of header_checks, address rewriting, milters. NOT: Table-driven case folding and case-insensitive string comparison specifically for UTF-8. Use libicu functions instead. When downgrading message/global to 7bit, is quoted-printable the appropriate encoding? Should it be base64? Should we encode headers with RFC 2047, when that is the only reason that Postfix cannot deliver to a non-UTF8SMTP server? Probably not in the general case. What about Postfix as a gateway server that converts UTF8SMTP for delivery to non-UTF8SMTP environments? Document and test restriction_classes example for smtpd_policy_service_default_action. Don't accept AUTH or other features that are not announced in the EHLO response. Suggested at Mailserver conference: Postscreen RDNS-based reputation (but this makes postscreen performance highly unpredicable because it introduces a dependency on random DNS servers). Suggested at Mailserver conference: a way to select a specific field in a table, presumably as the result value. This may be done with a filtermap{i,j,...}: table that propagates only the specified field(s). Discourage the use of "after 220" tests in POSTSCREEN_README and the documentation of individual parameter settings. To un-break "make tests" under src/smtpd, make tests independent from the DNS and native routines for host name/address lookup. Make been_here flag BH_FLAG_FOLD configurable for masochists. Replace some redundant TLS_README sections with pointers to FORWARD_SECRECY_README. Move html/index.html source to proto/. How hard is it to follow canonical or virtual mapping for the purpose of address validation? We must never reject a valid address. Preserve case in smtpd_resolve_addr() and add a structure member for the case-folded address. IIRC some Milter macro needs to show the unfolded address. Per SASL account rate limits. This requires new infrastructure that maintains stats by SASL account instead of client IP address. Watchdog timer in postmap/postalias. Begin code revision, after DANE support stabilizes. This should be one pass that changes only names and no code. recipient_delimiters = $recipient_delimiter for BC All source code must specify its original author and license statement. Some code modules specify Lutz Jaenicke as the original author and fall under his liberal license. Code that is added to such a module has the same license (or at least something that is not more restrictive). Code modules without input from Lutz Jaenicke must state its original author and license (preferably no more restrictive than Postfix's own license). Currently, too many files list Wietse as the original author, and Lutz Jaenicke's license, which is wrong. We have smtp_host_lookup, smtp_dns_resolver_options, and now smtp_dns_support_level. Of these, smtp_dns_resolver_options is orthogonal but the rest has overlap. There needs to be support for automatic migration from the deprecated disable_dns_lookups feature to the preferred smtp_dns_support_level feature. This support needs to exist for several releases before the deprecated feature can be removed. End code revision, after DANE support stabilizes. It would be nice if "bare username" lookup is not hard-coded for domains in the local address class. Don't forget Apple's code donation for fetching mail from IMAP server. Should postconf -o refuse to work without the -x option? Make 30s caching (feature 20070414) configurable, such that 0 means no caching. Make errno white/blacklist for getpwnam_r etc. and mailbox write errors. smtpd_muble_restrictions rule names are case-insensitive. restriction_classes values are case-sensitive but should be case-insensitive for consistency with smtpd_muble_restrictions. Make "rename" the default when postmapping a DB file (later: use copy+rename for postmap -i, postmap -d). Service-name parameters aren't documented in daemon manpages. When faking up the DSN ORCPT, don't send bare usernames from local command-line submission. lmtp_assume_final is broken. A 2XX response does not imply final delivery. The Sieve language implements accept-then-bounce. postscreen event-driven plug-in interface to send out a query in parallel with the Pregreet and DNSBL tests, using a simplified version of the policy delegation protocol. Parallelized queue preprocessing: rip out the queue manager code to read queue files and resolve recipients, and run it in parallel processes. The queue manager then processes their results as they become available. This would eliminate the qmgr<->trivial-rewrite bottleneck. This can also eliminate much of the scheduling disadvantage of a single queue manager compared to hundreds of mail receiving or sending processes (especially if there is a way to scan the queue in parallel). Memory pools for same-type memory objects. This can be used to either increase memory locality for frequently-allocated objects (MRU allocation) or to make use-after-free bugs more detectable (use LRU allocation and wipe the object immediately after free(). Finally, same-type memory pools prevent object type errors with use-after-free bugs. "no-cache" option for selected postscreen tests? Need a new DICT flag to indicate that a map handle supports locking. If it doesn't (as with memcache or proxymap handles), then postscreen etc. don't need to close a cache file after "postfix reload". After a fork() it is OK to keep using a memcache or proxymap handle, because the parent exits immediately. For this to work, the memcache client needs to propagate the flag from a persistent backup map, but the proxymap protocol should not propagate this to the client. Different TTL values for different DNSBL sources? Replace master(8) SIGHUP by very simple socket protocol to allow reload of a specific service. postscreen: in the dummy SMTP engine, log the protocol state at time of violation (like smtpd, set state->where initially to CONNECT, then update it with the name of the last "known" command, or set it to "unimplemented"). The discussion of postscreen cache configuration is in the wrong place (how whitelisting works). Move it to the section about configuring postscreen. Before proxymap can be exposed to the network (primarily to share postscreen or verify caches), need to enforce limits on attribute string name and value length in IPC protocols. 10-20KB seems OK. We need to enforce content sanity checks (for example, no control characters; Postfix does not pass around multi-line data in table lookups). The VSTREAM library already supports read/write deadlines. We need to use attack-resistant code for numeric conversion. move flush_init() etc. from defer service clients to the bounce daemon? Postfix works best when work can be spread out over many clients, instead of over a few servers. multi_connect() function that takes a list of inet:host:port and/or unix:pathname specs, with an explicit "inet" prefix argument to handle applications that use host:port only. This will simplify multi-host implementation for memcache client, dovecot client, and other. dict_memcache: treat "bad" key as cache miss, i.e. read/write the backup database as if the cache did not exist. This does not help because most Postfix maps (virtual, canonical, access, transport, ...) also don't support spaces in keys. postscreen: keep the cache open after "postfix reload" when it is remote (type memcache: or proxy:). This does not work because memcache can use a non-proxied file as backup). What is the feasibility of adding an mta_name (personality) attribute that is propagated via queue files and delivery agent requests? It would default to myhostname. Major performance improvement opportunity (that is until everyone runs Postfix queues on SSDs). Investigate the viability of a daemon that produces incoming and postdrop queue files on request (in reality it would maintain a limited queue of "spare" files). Central queue file allocation reduces the I/O performance disadvantage that qmgr has when 100 smtpd processes are receiving mail, or when lots of mail is submitted with the sendmail command line. When an smtpd process accepts MAIL FROM, a cleanup daemon requests a queue file and receives a queue ID + file handle from the queue file daemon. If the queue file daemon is down, the cleanup daemon creates the file itself like it does now; this can be hidden in the mail_stream library module. If the mail transaction is aborted, then the cleanup daemon gives the queue file back to the queue file daemon's "spare" file pool, saving most of the overhead of creating and deleting a queue file (the file would still need to be renamed at the start of the next mail transaction). If the cleanup daemon is unable to give a file back, then it can delete the file like it does now; this can be hidden in the mail_stream library module. The whole thing can be transparently added to Postfix by adding calls to a queue-file-service client to the mail_queue_enter() and mail_queue_remove() library routines. Other advantages: 1) negligible performance hit when queue file allocation happens earlier, so that logging and milters have a queue ID for the whole transaction not just the first valid recipient; 2) by not removing every queue files we get most of the performance gain of a queue based on append/truncate instead of the much more expensive create/delete. Investigate viability of Sendmail dns maps. Make the rules for how to use close-on-exec more explicit. Provide separate timeout control for dict_proxy client, rewrite client, resolve client, cleanup client, and so on. Perhaps a timeout argument to the mail_connect() routines. Trick from amavisd: save listen socket/fifo/etc state, clear their close-on-exec flags, exec the same program file to re-initialize (with saved socket state on command line or in environment), then restore the listen socket/fifo/etc close-on-exec flags. This could be a way to mitigate the impact of memory/file leaks, and to implement "postfix reload" support for master(8) features that currently don't support this. Sub-second time resolution. The first benefit is to make per-destination rate delays more usable. Other applications will come up once the support exists. The straightforward approach is to represent all time intervals in milliseconds, and to update all code that makes system calls with a time argument (as well as the compiled-in upper and lower time parameter bounds, which are currently in seconds). Unfortunately, that limits he maximum time interval to less than 25 days on 32-bit systems, and is likely to break compatibility (for starters, it cannot even deal with the compiled-in 100d upper bound on the queue file lifetime). A second option is to have a "compatibility" time base switch between milliseconds and seconds; this means extra changes to all code that makes system calls with a time argument, and the way that the compiled-in upper and lower bounds are specified. Some of this can be encapsulated in macros like time_to_sec(t), time_to_msec(t) and sec_to_time(t). Finally, it is relatively easy to replace the events(3) interface to use "double" for the time delay arguments, but it is a major pain to convert all main.cf time parameters into doubles (converting only some leads to a documentation nightmare). Address verify cache: allow a negative cache "refresh" result to purge a "positive" cache entry in some safe manner. Currently, the negative cache "refresh" result is discarded, address verify cache lookup returns OK, and each lookup forces a "refresh" probe until the entry expires. Some Sendmail configurations trigger sub-optimal behavior when the postscreen_whitelist_interfaces parameter lists primary MX addresses only. When postscreen's "deep protocol tests" are successful on the primary MX address (i.e. they result in 4XX responses to RCPT TO), some Sendmail configurations keep the primary MX connection open until AFTER they finish talking to the backup MX address. The problem is that the backup connection runs into a WHITELIST VETO condition because the whitelisting database has not yet been updated with the PASS NEW result for the primary MX connection. Unfortunately postscreen can't update the whitelisting database before the primary MX connection is closed, because a client may still make a mistake. In the SMTP server, check if the connection is closed before replying to ".", and discard the message if the reply can't be sent. This reduces the time window for RFC 1047 message duplication, and may even prevent the delivery of some spam. http://www.exim.org/lurker/message/20070416.103159.9d5ff0ce.en.html This requires splitting the SMTP server's commit operation into two operations: first, a tentative commit operation that performs most of the I/O and processing in milters and in the cleanup server; second, a final commit operation that is executed only if the remote SMTP client hasn't hung up in the mean time. Unfortunately, SMTP-based before-queue content filters don't support a tentative commit operation. Find out how to reproduce Berkeley DB bogus ENOENT errors. postscreen does not log this with Berkeley DB 1 (FreeBSD 4..8), 4.7.25 (Ubuntu 9.04) and 4.8.24 (Ubuntu 10.04). postconf command-line option to show the compile-time settings (CCARGS, AUXLIBS) in case binary packages don't install the makedefs.out file. events.c: cache the side effects of file descriptor event enable/disable operations in user space, and do bulk kernel updates at event_loop() time. This can eliminate costly system calls with successive event disable/enable operations on the same file descriptor. This can also eliminate the need for tricky code that tries to avoid the expense of successive disable/enable operations. Such code is likely to introduce bugs. When does it pay off to send domains in the active queue to a DNS prefetch daemon? Could this generalize to a dynamic transport map that piggy-backs domains with the same MX host into the same mail delivery transaction? tlsproxy(8) should receive TLS preferences from postscreen(8) and smtpd(8), instead of reading them from main.cf. This means that many tlsproxy_ parameters become postscreen_ parameters, and that tls_server_init() parameters move to to tls_server_start(). That is a significant API change. It also means tlsproxy can't open all files before chroot(). anvil rate limit for sasl_username. Encapsulate nbbio buffer access and update by tlsproxy. Full-duplex support for tlsproxy(8). This requires updating events(3) and nbbio(3). Register automagic destructor for object attached to VSTREAM. Use different ipc time limits for email message transactions (smtpd, pickup)->cleanup and for quick query/reply transactions such as address rewriting/resolution. Beware of large time limits for local or virtual alias expansion. permit_tempfail_action (default: defer_if_reject) to be used as the default value for dnswl_tempfail_action and rhswl_tempfail_action. Steal liberally from the code that implements unverified_recipient_tempfail_action etc. Support filtering of messages that are generated by Postfix: This would apply to postmaster notices and bounce messages (DKIM), and address verification (BATV). Consistency: in postconf.proto make