This file is a bit like DJB's THOUGHTS file. Here I write down what I think about some "features" and "bugs" in qmail (which one is a feature and which a bug differs from who you ask). 1. Local recipients qmail-smtpd should know if a local recipient exists if he sees the RCPT TO. qmail is very "secure" by meaning that there is little code that has root capabilities. Normally qmail-smtpd would have to do everything qmail-local does only to see if there is the recipient. Of course that's too much code. For me there are 2 possible ways to solve this: -create some sort of daemon that does all the magic. qmail-smtpd can ask it to tell if the user exists and qmail-local can get the delivery instruction from it. -use the vpopmail way (currently implemented in Qsmtpd): this only works for domains which are controlled by vpopmail. You also have to change vpopmail to create the domain and user (not the Maildir/!) directories readable for Qsmtpd (or qmail-smtpd). This only leaks information (to local users!) that are not that private: the existence of a mail user and it's filter settings. You can narrow this down by putting qmaild into group vpopmail (or a new group for this special purpose) and making the domain and user directories only readable to this group. Note: this change is needed for Qsmtpd anyway to allow Qsmtpd read the users filter config. You can circumwent this if you put all this information into some sort of database (e.g. LDAP). 2. Bounces I hate getting a bounce for every delivery that failed. It would be much nicer if qmail-send would collect the bounces to local recipients and return them all in one mail. For those local recipients that fail with a temporary error first it may send them later one by one but the recipients that fail at the first attempt with permanent error should be grouped together. Without looking into this deeper the code should something like this: repeat for all recipients do if (try_deliver fails) add error message to bounce else mark recipient as done if (bounce exists) deliver bounce until (all recipients are marked as done) This would also group together all bounces of local and remote deliveries of this queue run. 3. Remote deliveries I disagree with DJB about multiple recipient mails. IMHO a message to multiple recipients has to be delivered by a single transfer. I don't think qmail-send can handle this (but maybe I just don't understand this poorly documented code). The way I would do this is something like this: -qmail-send sees a message needs delivery. It calls qmail-lspawn for the local deliveries as usual. It calls qmail-rspawn (or it's successor) and tells him: a) the queue id (inode number) of the message to deliver and b) the maximum number of remote connections it may open at any time. For this qmail-send has to count the pending recipients in the file and calculate the minimum of pending recipients and free remote slots (concurrencyremote). The minimum number is passed to qmail-rspawn. If the remaining number of remote slots is 0 qmail-send will not schedule any more mails for remote delivery until at least one of this childs return. Note: There is a high possibility that qmail-rspawn will use less connections than the given number. Mails to multiple recipients at a single domain are not that rare. Using a bigger number for concurrentyremote is better here (with the possibility of a high network load if every message has only one recipients or every recipient has it's own MX). I would do it this way to keep the DNS lookups away from qmail-send. -qmail-rspawn will go through the recipient list. It will fork a qmail-remote (or better Qremote *g*) for every transfer, grouping mails to recipients at the same domain (this is simple) and the same primary MX (this is a bit more complicated, see below) together so they are sent only once through the network. This has some advantages: a) less network transfer b) less memory usage, CPU usage, latency and network transfer: fewer DNS lookups (by just comparing the recipent domains). This will give a small penalty of CPU cycles if there are many recipients at many different domains. c) less network latency: less TCP connections have to be established d) bounce messages can be grouped easier, at least all errors at the same host can go into a single bounce message. Some people say that if you try to deliver a mail to one MX and he gives a 5xx response the transfer has to be tried again at the other MXs. I think this is completely broken. I will not do it. If one host gives a 5xx the message will bounce (for this recipient). If a delivery fails with 4xx for all recipients and there is another MX this one will be tried. If there are multiple recipients and only some of them fail with 4xx (e.g. if there are too much recipients for a single transfer) they will be tried again at the next queue run. Grouping the transfers by DNS hosts is not that easy. It will require a multi- stage algorithmus looking a bit like this: -get MX entries for all domains involved. This may be limited to a reasonable small number of domains (e.g. 50) to save some memory and latency. -sort every MX list by priority -for all domains look if there are domains which share the same MX list, compact them into a single list (there are no differences in the delivery attempts to all this recipients). This helps to get the algorithm more effective. This group of domains will be called "one domain" in the following step. -while there are domains where no delivery attempt has been made: local variable: the list of domains for this MX. btw: primary MX = MX of the lowest (remaining) priority -take the first domain from the delivery list and add it to the local list. -look if one of their primary MXes is a primary MX for another domain. If it is, add this domain to the local list. -try to make a connection to this MX. Loop for all IP addresses of this host. -If there is a connection try to deliver the mail. If at least one recipient gets 2xx response remove this domains from list, try next domain. Write bounce information for all 5xx responses. If there are only 5xx and 4xx responses (or only 4xx) go to next step. Don't try recipients that got a 5xx at the other MXes. -If no connection can be established delete this host from _all_ MX lists. -If there is another MX of this priority clear the local domain list and start again. -if connection attempts to all MXes fail: remove this domain from list, will be retried at next queue run 4. SMTP Extensions to be supported by Qremote -STARTTLS (taken from the qmail patch) -SIZE (no cost for us but helps avoiding useless big transfers) -8BITMIME (really this time: if the remote mailer does not support it recode the mail). I agree that a mailer that is not 8 bit clean is broken, obsolete and ugly. But that's life. -CHUNKING: reduces the overhead of message recoding. All programs in the qmail package need to be fixed to use CRLF instead of bare LF when they generate or store messages (they should be fixed indipendently of this: RfC 2822 says lines MUST end with CRLF). 5. More fixes -see CHUNKING in previous section -qmail-queue must make sure that the messages do not contain lines longer than 1000 characters (or "sendmail" and qmail-inject must). Qsmtpd checks itself so that the main "problem" are the programs for local injection. Noone uses QMTP and friends ;)