httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rian <r...@MIT.EDU>
Subject Re: mod_smtpd: handling rctp addresses
Date Tue, 04 Oct 2005 17:42:21 GMT
As far as an abstracted mechanism for informing queue modules what
recipients they are queue I like this approach, but before any major
changes are made to mod_smtpd I think this and other problems should be
concretely resolved.

Originally the idea was to treat each transaction as an atomic entity,
for simplicity and strictness to how the SMTP protocol. Also this is how
qpsmtpd works, and seems to work fine.

Now the idea is handling each recipient differently and subrequesting by
recipient. Either way, I think it's important to first look at how
mod_smtpd will be used and then create it's plugin architecture around
that.

For example it should be possible to run one queue module on a SMTP
server, and then arbitrarily add another as time goes on.

For instance you have a local delivery server, but then later you want
to forward mail for authenticated users. In the conf you should first
you should have:

-------

LoadModule smtpd_module *.so
LoadModule smtpd_queue_local *.so

# Conf directive handled in mod_smtpd_queue_local
SmtpdQueueLocalRcpts [A-Za-z0-9]+(\@mydomain.net)? 

-----------

Later you shoudl just be able to add:

-----------

LoadModule smtpd_queue_relay *.so

-----------

And the relay module would queue every other address not handled by
relay, assuming the connection was authenticated.

This implies that if all the queue modules are called for each of the
recipients, even after they are handled, there should be some metadata
coming with the recipient that says it has already been handled so relay
knows not to relay a message that has already been handled.

Or that once a address is handled, the hooks are stopped (RUN_ONCE) and
the next address is called on the queue hooks. Of course relay should be
a RUN_LAST hook.

What's more powerful? I think probably the first, because maybe a server
admin will want a recipient to be queued by two modules. This means
there should be some metadata with each recipient.

But wait! Earlier I gace an example about how a module should know what
recipients it's dealing with using a module specific directive. But what
if we did this:

-------

SmtpdQueueHandler regex:.*@foo.org regex:rian@apache.org, postfix relay
local
SmtpdQueueHandler mysql:/rcpttable.mysqlCONF, relay

-------------

These directives impose a recipient policy on all of mod_smtpd's
submodules. For something like this to work, it would require that each
rcpt is subrequested and has metadata associated with it (in this case,
queue handler name). I feel something like this is a lot better because
it minimizes configuration directives needed to be learned by server
admins and encourages code reuse (at least in recipient lists). In this
scheme mod_smtpd is responsible for assigning queue handlers to
recipients and all the queue handlers have to do is check whether or not
they are handlers of the recipient object.

So more and more Brian's proposal seems to make a lot of sense for
mod_smtpd, except maybe adding a 'queued' member.

I think the ultimate goal for mod_smtpd is as much code reuse as
possible so your proposal seems to fit in with that goal.

After lots of thought it seems the only criteria queueing will be based
on is recipients. Queuing based on other message characteristics (like
subject, who the message is from (ip and mail from)) or headers seem
more and more rare.
-rian

On Tue, 2005-10-04 at 09:23 -0500, Brian J. France wrote:
> 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 <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"
> 	}
> 
> ------------------------------------------------------------------------ 
> ----------------
> 

Mime
View raw message