I would like to propose a change on how "rcpt to" addresses are validated and messages are handled (expanded) and how queue modules know it needs to process this message. I would like to change rcpt_to in smtpd_trans_rec to apr_table_t. The key for the table will be the address sent to "rcpt to" command and the value will be a pointer to a apr_array_header_t list of pointers to the following structure: typedef struct smtpd_rctp_rec { apr_pool_t *p; const char *mode; int validated; const char *address; apr_table_t info; const char *expanded; } mode: what queue handler should handle this message. Example would be local, relay, relay_to, forward, postfix. validated: if the rctp has been validated and ready to process address: what address to send to info: extra data is stored that the queue handler might needed expanded: log of how the address was expanded mod_smtpd would create a hook for expanding rctp address which other modules will use to enable different ways to validate rcpt address and setting what queue module should process a message. It would take a smtpd_rctp_rec * and a apr_array_header_t * of things to add to add and return decline, ok or delete. HANDLER_DECLARE(rcpt) will create a smtpd_rctp_rec and run the expanding hook and handle the return value and also the things to be add. Here are a few example of how I think it would work. This will be using some modules that do not exists yet and some that do: mod_smtpd_user_pwd - handle validating local users and setting info on them mod_smtpd_alias - enables aliases (forwarding email) mod_smtpd_queue_local - handles the "local" mode Handles deliver of mail to local users mod_smtpd_queue_relay - handles the "relay" and "forward" modes This module would hook the expanding hook using APR_HOOK_LAST since it will allow forwarding and relaying for authenticated user, but wants to make sure all other modules have a chance to change the address if needed. mod_smtpd_queue_smtp - handles the "relay_to" mode Sends all mail to another server. This module would hook the expanding hook using APR_HOOK_FIRST since it want so to set every smtpd_rctp_rec mode to replay_to and doesn't care what other modules have to say. Examples: ________________________________________________________________________ ________ user@domain.tld -> user expand hook: { mode: NULL address: "user@domain.tld" validate: 0 info: { } expanded: NULL } mod_smtpd_user_pwd handles request and returns ok. It changes the struct to look like this: { mode: "local" address: "user@domain.tld" info: { "mail_box" -> "username" } validate: 1 expanded: "user@domain.tld -> local user username" } mod_smtpd_queue_local would handle queuing ________________________________________________________________________ ________ auth'ed user relaying mail to user@otherdomain.tld expand hook: { mode: NULL address: "user@otherdomain.tld" validate: 0 info: { } expanded: NULL } mod_smtpd_auth will handle this and returns ok. It changes the struct to look like this: { mode: "relay" address: "user@otherdomain.tld" info: { } validate: 1 expanded: "authenticated user relaying user@otherdomain.tld" } mod_smtpd_queue_relay would handle queuing ________________________________________________________________________ ________ user@domain.tld -> user@offsite.tld expand hook: { mode: NULL address: "user@domain.tld" info: { } validate: 0 expanded: NULL } mod_smtpd_alias would handle the request and return delete. It adds a new entry to the list that looks like this: { mode: "forward" address: "user@offsite.tld" info: { } validate: 0 expanded : "user@domain.tld -> user@offsite.tld" } expand hook call on the new entry: { mode: "forward" address: "user@offsite.tld" info: { } validate: 0 expanded : "user@domain.tld -> user@offsite.tld" } mod_smtpd_forward would handle the request and return ok. It would set the struct like this: { mode: "forward" address: "user@offsite.tld" info: { } validate: 1 expanded : "user@domain.tld -> user@offsite.tld" } mod_smtpd_queue_relay would handle queuing ________________________________________________________________________ ________ info@company.tld -> user1@company.tld -> user11@offsite.tld -> user2@company.tld -> local user user2 -> user3@company.tld -> user5@company.tld -> user55@offsite.tld expand hook: { mode: NULL address: "info@company.tld" info: { } validate: 0 expanded: NULL } mod_smtpd_alias would handle the request and return delete. It would add new entries to the list that looked like this: { mode: "forward" address: "user11@offsite.tld" info: { } validate: 0 expanded: "info@company.tld -> user11@offsite.tld" } { mode: "forward" address: "user2@company.tld" info { } validate: 0 expanded: "info@company.tld -> user2@company.tld" } { mode: "forward" address: "user3@company.tld" info { } validate: 0 expanded: "info@company.tld -> user3@company.tld" } expand hook on first new item: { mode: "forward" address: "user11@offsite.tld" info: { } validate: 0 expanded: "info@company.tld -> user11@offsite.tld" } mod_smtpd_forward would handle the request and return ok It would set the struct like this: { mode: "forward" address: "user11@offsite.tld" info: { } validate: 1 expanded: "info@company.tld -> user11@offsite.tld" } expand hook on second new item: { mode: "forward" address: "user2@company.tld" info { } validate: 0 expanded: "info@company.tld -> user2@company.tld" } mod_smtpd_user_pwd handles request and returns ok. It set the struct to look like this: { mode: "local" address: "user2@company.tld" info { "mail_box" -> "user2" } validate: 1 expanded : "info@company.tld -> user2@company.tld -> local user user2" } expand hook on third new item: { mode: "forward" address: "user3@company.tld" info { } validate: 0 expanded: "info@company.tld -> user3@company.tld" } mod_smtpd_alias would handle the request and return delete. It would add a new entry to the list that looked like this: add list: { mode: "forward" address: "user5@company.tld" info: { } validate: 0 expanded: "info@company.tld -> user3@company.tld -> user5@company.tld" } expand hook on third new new item: { mode: "forward" address: "user5@company.tld" info: { } validate: 0 expanded: "info@company.tld -> user3@company.tld -> user5@company.tld" } mod_smtpd_alias would handle the request and return delete. It would add a new entry to the list that looked like this: { mode: "forward" address: "user55@offsite.tld" info: { } validate: 0 expanded: "info@company.tld -> user3@company.tld -> user5@company.tld -> user55@offsite.tld" } expand hook on third new new new item: { mode: "forward" address: "user55@offsite.tld" info: { } validate: 0 expanded: "info@company.tld -> user3@company.tld -> user5@company.tld -> user55@offsite.tld" } mod_smtpd_forward would handle the request and return ok It would set the struct like this: { mode: "forward" address: "user55@offsite.tld" info: { } validate: 1 expanded: "info@company.tld -> user3@company.tld -> user5@company.tld -> user55@offsite.tld" } ------------------------------------------------------------------------ ----------------