Added a method to make delivery to the local mailbox conditional on

the presence of a certain value in some other attribute.  Used to
implement mailForwardingAddress both in addition to normal delivery
and excluding normal delivery, selectable entry by entry.  The model
is mailDeliveryOption in Netscape MS.  The implementation aims to
become more general, though.  Affects "search-with-filter", any
entry can potentially use a parameter, introduced with "param=".

Optimize the case where we have to copy the message to an address that
is served by the directory.  Formerly, we would have the MTA deal with
it and invoke mail500 again later.  This has necessitated loading the
list of domains that are solved by us with "domain".  A new definition,
"host", takes the role of the old "domain" that was the FQDN of our
host for routing loop avoidance.
This commit is contained in:
Julio Sánchez Fernández 2000-04-07 15:00:22 +00:00
parent 8d6808862f
commit 36a4ed4f59

View File

@ -108,20 +108,6 @@ typedef struct baseinfo {
/* to see if this should be searched */
} Base;
/*
* We should limit the search to objectclass=mailRecipient or
* objectclass=mailGroup.
*/
/*
Base base[] = {
{"dc=StlInter, dc=Net",
0, 0xff,
{"mail=%s", "mailAlternateAddress=%s", NULL}},
{NULL}
};
*/
Base **base = NULL;
char *sendmailargs[] = { MAIL500_SENDMAIL, "-oMrLDAP", "-odi", "-oi", "-f", NULL, NULL };
@ -157,6 +143,7 @@ typedef struct attr_semantics {
#define AS_KIND_MODERATOR 7
#define AS_KIND_ROUTE_TO_ADDR 8 /* Rewrite recipient address as */
#define AS_KIND_OWN_ADDR 9 /* RFC822 name of this entry */
#define AS_KIND_DELIVERY_TYPE 10 /* How to deliver mail to this entry */
AttrSemantics **attr_semantics = NULL;
int current_priority = 0;
@ -168,7 +155,11 @@ typedef struct subst {
char **groupclasses = NULL;
char **def_attr = NULL;
char **mydomains = NULL; /* FQDNs not to route elsewhere */
char **myhosts = NULL; /* FQDNs not to route elsewhere */
char **mydomains = NULL; /* If an RFC822 address points to one
of these domains, search it in the
directory instead of returning it
to hte MTA */
static void load_config( char *filespec );
static void split_address( char *address, char **localpart, char **domainpart);
@ -218,7 +209,7 @@ main ( int argc, char **argv )
while ( (i = getopt( argc, argv, "d:C:f:h:l:m:v:" )) != EOF ) {
switch( i ) {
case 'd': /* turn on debugging */
debug = atoi( optarg );
debug |= atoi( optarg );
break;
case 'C': /* path to configuration file */
@ -552,8 +543,9 @@ add_attr_semantics( char *s )
as->as_syntax = AS_SYNTAX_DN;
} else if ( !strcasecmp( p, "url" ) ) {
as->as_syntax = AS_SYNTAX_URL;
} else if ( !strncasecmp( p, "search-with-filter=", 19 ) ) {
} else if ( !strcasecmp( p, "search-with-filter" ) ) {
as->as_syntax = AS_SYNTAX_BOOL_FILTER;
} else if ( !strncasecmp( p, "param=", 6 ) ) {
q = strchr( p, '=' );
if ( q ) {
p = q + 1;
@ -568,10 +560,6 @@ add_attr_semantics( char *s )
as->as_param = strdup( p );
p = q;
}
} else {
syslog( LOG_ALERT,
"Missing filter in %s", s );
exit( EX_TEMPFAIL );
}
} else if ( !strcasecmp( p, "host" ) ) {
as->as_kind = AS_SYNTAX_HOST;
@ -591,6 +579,8 @@ add_attr_semantics( char *s )
as->as_kind = AS_KIND_REQUEST;
} else if ( !strcasecmp( p, "owner" ) ) {
as->as_kind = AS_KIND_OWNER;
} else if ( !strcasecmp( p, "delivery-type" ) ) {
as->as_kind = AS_KIND_DELIVERY_TYPE;
} else {
syslog( LOG_ALERT,
"Unknown semantics word %s", p );
@ -667,6 +657,9 @@ load_config( char *filespec )
} else if ( !strncmp(line, "domain", p-line) ) {
p += strspn(p, " \t");
add_single_to( &mydomains, p );
} else if ( !strncmp(line, "host", p-line) ) {
p += strspn(p, " \t");
add_single_to( &myhosts, p );
} else {
syslog( LOG_ALERT,
"Unparseable config definition at line %d",
@ -1083,22 +1076,85 @@ url_list_search(
* but really, routing belongs in the MTA.
*/
static int
is_my_domain(
char * domain
is_my_host(
char * host
)
{
char **d;
if ( d == NULL )
return 0;
for ( d = mydomains; *d; d++ ) {
if ( !strcasecmp(*d,domain) ) {
for ( d = myhosts; *d; d++ ) {
if ( !strcasecmp(*d,host) ) {
return 1;
}
}
return 0;
}
static int
is_my_domain(
char * address
)
{
char **d;
char *p;
if ( d == NULL )
return 0;
p = strchr( address, '@' );
if ( p == NULL)
return 0;
for ( d = mydomains; *d; d++ ) {
if ( !strcasecmp(*d,p+1) ) {
return 1;
}
}
return 0;
}
static void
do_addresses(
char **addresses,
char ***to,
int *nto,
Group ***togroups,
int *ngroups,
Error **err,
int *nerr,
int type
)
{
int i, j;
int n;
/*
* Well, this is tricky, every address in my_addresses will be
* removed from the list while we shift the other values down
* and we do it in a single scan of the address list and
* without using additional memory. We are going to be
* modifying the value list in a way that the later
* ldap_value_free works.
*/
j = 0;
for ( i = 0; addresses[i]; i++ ) {
if ( is_my_domain(addresses[i]) ) {
do_address( addresses[i], to, nto, togroups, ngroups,
err, nerr, type );
ldap_memfree( addresses[i] );
} else {
if ( j < i ) {
addresses[j] = addresses[i];
}
j++;
}
}
addresses[j] = NULL;
if ( addresses[0] ) {
add_to( to, nto, addresses );
}
}
/*
* The entry engine processes an entry. Normally, each entry will resolve
* to one or more values that will be added to the 'to' argument. This
@ -1136,6 +1192,8 @@ entry_engine(
int needs_mta_routing = 0;
char **own_addresses = NULL;
int own_addresses_total = 0;
char **delivery_types = NULL;
int delivery_types_total = 0;
char *nvals[2];
for ( i=0; attr_semantics[i] != NULL; i++ ) {
@ -1166,7 +1224,9 @@ entry_engine(
break;
switch ( as->as_syntax ) {
case AS_SYNTAX_RFC822:
add_to( current_to, current_nto, vals );
do_addresses( vals, current_to, current_nto,
togroups, ngroups, err, nerr,
USER );
resolved = 1;
break;
case AS_SYNTAX_RFC822_EXT:
@ -1179,8 +1239,18 @@ entry_engine(
* We used to send a copy to the vacation host
* if onVacation to uid@vacationhost
*/
add_to( current_to, current_nto, vals );
resolved = 1;
if ( as->as_param ) {
for ( j=0; j<delivery_types_total; j++ ) {
if ( !strcasecmp( as->as_param, delivery_types[j] ) ) {
add_to( current_to, current_nto, vals );
resolved = 1;
break;
}
}
} else {
add_to( current_to, current_nto, vals );
resolved = 1;
}
break;
case AS_SYNTAX_DN:
@ -1284,7 +1354,7 @@ entry_engine(
break;
case AS_KIND_ROUTE_TO_HOST:
if ( !is_my_domain( vals[0] ) ) {
if ( !is_my_host( vals[0] ) ) {
cur_priority = as->as_priority;
if ( as->as_syntax == AS_SYNTAX_PRESENT ) {
needs_mta_routing = 1;
@ -1312,6 +1382,11 @@ entry_engine(
cur_priority = as->as_priority;
break;
case AS_KIND_DELIVERY_TYPE:
add_to( &delivery_types, &delivery_types_total, vals );
cur_priority = as->as_priority;
break;
default:
syslog( LOG_ALERT,
"Invalid kind %d", as->as_kind );
@ -1380,6 +1455,9 @@ entry_engine(
if ( own_addresses ) {
ldap_value_free( own_addresses );
}
if ( delivery_types ) {
ldap_value_free( delivery_types );
}
return( resolved );
}
@ -1429,7 +1507,6 @@ do_address(
int type
)
{
struct timeval timeout;
char *localpart = NULL, *domainpart = NULL;
char *synthname = NULL;
int resolved;
@ -1454,8 +1531,6 @@ do_address(
if ( synthname[i] == '.' || synthname[i] == '_' )
synthname[i] = ' ';
}
timeout.tv_sec = MAIL500_TIMEOUT;
timeout.tv_usec = 0;
substs[0].sub_char = 'm';
substs[0].sub_value = name;
substs[1].sub_char = 'h';