This is a discussion on Re: [courier-users] hosteddomains and aliases capitalization within the Courier-Imap forums, part of the Mail Servers and Related category; This is a multi-part message in MIME format. --------------080907080602050203020303 Content-Type: text/plain; charset=ISO-8859-1; format=flowed ...
|
|||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
|
|||
|
This is a multi-part message in MIME format.
--------------080907080602050203020303 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit David Gomillion wrote: > charles uchu wrote: >> >> I think it is understood that based on the current code in courier that, >> even if there is an aliased domain set in hosteddomains, that you must >> again explicitly state this aliasing in the aliases file for addresses >> that are not mailboxes. > > To cut down on the confusion, I always recommend creating a hosted > domain, and then create actual mailboxes for each alias I want to > create. In it I create a .courier file to forward the mail where ever I > want it to go. That way one can trace which alias has been matched. Although technically it is a full blown mailbox, it would be unfair to count it as such for administrative purposes. > The ONLY aliases I create in the global alias file are > those required by the system (like root, postmaster, etc). However,it is annoying to maintain a bunch of aliases for each domain. I have a script structured more or less like so: LCLOCAL=`echo $LOCAL | tr '[A-Z]' '[a-z]'` case $LCLOCAL in webmaster|postmaster|admin|abuse|operator|sys|syst em|root) NEWADDR="me@my.domain";; *) NEWADDR="";; esac if [ "$NEWADDR" = "" ]; then case $HOST in domain1*) # per domain catchall policy...;; # ... esac fi if [ "$NEWADDR" = "" ]; then exit 64 fi printf "$NEWADDR\n" exit 0 > It's a little extra work, but in the end, I opt for simplicity and > maintainability. And it's very easy to script with bash... Yes. After some years spent trying to match rcptfilters with a dynamic delivery instruction calling the above script from .courier-default, I finally coded the attached replacement for maildropfilter to run the same script in either case. I'd propose to drop it in a miscellanea "contrib" directory, if Courier had one... --------------080907080602050203020303 Content-Type: text/plain; name="rcptfilter.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="rcptfilter.c" /* * rcptfilter.c - written by vesely in milan on 8 aug 2006 * * Run rcptfilter.sh * gcc -W -O -DNDEBUG -o /usr/local/sbin/rcptfilter rcptfilter.c * gcc -W -Wall -Wno-parentheses -O0 -g -o rcptfilter rcptfilter.c */ #define SCRIPTFILE "rcptfilter.sh" static char const usage[] = "usage:\n" "\trcptfilter -h\n" "\trcptfilter -D uid/gid -M rcptfilter[-ext] ...\n" "The first format is only useful to print this note.\n" "The second format is used by Courier's local output module if the\n" "maildropfilter configuration file contains the path of this executable.\n" "In this case, rcptfilter changes directory to HOME and looks for file\n" "\"" SCRIPTFILE "\" and runs it (with null input and output, logged error)\n" "and then returns an exit code of 0 if the script exits rc < 50, 1 otherwise.\n" "The script will have argument $1 set to \"RCPT\" and the other arguments\n" "set to whatever was passed to rcptfilter as ellipsis (...). The variables\n" "LOCAL and HOST will be set from ext. The rest of the environment remains."; #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <syslog.h> #include <ctype.h> #include <errno.h> #include <assert.h> static volatile int signal_child = 0, signal_timed_out = 0, signal_break = 0; static void sig_catcher(int sig) { #if !defined(NDEBUG) char buf[80]; unsigned s = snprintf(buf, sizeof buf, "rcptfilter[%d]: received signal %d\n", (int)getpid(), sig); if (s >= sizeof buf) { buf[sizeof buf - 1] = '\n'; s = sizeof buf; } write(2, buf, s); #endif switch(sig) { case SIGALRM: signal_timed_out = 1; break; case SIGHUP: case SIGPIPE: case SIGINT: case SIGQUIT: case SIGTERM: signal_break = 1; break; case SIGCHLD: signal_child = 1; break; default: break; } } #if 0 static void reset_signal(void) { struct sigaction act; memset(&act, 0, sizeof act); sigemptyset(&act.sa_mask); act.sa_handler = SIG_DFL; sigaction(SIGALRM, &act, NULL); sigaction(SIGPIPE, &act, NULL); sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); sigaction(SIGHUP, &act, NULL); sigaction(SIGCHLD, &act, NULL); } #endif static void set_signal(void) { struct sigaction act; memset(&act, 0, sizeof act); sigemptyset(&act.sa_mask); act.sa_handler = sig_catcher; sigaction(SIGALRM, &act, NULL); sigaction(SIGPIPE, &act, NULL); sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); sigaction(SIGHUP, &act, NULL); sigaction(SIGCHLD, &act, NULL); } static void addtoenv(char const *name, char const *value) { char *freeonexit = (char*)malloc(strlen(name) + strlen(value) + 1); if (freeonexit) putenv(strcat(strcpy(freeonexit, name), value)); } static int run_script(char const *ext, char *argv[], char const *home) { int rtc = 0; char *local = strdup(ext); if (local) { int err[2]; char *host = strchr(local, '@'); if (host) *host++ = 0; else host = ""; addtoenv("HOST=", host); addtoenv("LOCAL=", local); free(local); if (pipe(err) < 0) syslog(LOG_CRIT, "Cannot open pipe: %s\n", strerror(errno)); else { pid_t const pid = fork(); if (pid < 0) syslog(LOG_CRIT, "Cannot fork: %s\n", strerror(errno)); else if (pid) { char buf[2048], *next = &buf[0]; char *const first = &buf[0], *const last = &buf[sizeof buf - 2]; close(err[1]); alarm(30); last[1] = 0; // terminator on forced newline while (signal_timed_out == 0 && signal_break == 0 && signal_child == 0) { int rd = read(err[0], next, last - next); #if !defined NDEBUG printf("rd=%2d, next=%2d\n", rd, next - first); #endif if (rd > 0) { char *p = first, *br; next += rd; *next = next == last? '\n': 0; // force newline if full while ((br = strchr(p, '\n')) != NULL) { int level = LOG_CRIT; *br = 0; /* * e.g., "##This is a warning\n" */ while (*p == '#' && level < LOG_DEBUG) ++p, ++level; if (*p) syslog(level, "script: %s\n", p); p = br + (br < last); // +1 if not forced newline assert(first <= p && p <= next); } memmove(first, p, next - p); next -= p - first; assert(first <= next && next < last); } else if (rd == 0 || errno != EINTR && errno != EAGAIN) { if (rd) syslog(LOG_CRIT, "Pipe broken: %s\n", strerror(errno)); break; } } alarm(0); if (signal_timed_out || signal_break) { kill(pid, SIGTERM); } close(err[0]); for (;;) { int status; pid_t wpid = wait(&status); if (wpid < 0 && errno != EAGAIN && errno != EINTR) { syslog(LOG_CRIT, "Cannot wait %s/" SCRIPTFILE "[%u]: %s\n", home, (unsigned)wpid, strerror(errno)); break; } else if (wpid == pid) { if (WIFEXITED(status)) { int level, s_rtc = WEXITSTATUS(status); switch (s_rtc) { case 0: case 64: case 99: level = LOG_DEBUG; break; default: level = LOG_CRIT; break; } rtc = s_rtc > 50; syslog(level, "%s/" SCRIPTFILE " with %s exited %d, rtc=%d\n", home, ext, s_rtc, rtc); } else if (WIFSIGNALED(status)) { syslog(LOG_CRIT, "%s/" SCRIPTFILE " terminated with signal %d, rtc=%d\n", home, WTERMSIG(status), rtc); } else continue; // stopped? break; } } } else // child process { close(0); open("/dev/null", O_RDONLY); close(1); open("/dev/null", O_WRONLY); close(2); dup(err[1]); close(err[0]); close(err[1]); closelog(); execv(SCRIPTFILE, argv); syslog(LOG_MAIL|LOG_CRIT, "rcptfilter: cannot execv: %s\n", strerror(errno)); exit(0); } } } return rtc; } int main(int argc, char *argv[]) { int rtc = 0; int i, uid = 0, gid = 0, err = 0; char *ext = NULL, *home = getenv("HOME"); static char const argerror[] = "invoked with wrong argument: "; char *xargv[32]; size_t xargc = 0; openlog("rcptfilter", LOG_PID, LOG_MAIL); xargv[xargc++] = SCRIPTFILE; xargv[xargc++] = "RCPT"; for (i = 1; i < argc; ++i) { char *a = argv[i]; int pass_it = 1; if (*a == '-') { pass_it = 0; switch (*++a) { case 'D': if (i + 1 >= argc) { syslog(LOG_CRIT, "%s-D requires a value\n", argerror); ++err; } else { char *t = NULL; a = argv[++i]; uid = strtoul(a, &t, 10); if (t && *t == '/') { gid = strtoul(t + 1, &t, 10); if (t && *t) t = NULL; } else t = NULL; if (t == NULL) { syslog(LOG_CRIT, "%suidgid is %s\n", argerror, a); ++err; } } break; case 'M': if (i + 1 >= argc) { syslog(LOG_CRIT, "%s-M requires a value\n", argerror); ++err; } else if (strncmp(a = argv[++i], "rcptfilter" , sizeof "rcptfilter" - 1) != 0) { syslog(LOG_CRIT, "%s-M with value %s\n", argerror, a); ++err; } else { ext = strchr(a, '-'); if (ext) ++ext; else ext = ""; } break; case 'h': puts(usage); return 0; default: pass_it = 1; break; } } if (pass_it && xargc + 1 < sizeof xargv/ sizeof xargv[0]) { xargv[xargc++] = a; } } xargv[xargc] = NULL; if (geteuid() == 0 && (uid || gid)) { if (gid) setgid(gid); setuid(uid); } set_signal(); if (home && ext) { struct stat buf; uid_t const me = geteuid(); gid_t const myg = getegid(); if (chdir(home)) { syslog(LOG_CRIT, "Cannot chdir to %s: %s\n", home, strerror(errno)); } else if (stat(SCRIPTFILE, &buf) != 0) { if (errno != ENOENT) syslog(LOG_CRIT, "Cannot stat %s/" SCRIPTFILE ": %s\n", home, strerror(errno)); } else if (!S_ISREG(buf.st_mode) || !( ((S_IXUSR & buf.st_mode) && (me == 0 || me == buf.st_uid)) || ((S_IXGRP & buf.st_mode) && (me == 0 || myg == buf.st_gid)) || (S_IXOTH & buf.st_mode))) { syslog(LOG_INFO, "%s/" SCRIPTFILE " not executable by %d/%d\n", home, (int)me, (int)myg); } else { rtc = run_script(ext, xargv, home); } } else { syslog(LOG_CRIT, "%smissing %s%s%s\n", argerror, home ? "" : "HOME env variable", home || ext ? "" : " and ", ext ? "" : "-M argument"); } return rtc; } --------------080907080602050203020303 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=...057&dat=121642 --------------080907080602050203020303 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ courier-users mailing list courier-users@lists.sourceforge.net Unsubscribe: https://lists.sourceforge.net/lists/.../courier-users --------------080907080602050203020303-- |