From: Martin Mares Date: Sun, 8 Jan 2006 12:03:38 +0000 (+0000) Subject: ... X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=f271fce07041cb7ddb7b83663d121043dd1c6405;p=maildups.git ... --- diff --git a/Makefile b/Makefile index 65127cc..6496a26 100644 --- a/Makefile +++ b/Makefile @@ -4,17 +4,19 @@ CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -W VERSION=0.1 YEAR=2006 -all: mdup +all: mdup smail mdup: mdup.o util.o sha1.o +smail: smail.o util.o mdup.o: mdup.c util.h +smail.o: smail.c util.h util.o: util.c util.h sha1.o: sha1.c util.h clean: rm -f `find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core` - rm -f mdup + rm -f mdup smail rm -rf maint/dist distclean: clean diff --git a/mdup.c b/mdup.c index 0d35541..877d375 100644 --- a/mdup.c +++ b/mdup.c @@ -216,7 +216,7 @@ parse_header_line(char *line, uns cnt, struct item *item) uns lul = strlen(local_user); if (!strcasecmp(rhs, local_domain) && !strncasecmp(lhs, local_user, lul) && - !strncasecmp(lhs+lul, "+md+", 4)) + !strncasecmp(lhs+lul, "+md-", 4)) { verb(1, "Detected local Message-ID"); item->timestamp = 2; diff --git a/smail.c b/smail.c new file mode 100644 index 0000000..c6cd754 --- /dev/null +++ b/smail.c @@ -0,0 +1,208 @@ +/* + * Sendmail Wrapper :) + * + * (c) 2006 Martin Mares + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" + +static char *local_user; +static char *local_domain; +static char *from_user; +static char *from_domain; + +static time_t now; +static struct tm *now_tm; + +static pid_t sm_pid; +static FILE *sm_fh; + +static void +start_sendmail(char **oargv, int oargc) +{ + char **argv = xmalloc(sizeof(char *) * (oargc+4)); + int argc = 0; + argv[argc++] = "/usr/sbin/sendmail"; + + char from[strlen(from_user) + strlen(from_domain) + 16]; + if (from_user) + { + sprintf(from, "%s+f-%04d%02d%02d@%s", from_user, now_tm->tm_year + 1900, now_tm->tm_mon + 1, now_tm->tm_mday, from_domain); + argv[argc++] = "-f"; + argv[argc++] = from; + verb(1, "Using -f %s", from); + } + + memcpy(argv+argc, oargv, sizeof(char *) * oargc); + argc += oargc; + argv[argc] = NULL; + + // for (uns i=0; argv[i]; i++) verb(2, "Option: <%s>", argv[i]); + + int pfd[2]; + if (pipe(pfd) < 0) + die("pipe failed: %m"); + + sm_pid = fork(); + if (sm_pid < 0) + die("fork failed: %m"); + if (!sm_pid) + { + dup2(pfd[0], 0); + close(pfd[0]); + close(pfd[1]); + execvp(argv[0], argv); + die("Cannot exec %s: %m", argv[0]); + } + close(pfd[0]); + sm_fh = fdopen(pfd[1], "w"); + if (!sm_fh) + die("fdopen() failed: %m"); + verb(1, "Forked pid %d for %s", sm_pid, argv[0]); +} + +static void +close_sendmail(void) +{ + if (ferror(sm_fh) || fclose(sm_fh)) + die("Error occured when writing to sendmail pipe"); + for (;;) + { + int st; + pid_t p = wait(&st); + if (p < 0) + die("wait failed: %m"); + if (p == sm_pid) + { + verb(1, "Subprocess %d finished with status 0x%x", p, st); + if (WIFEXITED(st)) + { + if (WEXITSTATUS(st)) + die("Sendmail process failed with exit code %d", WEXITSTATUS(st)); + return; + } + if (WIFSIGNALED(st)) + die("Sendmail process died on signal %d", WIFSIGNALED(st)); + die("Sendmail process died with unknown status 0x%x", st); + } + } +} + +static void +process_header(void) +{ + char hdr[1024]; + + for (;;) + { + if (!fgets(hdr, sizeof(hdr), stdin)) + die("Malformed mail headers: unexpected EOF"); + char *nl = strchr(hdr, '\n'); + if (!nl) + die("Malformed mail headers: line too long"); + if (hdr[0] == '\r' || hdr[0] == '\n') + break; + if (strncasecmp(hdr, "Message-ID:", 11)) + { + fputs(hdr, sm_fh); + *nl = 0; + } + } + + if (local_user) + { + char hostname[64]; + if (gethostname(hostname, sizeof(hostname))) + hostname[0] = 0; + else + hostname[sizeof(hostname)-1] = 0; + fprintf(sm_fh, "Message-ID: <%s+md-%04d%02d%02d.%02d%02d%02d.%d.%s@%s>\n", + local_user, + now_tm->tm_year + 1900, now_tm->tm_mon + 1, now_tm->tm_mday, + now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, + getpid(), hostname, + local_domain); + } + fputs("\n", sm_fh); +} + +static void +process_body(void) +{ + char buf[1024]; + int n; + while ((n = fread(buf, 1, sizeof(buf), stdin)) > 0) + fwrite(buf, 1, n, sm_fh); + if (n < 0) + die("Malformed mail body: %m"); +} + +static void NONRET +usage(void) +{ + fprintf(stderr, "Usage: smail [] -- \n\ +\n\ +Options:\n\ +-f@\tGenerate envelope sender address for easy identification of bounces\n\ +-l@\tAdd Message-ID for detection of messages looped back\n\ +-v\t\t\tIncrease verbosity\n\ +\n\ +MailDups " STR(VERSION) ", (c) " STR(YEAR) " Martin Mares \n\ +It can be freely distributed and used according to the GNU GPL v2.\n\ +"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int c; + while ((c = getopt(argc, argv, "f:l:v")) >= 0) + switch (c) + { + case 'f': + { + char *c = strchr(optarg, '@'); + if (!c) + usage(); + *c++ = 0; + from_user = optarg; + from_domain = c; + break; + } + case 'l': + { + char *c = strchr(optarg, '@'); + if (!c) + usage(); + *c++ = 0; + local_user = optarg; + local_domain = c; + break; + } + case 'v': + verbose++; + break; + default: + usage(); + } + + now = time(NULL); + if (!(now_tm = gmtime(&now))) + die("gmtime() failed: %m"); + + start_sendmail(argv+optind, argc-optind); + process_header(); + process_body(); + close_sendmail(); + return 0; +}