From: Julio Sánchez Fernández Date: Fri, 7 Apr 2000 15:00:22 +0000 (+0000) Subject: Added a method to make delivery to the local mailbox conditional on X-Git-Tag: LDBM_PRE_GIANT_RWLOCK~3114 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=36a4ed4f5938310d8f3f96ba449f997f120dfdfb;p=openldap 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. --- diff --git a/clients/mail500/main.c b/clients/mail500/main.c index 84bd0b2a19..38d0521ee3 100644 --- a/clients/mail500/main.c +++ b/clients/mail500/main.c @@ -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", @@ -1082,23 +1075,86 @@ url_list_search( * We should probably take MX records into account to cover all bases, * but really, routing belongs in the MTA. */ +static int +is_my_host( + char * host +) +{ + char **d; + + if ( d == NULL ) + return 0; + for ( d = myhosts; *d; d++ ) { + if ( !strcasecmp(*d,host) ) { + return 1; + } + } + return 0; +} + static int is_my_domain( - char * 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,domain) ) { + 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; jas_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';