On Sun, 2 Nov 2003, Michael Bagnall wrote:

> I agree with your theory - but the reality is (and I know because I've
> been involved in it in a current project) what do you do with the
> donations?

You can do what I did.  I work for an ISP that is rolling out vpopmail.
Since 90% of our users will be dealing mainly with sqwebmail, I don't want
them needing to know anything about qmailadmin, with it's wildly different
look and feel.  There was already some work on this front; there is a
password change plugin for squirrelmail and a SA settings plugin.  But I
wanted some additional qmailadmin functions there, namely vacation,
forward, and SA enable.

Attached is a program that I paid out of pocket for and which I am giving
to Tom and friends to do what they will with it.  It's a command-line tool
that allows all of the above to be set/unset.  On it's own it doesn't do
much, but once I build a plugin for Squirrelmail that can call it with an
email address, I'll have all the per-user qmailadmin functions inside my
webmail interface.  I intend to contribute that when it's done as well.

If anyone wants any details on the attached file, let me know, or start a
new thread.

So in short, it's simple.  If you have money to spend, call up a friend
that codes C for a living, give them the parameters for what you need
developed or fixed, and pay them.  Contribute that code back to the
project, and you've made a donation.  Simple.  It fixes your issue and it
builds the codebase.  There are plenty of people that are good C coders
out there that wouldn't mind being paid for some work.

This project was quite cheap, but for me, and eventually for other
vpopmail/squirrelmail users well worth it I hope.

Thanks,

Charles

> Thanks;
>
> Michael R. Bagnall
> Powertools Productions, LLC.
> [EMAIL PROTECTED]
> 615.453.1141 / 800.444.1563
> http://www.powertools.net
>
>
> On Nov 2, 2003, at 7:36 AM, Eero Volotinen wrote:
>
> >> This is an open source project.... there really *is* no place to send
> >> donations that I am aware... there have been dozens of contributors to
> >> the source code and other parts (localization, etc).
> >
> > Well, there should be some place to where people can send money using
> > paypal/visa. Lets say amounts from 10e to 1000e.
> >
> > Short calculation:
> >
> > 10e * 1000 (donators) = 1000e this can speed up development. There are
> > very many vpopmail/qmailadmin users in the world.
> >
> > Coding takes time and time is money.
> >
> > --
> > Eero
> >
> >
>
>
>
/*
 * AUTHOR: [EMAIL PROTECTED]
 *
 * COPYRIGHT: Do whatever you want with this. Please send me bug fixes
 * or enhancements. This software has NO WARRANTEE, EXPRESS OR IMPLIED AND
 * IS NOT SUITABLE FOR ANY PURPOSE WHATSOEVER. USE IT AT YOUR OWN HAZARD.
 * If it screws up, look in the mirror.
 *
 * ADVICE: This program _could_ (remember, it is not suitable for any purpose)
 * be run setuid vpopmail, or whatever user owns your mail domains,
 * to allow editing of .qmail files.
 *
 * FEATURES: Read and write .qmail files and vacation messages. It will not
 * do transactional updates (incremental option changes). Whatever is specified
 * will be used to fully set the .qmail file. Use the read function to find out
 * what is already set in order to re-feed options back in to make an
 * incremental change. To inhibit insanity, when the vacation message is being
 * read from stdin, it will only wait 10 seconds until aborting. No one wants
 * a script or CGI to hang because someone forgot to write the body. It will
 * still enable vacation, but without a message body.
 *
 * When it reads the current .qmail file to determine the current options,
 * it does an _exact_ string match for the various vpopmail ways of
 * enabling features. If you change the location of the vacation or spam 
 * program you will need to do it very exactly.
 *
 *
 */

/* compile instructions:
 *
 * gcc -I. -I/home/vpopmail/include     -g -O2 dotqmailedit.c -o dotqmailedit -L 
../vpopmail-5.3.24 -lvpopmail -lcrypt -L /usr/local/lib/mysql -lmysqlclient
 *
 */

#define DEBUGx

#define FORWARD         (1<<1)
#define VACATION        (1<<2)
#define SPAM            (1<<3)
#define COPY            (1<<4)
#define BLACKHOLE       (1<<5)
#define DISABLE         (1<<6)

#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#include "vpopmail.h"
#include "vpopmail_config.h"
#include "vauth.h"
#include "config.h"

#define FPRINT(c,s)     {fputs(c,s); fputc('\n',s);}

#define VACATION_COMMAND "vacation command"

struct user_strings {
  char forward[1024]; /* This may be used if a forward is used */
  char vsubject[1024]; /* This may be used if a vacation is set */

  char vacation[1024];
  char copy[1024];
  char spam[1024];
  char dot[1024];
  char delete[1024];
};

void
usage(void) {
  printf("Usage: dotqmailedit\n"
         "-b black hole\n"
         "-f {addr} forward\n"
         "-c copy to local Maildir\n"
         "-v {subject} set vacation autoresponder\n"
         "-d {domain} REQUIRED\n"
         "-u {user} REQUIRED\n"
         "-s turn on spam filter\n"
         "-x verbose\n"
         "-r read current .qmail\n"
         "-h help (this)\n\n");
  printf("When using -v, stdin will be read for the message body.\n"
         "When using -r, one line will be output with all flags for current 
settings\nseparated by tabs\n"
         "  If vacation is specified, the body will follow this first line.\n"
         "  Flags are:\n"
         "\tforward={forwarded address}\n"
         "\tvacation\n\tspam\n\tcopy\n\tblackhole\n\n");
}

int
read_current(struct vqpasswd *vpw, struct user_strings *us) {
  char linebuf[1024];
  FILE *fs;
  int llen=0;
  
  int rflag=0;

  fs = fopen(us->dot,"r");

  while ( fgets(linebuf,1024,fs) ) {
    if ( (llen=strlen(linebuf)) < 1 )
      continue;

    llen--;
    linebuf[llen]='\0';

#ifdef DEBUG
    printf(">%s<\n",linebuf);
#endif

    if ( strcmp(us->delete,linebuf) == 0 ) {
      rflag |= BLACKHOLE;
    }
    else if ( linebuf[0] == '&' ) {
      rflag |= FORWARD;
      bcopy(&linebuf[1],us->forward,llen-1);
    }
    else if ( strcmp(us->spam,linebuf) == 0 ) {
      rflag |= SPAM;
    }
    else if ( strcmp(us->copy,linebuf) == 0 ) {
      rflag |= COPY;
    }
    else if ( strcmp(us->vacation, linebuf) == 0 ) {
      rflag |= VACATION;
    }
  }
#ifdef DEBUG
  fprintf(stderr, "%d\n",rflag);
#endif

  return rflag;
}

void
print_current(int flags, struct user_strings *us, struct vqpasswd *vpw) {
  char NewBuf[256];
  FILE *fs;
  size_t len;

  if ( flags & FORWARD )
    printf("forward=%s\t",us->forward);
  if ( flags & VACATION )
    printf("vacation\t");
  if ( flags & SPAM )
    printf("spam\t");
  if (flags & COPY )
    printf("copy\t");
  if ( flags & BLACKHOLE )
    printf("blackhole\t");
  printf("\n");
  if ( flags & VACATION ) {
    snprintf(NewBuf,sizeof(NewBuf),"%s/vacation/message", vpw->pw_dir);
    if ( ! (fs=fopen(NewBuf,"r")) ) {
      printf("Open vacation message failed\n");
    }
    else {
      while ( ! feof(fs) ) {
        len=fread(NewBuf,sizeof(char),256,fs);
        fwrite(NewBuf,sizeof(char),len,stdout);
      }
      fclose(fs);
    }
  }
}

int
main(int argc, char **argv) {

  static char NewBuf[1024];
  struct vqpasswd *vpw=NULL;

  /* Flags */
  int aflag=0;
  int rflag=0;
  int fd;

  int verbose=0;
  int read_cur=0;
  int len;
  int nfds;

  char forward_s[1024];
  char user_s[1024];
  char domain_s[1024];
  char dotqmail[2048];
  char vacation_s[1024];

  FILE *fs;
  fd_set rset;
  struct timeval timeout;

  char c;

  struct user_strings us;

  bzero((void *)&us,sizeof(us));

  while ((c = getopt(argc,argv, "bf:Fcv:Vu:Dd:sSxhr")) != EOF )

    switch (c) {

    case 'h':
      usage();
      exit(0);
      break;

    case 'b':
      aflag |= BLACKHOLE;
      break;

    case 'D':
      /* To disable everything */
      aflag |= DISABLE;
      break;

    case 'f':
      aflag |= FORWARD;
      strncpy(forward_s,optarg,1024);
      break;

    case 'F':
      aflag &= ~FORWARD;
      break;

    case 'c':
      aflag |= COPY;
      break;
      
    case 'u':
      strncpy(user_s,optarg,1024);
      break;

    case 'd':
      strncpy(domain_s,optarg,1024);
      break;

    case 's':
      aflag |= SPAM;
      break;

    case 'v':
      aflag |= VACATION;
      strncpy(vacation_s,optarg,1024);
      break;

    case 'V':
      aflag &= ~ VACATION;
      break;

    case 'x':
      verbose=1;
      break;

    case 'r':
      read_cur=1;
      break;

    default:
      fprintf(stderr, "Argument failed: %c\n",c);
      exit(1);
      break;
    }

  if ( verbose )
    fprintf(stderr, "%s %s\n", user_s, domain_s);

  vpw = vauth_getpw(user_s,domain_s);

  if ( ! vpw ) {
    fprintf(stderr, "failed lookup of [EMAIL PROTECTED]",user_s, domain_s);
    vclose();
    exit(7);
  }

  if ( verbose )
    fprintf(stderr, "%s\n", vpw->pw_dir);

  /* Format user strings, used for comparisions and output */
  snprintf(us.vacation, 1024,
           "| %s/autorespond 86400 3 %s/vacation/message %s/vacation",
           AUTORESPOND_PATH, vpw->pw_dir, vpw->pw_dir );
  snprintf(us.copy, 1024, "%s/Maildir/", vpw->pw_dir);
  strncpy(us.spam,SPAM_COMMAND,1024);
  snprintf(us.dot, 1024,"%s/.qmail", vpw->pw_dir);
  snprintf(us.delete, 1024, "|%s/true delete", TRUE_PATH);

#ifdef DEBUG
  puts(us.vacation);
  puts(us.copy);
  puts(us.spam);
  puts(us.dot);
  puts(us.delete);
#endif

  rflag=read_current(vpw, &us);
  if ( read_cur ) {
    print_current(rflag,&us,vpw);
    exit(0);
  }

  if ( aflag & DISABLE) {
    unlink(us.dot);
  }

  if ( (aflag & VACATION) == 0 ) {
    /* delete any vacation directory */
    snprintf(NewBuf,sizeof(NewBuf),"%s/vacation", vpw->pw_dir);
    vdelfiles(NewBuf);
  }

  if ( aflag & BLACKHOLE ) {
    /* open the .qmail file */
    fs = fopen(us.dot,"w");

    /* for now we use /bin/true, eventually switch this to '# delete' */
    FPRINT(us.delete,fs);

    fclose(fs);
    exit(0);
  }

  /* Option: spamcheck+ no others */
  /* if the mail is to be checked for spam, rewrite the file with command */
  if ( (aflag & SPAM) == SPAM ) {
    fs = fopen(us.dot, "w+");
    FPRINT(us.spam,fs);
    fclose(fs);
  }
    
  /* Option: forward+ savecopy+ spamcheck+ */
  if ( aflag & FORWARD ) {
    fs = fopen(us.dot,"w+");

    /*
     * The original version allows up to 5 forwards in a single .qmail file
     * This is not a feature supported yet.
     */

    fprintf(fs,"&%s\n", forward_s);

    if ( aflag & COPY ) {
      if ( aflag & SPAM ) {
        FPRINT(us.spam,fs);
      } else {
        FPRINT(us.copy,fs);
      }
    } 
    fclose(fs);
  }

  /* Option: vacation+ spamcheck+ */
  if ( aflag & VACATION ) {
    /* make the vacation directory */
    snprintf(NewBuf,sizeof(NewBuf),"%s/vacation", vpw->pw_dir);
    mkdir(NewBuf, 0750);

    /* open the .qmail file */
    fs = fopen(us.dot,"w+");
    FPRINT(us.vacation,fs);

    /* save a copy for the user (if checking for spam, it will keep a copy)*/
    if( aflag & SPAM ) {
      FPRINT(us.spam,fs);
    } 
    else {
      FPRINT(us.copy,fs);
    }

    /* save the forward for vacation too */

    if ( aflag & FORWARD )
      fprintf(fs,"&%s\n", forward_s);

    fclose(fs);
    
    /* set up the message file */
    snprintf(NewBuf,sizeof(NewBuf),"%s/vacation/message", vpw->pw_dir);

    /* We are not going to wait forever, you'll see what I mean */

    if ( (fd = open(NewBuf, O_WRONLY|O_TRUNC|O_CREAT)) < 0 ) {
      fprintf(stderr, "Unable to open vacation file %s\n",NewBuf);
      vclose();
      exit(4);
    }

    len=snprintf(NewBuf,1024,"From: [EMAIL PROTECTED]: %s\n\n",
             user_s, domain_s, vacation_s);
    write(fd,NewBuf,len);

    timeout.tv_sec = 10;
    timeout.tv_usec = 0;

    FD_ZERO(&rset);
    FD_SET(0,&rset);
    
    while( (nfds=select(1,&rset,NULL,NULL,&timeout)) > 0 ) {
      /* No need to check rset since we only have one fd in there */
      if ( (len=read(0,NewBuf,1024)) == 0)
        break;

      write(fd,NewBuf,len);
      FD_SET(0,&rset);
    }
    close(fd);

    if ( nfds == 0 )
      fprintf(stderr, "Timeout reading vacation message from stdin. Aborted.\n");


  }

  vclose();
  exit(0);

}

Reply via email to