Here is a patch to fix the operation of Qmail EXT in vdelivermail.c.  The QMAIL EXT 
option to vdelivermail.c is broken.  Here is a
description of the problem and the patch is included at the bottom of the Email and as 
an attachement.

The problem is that when Qmail-Ext is turned on vdelivermail takes ANY address with a 
'-' in it and removes the '-' and following
characters in the address.  This is not a correct implementation (at least not the way 
Qmail implements its variable envelope return
paths or extensions).  It should first try and deliver the message with the '-' in the 
address as given and if that fails then try
delivering it without the '-' and following characters.
Example delivery of [EMAIL PROTECTED] to illustrate problem

Current implementation:
attempts to deliver to [EMAIL PROTECTED]

Correct Implementation:
attempts to deliver to [EMAIL PROTECTED]
if it fails attempt to deliver to [EMAIL PROTECTED]


Please don't be alarmed by the size of the patch.  To implement QMAIL EXT properly I 
had to break some code off into separate
functions to keep from duplicating code.  The patch has been tested and compiled with 
QMAIL EXT on and off and with all test cases I
could think of.

Note to package maintainers:  I'm not sure what compilers and O/S's this package has 
to work on.  You could gain some performance by
declaring some of the functions in vdelivermail.c inline but of course this is not 
traditional or ANSI compatible and would be
guaranteed to work only with gcc (I think).  You may want to make the QMAIL-EXT turned 
on by default in autoconf as it is the
default behavior of standard qmail delivery.

BTW Big thanks to whomever fixed the exit codes in vchkpw.c from 4.10.28 to 4.10.29, I 
knew they were wrong but didn't know what
they were supposed to be.  Thanks!

-David Wartell
ActionWeb Services
http://www.actionwebservices.com


51a52,55
> #ifdef QMAIL_EXT
> char TheUserExt[AUTH_SIZE]; /* the User with '-' and following chars out if any */
> #endif
>
65c69
< int process_valias(char *user, char *domain);
---
> int process_valias(void);
75a80,81
> void checkuser(void);
> void usernotfound(void);
87,88d92
<  int ret;
<
94c98
<     if ( process_valias( TheUser, TheDomain) == 1 ) {
---
>     if ( process_valias() == 1 ) {
102,121c106,114
<
<         /* check if the account is locked and thier email
<          * should be bounced back
<          */
<       if (vpw->pw_gid & BOUNCE_MAIL ) {
<             printf("vdelivermail: account is locked email bounced %s@%s\n",
<                 TheUser, TheDomain);
<             vexit(100);
<         }
<
<         /* check for a .qmail file in thier Maildir
<          * If it exists, then deliver to the contents and exit
<          */
<         if ( check_forward_deliver(vpw->pw_dir) == 1 ) {
<             vexit(0);
<         }
<
<         snprintf(TheDir, AUTH_SIZE, "%s/Maildir/", vpw->pw_dir);
<         if ( deliver_mail(TheDir, vpw->pw_shell) != 0 ) {
<             vexit(100);
---
>         checkuser();
>     }
> #ifdef QMAIL_EXT
>     /* try and find user that matches the QmailEXT address if: no user found, */
>     /* and the QmailEXT address is different, meaning there was an extension */
>     else if ( strncmp(TheUser, TheUserExt, AUTH_SIZE) != 0 ) {
>         /* get the user from vpopmail database */
>         if ((vpw=vauth_getpw(TheUserExt, TheDomain)) != NULL ) {
>           checkuser();
123,163c116,117
<
<     /* the vpopmail user does not exist. Follow the rest of
<      * the directions in the .qmail-default file
<      */
<     } else {
<
<         /* If they want to delete email for non existant users
<          * then just exit 0. Qmail will delete the email for us
<          */
<         if ( strcmp(bounce, DELETE_ALL) == 0 ) {
<             /* just exit 0 and qmail will delete the email from the system */
<             vexit(0);
<
<         /* If they want to bounce the email back then
<          * print a message and exit 100
<          */
<         } else if ( strcmp(bounce, BOUNCE_ALL) == 0 ) {
<             printf("Sorry, no mailbox here by that name. vpopmail (#5.1.1)\n");
<
<             /* exit 100 causes the email to be bounced back */
<             vexit(100);
<
<         }
<
<         /* check if it is a path add the /Maildir/ for delivery */
<         if ( strstr( bounce, VPOPMAILDIR ) != 0 ) {
<             strcat( bounce, "/Maildir/");
<         }
<
<       ret = deliver_mail(bounce, "NOQUOTA" );
<
<         /* Send the email out, if we get a -1 then the user is over quota */
<         if ( ret == -1 ) {
<             printf("user is over quota, mail bounced\n");
<             vexit(100);
<         } else if ( ret == -2 ) {
<           printf("system error\n");
<           vexit(100);
<         } else if ( ret != 0 ) {
<           printf("mail is looping\n");
<           vexit(100);
---
>       else {
>           usernotfound();
165c119,122
<
---
>     }
> #endif
>     else {
>         usernotfound();
217c174,175
<     for(i=0;TheUser[i]!=0;++i) {
---
>     /* delete the '-' and following chars if any and store in TheUserExt */
>     for(i = 0; TheUser[i] != 0; i++) {
219d176
<             TheUser[i] = 0;
221a179,180
>
>         TheUserExt[i] = TheUser[i];
222a182,183
>
>     TheUserExt[i] = 0;
239c200
< int process_valias(char *user, char *domain)
---
> int process_valias(void)
245c206
<     tmpstr = valias_select( user, domain );
---
>     tmpstr = valias_select( TheUser, TheDomain );
259a221,242
>     #ifdef QMAIL_EXT
>     /* try and find alias that matches the QmailEXT address if: no alias found, */
>     /* and the QmailEXT address is different, meaning there was an extension */
>     if ( (!found) && ( strncmp(TheUser, TheUserExt, AUTH_SIZE) != 0 )  ) {
>         /* Get the first alias for this user@domain */
>         tmpstr = valias_select( TheUserExt, TheDomain );
>
>         /* tmpstr will be NULL if there are no more aliases */
>         while (tmpstr != NULL ) {
>
>             /* We found one */
>             found = 1;
>
>             /* deliver the mail */
>             deliver_mail(tmpstr, "NOQUOTA");
>
>             /* Get the next alias for this user@domain */
>             tmpstr = valias_select_next();
>         }
>     }
>     #endif
>
885a869,941
>
> }
>
>
> /*
>  * check for locked account
>  * deliver to .qmail file if any
>  * deliver to user if no .qmail file
>  */
> void checkuser() {
>     if (vpw->pw_gid & BOUNCE_MAIL ) {
>         printf("vdelivermail: account is locked email bounced %s@%s\n",
>             TheUser, TheDomain);
>         vexit(100);
>     }
>
>     /* check for a .qmail file in thier Maildir
>      * If it exists, then deliver to the contents and exit
>      */
>     if ( check_forward_deliver(vpw->pw_dir) == 1 ) {
>         vexit(0);
>     }
>
>     snprintf(TheDir, AUTH_SIZE, "%s/Maildir/", vpw->pw_dir);
>     if ( deliver_mail(TheDir, vpw->pw_shell) != 0 ) {
>         vexit(100);
>     }
> }
>
>
> /*
>  * the vpopmail user does not exist. Follow the rest of
>  * the directions in the .qmail-default file
>  */
> void usernotfound() {
>  int ret;
>
>     /* If they want to delete email for non existant users
>      * then just exit 0. Qmail will delete the email for us
>      */
>     if ( strcmp(bounce, DELETE_ALL) == 0 ) {
>         /* just exit 0 and qmail will delete the email from the system */
>         vexit(0);
>
>     /* If they want to bounce the email back then
>      * print a message and exit 100
>      */
>     } else if ( strcmp(bounce, BOUNCE_ALL) == 0 ) {
>         printf("Sorry, no mailbox here by that name. vpopmail (#5.1.1)\n");
>
>         /* exit 100 causes the email to be bounced back */
>         vexit(100);
>
>     }
>
>     /* check if it is a path add the /Maildir/ for delivery */
>     if ( strstr( bounce, VPOPMAILDIR ) != 0 ) {
>         strcat( bounce, "/Maildir/");
>     }
>
>     ret = deliver_mail(bounce, "NOQUOTA" );
>
>     /* Send the email out, if we get a -1 then the user is over quota */
>     if ( ret == -1 ) {
>         printf("user is over quota, mail bounced\n");
>         vexit(100);
>     } else if ( ret == -2 ) {
>         printf("system error\n");
>         vexit(100);
>     } else if ( ret != 0 ) {
>         printf("mail is looping\n");
>         vexit(100);
>     }

vdelivermail.c.QMAILEXT.4.10.29.patch

Reply via email to