int Brfc822date(Biobuf *b, Tm *tm) { char buf[64]; if(tm == nil) tm = localtime(time(nil)); rfc822date(buf, sizeof(buf), tm); return Bimapstr(b, buf); }
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); } bzero(&bounceq, sizeof(bounceq)); LIST_INIT(&bounceq.queue); bounceq.sender = ""; if (add_recp(&bounceq, it->sender, EXPAND_WILDCARD) != 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, 0, 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, int nodot, int recp_from_header) { struct parse_state parse_state; 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; int had_last_line = 0; int nocopy = 0; parse_state.state = NONE; 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, useruid, queue->sender, queue->id, hostname(), VERSION, rfc822date()); if ((ssize_t)error < 0) return (-1); while (!feof(stdin)) { if (fgets(line, sizeof(line) - 1, stdin) == NULL) break; if (had_last_line) errlogx(1, "bad mail input format:" " from %s (uid %d) (envelope-from %s)", username, useruid, queue->sender); linelen = strlen(line); if (linelen == 0 || line[linelen - 1] != '\n') { /* * This line did not end with a newline character. * If we fix it, it better be the last line of * the file. */ line[linelen] = '\n'; line[linelen + 1] = 0; had_last_line = 1; } if (!had_headers) { /* * Unless this is a continuation, switch of * the Bcc: nocopy flag. */ if (!(line[0] == ' ' || line[0] == '\t')) nocopy = 0; 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; else if (strprefixcmp(line, "Bcc:") == 0) nocopy = 1; if (parse_state.state != NONE) { if (parse_addrs(&parse_state, line, queue) < 0) { errlogx(1, "invalid address in header\n"); /* NOTREACHED */ } } if (recp_from_header && ( strprefixcmp(line, "To:") == 0 || strprefixcmp(line, "Cc:") == 0 || strprefixcmp(line, "Bcc:") == 0)) { parse_state.state = START; if (parse_addrs(&parse_state, line, queue) < 0) { errlogx(1, "invalid address in header\n"); /* NOTREACHED */ } } } 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 msgid, assign earlier and log? */ had_messagid = 1; snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n", (uintmax_t)time(NULL), queue->id, (uintmax_t)random(), hostname()); } else if (!had_from) { had_from = 1; snprintf(line, sizeof(line), "From: <%s>\n", queue->sender); } if (fwrite(line, strlen(line), 1, queue->mailf) != 1) return (-1); } strcpy(line, "\n"); } if (!nodot && linelen == 2 && line[0] == '.') break; if (!nocopy) { if (fwrite(line, strlen(line), 1, queue->mailf) != 1) return (-1); } } return (0); }
int readmail(struct queue *queue, int nodot, int recp_from_header) { struct parse_state parse_state; char *line = NULL; ssize_t linelen; size_t linecap = 0; char newline[MAX_LINE_RFC822]; size_t error; int had_headers = 0; int had_from = 0; int had_messagid = 0; int had_date = 0; int nocopy = 0; int ret = -1; parse_state.state = NONE; 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, useruid, queue->sender, queue->id, hostname(), VERSION, rfc822date()); if ((ssize_t)error < 0) return (-1); while (!feof(stdin)) { newline[0] = '\0'; if ((linelen = getline(&line, &linecap, stdin)) <= 0) break; if (!had_headers) { if (linelen > MAX_LINE_RFC822) { /* XXX also split headers */ errlogx(EX_DATAERR, "bad mail input format:" " from %s (uid %d) (envelope-from %s)", username, useruid, queue->sender); } /* * Unless this is a continuation, switch of * the Bcc: nocopy flag. */ if (!(line[0] == ' ' || line[0] == '\t')) nocopy = 0; 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; else if (strprefixcmp(line, "Bcc:") == 0) nocopy = 1; if (parse_state.state != NONE) { if (parse_addrs(&parse_state, line, queue) < 0) { errlogx(EX_DATAERR, "invalid address in header\n"); /* NOTREACHED */ } } if (recp_from_header && ( strprefixcmp(line, "To:") == 0 || strprefixcmp(line, "Cc:") == 0 || strprefixcmp(line, "Bcc:") == 0)) { parse_state.state = START; if (parse_addrs(&parse_state, line, queue) < 0) { errlogx(EX_DATAERR, "invalid address in header\n"); /* NOTREACHED */ } } } if (strcmp(line, "\n") == 0 && !had_headers) { had_headers = 1; while (!had_date || !had_messagid || !had_from) { if (!had_date) { had_date = 1; snprintf(newline, sizeof(newline), "Date: %s\n", rfc822date()); } else if (!had_messagid) { /* XXX msgid, assign earlier and log? */ had_messagid = 1; snprintf(newline, sizeof(newline), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n", (uintmax_t)time(NULL), queue->id, (uintmax_t)random(), hostname()); } else if (!had_from) { had_from = 1; snprintf(newline, sizeof(newline), "From: <%s>\n", queue->sender); } if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1) goto fail; } strlcpy(newline, "\n", sizeof(newline)); } if (!nodot && linelen == 2 && line[0] == '.') break; if (!nocopy) { if (newline[0]) { if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1) goto fail; } else { if (writeline(queue, line, linelen) != 0) goto fail; } } } ret = 0; fail: free(line); return (ret); }