]> git.sur5r.net Git - openldap/commitdiff
Added a method to make delivery to the local mailbox conditional on
authorJulio Sánchez Fernández <jsanchez@openldap.org>
Fri, 7 Apr 2000 15:00:22 +0000 (15:00 +0000)
committerJulio Sánchez Fernández <jsanchez@openldap.org>
Fri, 7 Apr 2000 15:00:22 +0000 (15:00 +0000)
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.

clients/mail500/main.c

index 84bd0b2a1903e2082671d68eec0247c4ec5f4ab2..38d0521ee3d6bda730397515cf0a9a40c8fb25e3 100644 (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",
@@ -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; 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';