openldap/clients/mail500
2000-08-21 04:40:25 +00:00
..
mail500.m4 Merge latest devel codes into releng 2 branch. 2000-06-13 19:56:15 +00:00
main.c Suck in latest from devel, mostly example/documentation changes 2000-08-21 04:40:25 +00:00
Make-template Initial revision 1998-08-09 00:43:13 +00:00
Makefile.in Merge latest devel codes into releng 2 branch. 2000-06-13 19:56:15 +00:00
README Suck in latest from devel, mostly example/documentation changes 2000-08-21 04:40:25 +00:00
sendmail.cf Merge latest devel codes into releng 2 branch. 2000-06-13 19:56:15 +00:00
Version.c Initial revision 1998-08-09 00:43:13 +00:00

This is the README file for mail500, a mailer that does directory
lookups via LDAP.  The name is historical and refers to X.500.

If you are planning to run mail500 at your site, there are several
things you will have to tailor in main.c:

	LDAPHOST - The host running an LDAP server

	base[] - The array telling mail500 where/how to search for
		things.  See the explanation below.

*** WHAT mail500 DOES: ***

mail500 is designed to be invoked as a mailer (e.g., from sendmail),
similar to the way /bin/mail works.  It takes a few required arguments
and then a list of addresses to deliver to.  It expects to find the
message to deliver on its standard input.  It looks up the addresses in
directory to figure out where to route the mail, and then execs sendmail
to do the actual delivery.  It supports simple aliases, groups, and
mailing lists, the details of which are given below.

*** HOW IT WORKS (from the sendmail side): ***

The idea is that you might have a rule like this in your sendmail.cf
file somewhere in rule set 0:

R$*<@example.com>$*	$#mail500$@example.com$:<$1>

This rule says that any address that ends in @example.com will cause the
mail500 mailer to be called to deliver the mail.  You probably also want
to do something to prevent addresses like uuhost!user@example.com or
user%host@example.com from being passed to mail500.  This can be done by
adding rules like this to rule set 9 where we strip off our local names:

R<@example.com>$*:$*                 $>10<@>$1:$2
R$+%$+<@example.com>                 $>10$1%$2<@>
R$+!$+<@example.com>                 $>10$1!$2<@>

See the sample sendmail.cf in this directory for more details.
For sendmail 8.9 (and later) users can use MAILER(mail500) if
mail500.m4 is placed within sendmail's cf/mailer directory.

The mail500 mailer should be defined similar to this in the
sendmail.cf file:

Mmail500, P=/usr/local/etc/mail500, F=DFMSmnXuh, A=mail500 -f $f -h $h -m $n@$w $u

This defines how mail500 will be treated by sendmail and what
arguments it will have when it's called.  The various flags specified
by the F=... parameter are explained in your local sendmail book (with
any luck).  The arguments to mail500 are as follows:

	-f	Who the mail is from.  This will be used as the address
		to which any errors should be sent (unless the address
		specifies a mailing list - see below).  Normally, sendmail
		defines the $f macro to be the sender.

	-h	The domain for which the mail is destined.  This is passed
		in to mail500 via the $h macro, which is set by the
		$@ metasymbol in the rule added to rule set 0 above.
		It's normally used when searching for groups.

	-m	The mailer-daemon address.  If errors have to be sent,
		this is the address they will come from.  $n is normally
		set to mailer-daemon and $w is normally the local host
		name.

The final argument $u is used to stand for the addresses to which to
deliver the mail.

*** HOW IT WORKS (from the mail500 side): ***

When mail500 gets invoked with one or more names to which to
deliver mail, it searches for each name in LDAP.  Where it searches,
and what kind(s) of search(es) it does are compile-time configurable
by changing the base array in main.c.  The configuration:

	Base    base[] =
		{ "ou=People, dc=example, dc=com", 0
			"uid=%s", "cn=%s", NULL,
		  "ou=System Groups, ou=Groups, dc=example, dc=com", 1
			"(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
		  "ou=User Groups, ou=Groups, dc=example, dc=com", 1
			"(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
		  NULL
		};

means that in delivering mail to "name" mail500 would do the
the following searches, stopping if it found anything at any step:

	Search (18) [2]: dc=com@dc=example@ou=People
	Search subtree (uid=name)
	Search (18) [3]: dc=com@dc=example@ou=People
	Search subtree (cn=name)

	Search (18) [4]: dc=com@dc=example@ou=Groups@ou=System Groups
	Search subtree & ((cn=name)(associatedDomain=OpenLDAP.org))

	Search (18) [5]: dc=com@dc=example@ou=Groups@ou=User Groups
	Search subtree & ((cn=name)(associatedDomain=example.com))

Notice that when specifying a filter %s is replaced by the name,
or user portion of the address while %h is replaced by whatever is
passed in to mail500 via the -h option (typically the host portion
of the address).

You can also specify whether you want search results that matched
because the entry's RDN matched the search to be given preference
or not.  We only give such preference in the mail group
portion of the searches.  Beware with this option:  the algorithm
used to decide whether an entry's RDN matched the search is very
simple-minded, and may not always be correct.

There is currently no limit on the number of areas searched (the base
array can be as large as you want), and an arbitrary limit of 2 filters
for each base.  If you want more than that, simply changing the 3 in
the typedef for Base should do the trick.

*** HOW IT WORKS (from the LDAP side): ***

In LDAP, there are several new attribute types and one new object
class defined that mail500 makes use of.  At its most basic, for normal
entries mail500 will deliver to the value(s) listed in the
rfc822Mailbox attribute of the entry.  For example, an entry has
the attribute

	mail: user@example.com

So mail sent to user@example.com will be delivered via mail500 to that
address.  If there were multiple values for the mail attribute, multiple
copies of the mail would be sent.

A new object class, rfc822MailGroup, and several new attributes have
been defined to handle email groups/mailing lists.  To use this, you
will need to add this to your local oidtable.oc:

	# object class for representing RFC 822 mailgroups
	rfc822MailGroup:        umichObjectClass.2 : \
		top : \
		cn : \
		rfc822Mailbox, member, memberOfGroup, owner, \
		errorsTo, rfc822ErrorsTo, requestsTo, rfc822RequestsTo,
		joinable, associatedDomain, \
		description, multiLineDescription, \
		userPassword, krbName, \
		telecommunicationAttributeSet, postalAttributeSet

And you will need to add these to your local oidtable.at:

	# attrs for rfc822mailgroups
	multiLineDescription:   umichAttributeType.2    : CaseIgnoreList
	rfc822ErrorsTo:         umichAttributeType.26   : CaseIgnoreIA5String
	rfc822RequestsTo:       umichAttributeType.27   : CaseIgnoreIA5String
	joinable:               umichAttributeType.28   : Boolean
	memberOfGroup:          umichAttributeType.29   : DN
	errorsTo:		umichAttributeType.30	: DN
	requestsTo:		umichAttributeType.31	: DN

The idea was to define a kind of hybrid mail group that could handle
people who were in LDAP or not.  So, for example, members of a group
can be specified via the member attribute (for LDAP members) or the
rfc822MailBox attribute (for non-LDAP members).  Similarly for the
errorsTo and rfc822ErrorsTo, and the requestsTo and rfc822RequestsTo
attributes.

To create a real mailing list, with a list maintainer, all you have to
do is create an rfc822MailGroup and fill in the errorsTo or
rfc822ErrorsTo attributes (or both).  That will cause any errors
encountered when delivering mail to the group to go to the addresses
listed (or LDAP entry via it's mail attribute).

If you fill in the requestsTo or rfc822RequestsTo (or both) attributes,
mail sent to groupname-request will be sent to the addresses listed
there.  mail500 does this automatically, so you don't have to explicitly
add the groupname-request alias to your group.

To allow users to join a group, there is the joinable flag.  If TRUE,
mail500 will search for entries that have a memberOfGroup attribute
equal to the DN of the group, using the same algorithm it used to find
the group in the first place (i.e. the DNs and filters listed in the
base array).  This allows people to join (or subscribe to) a group
without having to modify the group entry directly.  If joinable is
FALSE, the search is not done.

Finally, keep in mind that this is somewhat experimental at the moment.
We are using it in production at U-M, but your mileage may vary...