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);
}