From: Simon Schubert Date: Thu, 27 Aug 2009 11:52:43 +0000 (+0200) Subject: dma: factor out mail handling code X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=28be0b9645aae051c6fc0ac24bf185251e6b2011;p=people%2Fms%2Fdma.git dma: factor out mail handling code --- diff --git a/Makefile b/Makefile index 8d0c09f..42e0044 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ DPADD= ${LIBSSL} ${LIBCRYPTO} LDADD= -lssl -lcrypto PROG= dma -SRCS= base64.c conf.c crypto.c net.c dma.c aliases_scan.l aliases_parse.y spool.c local.c util.c +SRCS= aliases_parse.y aliases_scan.l base64.c conf.c crypto.c +SRCS+= dma.c local.c mail.c net.c spool.c util.c MAN= dma.8 BINOWN= root diff --git a/dma.c b/dma.c index ca9e9c1..bf22e8e 100644 --- a/dma.c +++ b/dma.c @@ -184,76 +184,6 @@ out: return (-1); } -static int -readmail(struct queue *queue, const char *sender, int nodot) -{ - char line[1000]; /* by RFC2822 */ - size_t linelen; - size_t error; - int had_headers = 0; - int had_from = 0; - int had_messagid = 0; - int had_date = 0; - - error = fprintf(queue->mailf, - "Received: from %s (uid %d)\n" - "\t(envelope-from %s)\n" - "\tid %s\n" - "\tby %s (%s)\n" - "\t%s\n", - username, getuid(), - sender, - queue->id, - hostname(), VERSION, - rfc822date()); - if ((ssize_t)error < 0) - return (-1); - - while (!feof(stdin)) { - if (fgets(line, sizeof(line), stdin) == NULL) - break; - linelen = strlen(line); - if (linelen == 0 || line[linelen - 1] != '\n') { - errno = EINVAL; /* XXX mark permanent errors */ - return (-1); - } - if (!had_headers) { - if (strprefixcmp(line, "Date:") == 0) - had_date = 1; - else if (strprefixcmp(line, "Message-Id:") == 0) - had_messagid = 1; - else if (strprefixcmp(line, "From:") == 0) - had_from = 1; - } - if (strcmp(line, "\n") == 0 && !had_headers) { - had_headers = 1; - while (!had_date || !had_messagid || !had_from) { - if (!had_date) { - had_date = 1; - snprintf(line, sizeof(line), "Date: %s\n", rfc822date()); - } else if (!had_messagid) { - /* XXX better msgid, assign earlier and log? */ - had_messagid = 1; - snprintf(line, sizeof(line), "Message-Id: <%s@%s>\n", - queue->id, hostname()); - } else if (!had_from) { - had_from = 1; - snprintf(line, sizeof(line), "From: <%s>\n", sender); - } - if (fwrite(line, strlen(line), 1, queue->mailf) != 1) - return (-1); - } - strcpy(line, "\n"); - } - if (!nodot && linelen == 2 && line[0] == '.') - break; - if (fwrite(line, strlen(line), 1, queue->mailf) != 1) - return (-1); - } - - return (0); -} - static struct qitem * go_background(struct queue *queue) { @@ -316,101 +246,6 @@ retit: exit(1); } -static void -bounce(struct qitem *it, const char *reason) -{ - struct queue bounceq; - struct qitem *bit; - char line[1000]; - size_t pos; - int error; - - /* Don't bounce bounced mails */ - if (it->sender[0] == 0) { - syslog(LOG_INFO, "can not bounce a bounce message, discarding"); - exit(1); - } - - LIST_INIT(&bounceq.queue); - if (add_recp(&bounceq, it->sender, "", 1) != 0) - goto fail; - - if (newspoolf(&bounceq, "") != 0) - goto fail; - - syslog(LOG_ERR, "delivery failed, bouncing as %s", bounceq.id); - setlogident("%s", bounceq.id); - - error = fprintf(bounceq.mailf, - "Received: from MAILER-DAEMON\n" - "\tid %s\n" - "\tby %s (%s)\n" - "\t%s\n" - "X-Original-To: <%s>\n" - "From: MAILER-DAEMON <>\n" - "To: %s\n" - "Subject: Mail delivery failed\n" - "Message-Id: <%s@%s>\n" - "Date: %s\n" - "\n" - "This is the %s at %s.\n" - "\n" - "There was an error delivering your mail to <%s>.\n" - "\n" - "%s\n" - "\n" - "%s\n" - "\n", - bounceq.id, - hostname(), VERSION, - rfc822date(), - it->addr, - it->sender, - bounceq.id, hostname(), - rfc822date(), - VERSION, hostname(), - it->addr, - reason, - config->features & FULLBOUNCE ? - "Original message follows." : - "Message headers follow."); - if (error < 0) - goto fail; - - if (fseek(it->mailf, it->hdrlen, SEEK_SET) != 0) - goto fail; - if (config->features & FULLBOUNCE) { - while ((pos = fread(line, 1, sizeof(line), it->mailf)) > 0) { - if (fwrite(line, 1, pos, bounceq.mailf) != pos) - goto fail; - } - } else { - while (!feof(it->mailf)) { - if (fgets(line, sizeof(line), it->mailf) == NULL) - break; - if (line[0] == '\n') - break; - if (fwrite(line, strlen(line), 1, bounceq.mailf) != 1) - goto fail; - } - } - - if (linkspool(&bounceq, "") != 0) - goto fail; - /* bounce is safe */ - - delqueue(it); - - bit = go_background(&bounceq); - deliver(bit); - /* NOTREACHED */ - -fail: - syslog(LOG_CRIT, "error creating bounce: %m"); - delqueue(it); - exit(1); -} - static void deliver(struct qitem *it) { @@ -462,7 +297,7 @@ bounce: /* NOTREACHED */ } -static void +void run_queue(struct queue *queue) { struct qitem *it; @@ -509,7 +344,6 @@ int main(int argc, char **argv) { char *sender = NULL; - struct qitem *it; struct queue queue; struct queue lqueue; int i, ch; @@ -674,8 +508,7 @@ skipopts: if (config->features & DEFER) return (0); - it = go_background(&queue); - deliver(it); + run_queue(&queue); /* NOTREACHED */ return (0); diff --git a/dma.h b/dma.h index 70e5f03..04cd28e 100644 --- a/dma.h +++ b/dma.h @@ -175,6 +175,7 @@ int base64_decode(const char *, void *); /* dma.c */ int add_recp(struct queue *, const char *, const char *, int); +void run_queue(struct queue *); /* spool.c */ int newspoolf(struct queue *, const char *); @@ -187,6 +188,10 @@ void dropspool(struct queue *, struct qitem *); /* local.c */ int deliver_local(struct qitem *, const char **errmsg); +/* mail.c */ +void bounce(struct qitem *, const char *); +int readmail(struct queue *, const char *, int); + /* util.c */ const char *hostname(void); void setlogident(const char *, ...); diff --git a/mail.c b/mail.c new file mode 100644 index 0000000..d11f465 --- /dev/null +++ b/mail.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2008 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Simon 'corecode' Schubert . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include "dma.h" + +void +bounce(struct qitem *it, const char *reason) +{ + struct queue bounceq; + char line[1000]; + size_t pos; + int error; + + /* Don't bounce bounced mails */ + if (it->sender[0] == 0) { + syslog(LOG_INFO, "can not bounce a bounce message, discarding"); + exit(1); + } + + LIST_INIT(&bounceq.queue); + if (add_recp(&bounceq, it->sender, "", 1) != 0) + goto fail; + + if (newspoolf(&bounceq, "") != 0) + goto fail; + + syslog(LOG_ERR, "delivery failed, bouncing as %s", bounceq.id); + setlogident("%s", bounceq.id); + + error = fprintf(bounceq.mailf, + "Received: from MAILER-DAEMON\n" + "\tid %s\n" + "\tby %s (%s)\n" + "\t%s\n" + "X-Original-To: <%s>\n" + "From: MAILER-DAEMON <>\n" + "To: %s\n" + "Subject: Mail delivery failed\n" + "Message-Id: <%s@%s>\n" + "Date: %s\n" + "\n" + "This is the %s at %s.\n" + "\n" + "There was an error delivering your mail to <%s>.\n" + "\n" + "%s\n" + "\n" + "%s\n" + "\n", + bounceq.id, + hostname(), VERSION, + rfc822date(), + it->addr, + it->sender, + bounceq.id, hostname(), + rfc822date(), + VERSION, hostname(), + it->addr, + reason, + config->features & FULLBOUNCE ? + "Original message follows." : + "Message headers follow."); + if (error < 0) + goto fail; + + if (fseek(it->mailf, it->hdrlen, SEEK_SET) != 0) + goto fail; + if (config->features & FULLBOUNCE) { + while ((pos = fread(line, 1, sizeof(line), it->mailf)) > 0) { + if (fwrite(line, 1, pos, bounceq.mailf) != pos) + goto fail; + } + } else { + while (!feof(it->mailf)) { + if (fgets(line, sizeof(line), it->mailf) == NULL) + break; + if (line[0] == '\n') + break; + if (fwrite(line, strlen(line), 1, bounceq.mailf) != 1) + goto fail; + } + } + + if (linkspool(&bounceq, "") != 0) + goto fail; + /* bounce is safe */ + + delqueue(it); + + run_queue(&bounceq); + /* NOTREACHED */ + +fail: + syslog(LOG_CRIT, "error creating bounce: %m"); + delqueue(it); + exit(1); +} + +int +readmail(struct queue *queue, const char *sender, int nodot) +{ + char line[1000]; /* by RFC2822 */ + size_t linelen; + size_t error; + int had_headers = 0; + int had_from = 0; + int had_messagid = 0; + int had_date = 0; + + error = fprintf(queue->mailf, + "Received: from %s (uid %d)\n" + "\t(envelope-from %s)\n" + "\tid %s\n" + "\tby %s (%s)\n" + "\t%s\n", + username, getuid(), + sender, + queue->id, + hostname(), VERSION, + rfc822date()); + if ((ssize_t)error < 0) + return (-1); + + while (!feof(stdin)) { + if (fgets(line, sizeof(line), stdin) == NULL) + break; + linelen = strlen(line); + if (linelen == 0 || line[linelen - 1] != '\n') { + errno = EINVAL; /* XXX mark permanent errors */ + return (-1); + } + if (!had_headers) { + if (strprefixcmp(line, "Date:") == 0) + had_date = 1; + else if (strprefixcmp(line, "Message-Id:") == 0) + had_messagid = 1; + else if (strprefixcmp(line, "From:") == 0) + had_from = 1; + } + if (strcmp(line, "\n") == 0 && !had_headers) { + had_headers = 1; + while (!had_date || !had_messagid || !had_from) { + if (!had_date) { + had_date = 1; + snprintf(line, sizeof(line), "Date: %s\n", rfc822date()); + } else if (!had_messagid) { + /* XXX better msgid, assign earlier and log? */ + had_messagid = 1; + snprintf(line, sizeof(line), "Message-Id: <%s@%s>\n", + queue->id, hostname()); + } else if (!had_from) { + had_from = 1; + snprintf(line, sizeof(line), "From: <%s>\n", sender); + } + if (fwrite(line, strlen(line), 1, queue->mailf) != 1) + return (-1); + } + strcpy(line, "\n"); + } + if (!nodot && linelen == 2 && line[0] == '.') + break; + if (fwrite(line, strlen(line), 1, queue->mailf) != 1) + return (-1); + } + + return (0); +}