mail.c (814aaaa7da4dab462d90e12e7b48b75f2093ccfd) mail.c (b4b4b5304bd22eab265c9c049cb7fc6b55c4ef3f)
1/*
2 * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>.
3 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
4 *
5 * This code is derived from software contributed to The DragonFly Project
6 * by Simon Schubert <2@0x2c.org>.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 24 unchanged lines hidden (view full) ---

33 * SUCH DAMAGE.
34 */
35
36#include <errno.h>
37#include <inttypes.h>
38#include <signal.h>
39#include <syslog.h>
40#include <unistd.h>
1/*
2 * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>.
3 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
4 *
5 * This code is derived from software contributed to The DragonFly Project
6 * by Simon Schubert <2@0x2c.org>.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 24 unchanged lines hidden (view full) ---

33 * SUCH DAMAGE.
34 */
35
36#include <errno.h>
37#include <inttypes.h>
38#include <signal.h>
39#include <syslog.h>
40#include <unistd.h>
41#include <ctype.h>
42
43#include "dma.h"
44
45void
46bounce(struct qitem *it, const char *reason)
47{
48 struct queue bounceq;
49 char line[1000];

--- 287 unchanged lines hidden (view full) ---

337 errlog(EX_SOFTWARE, "strdup");
338
339 if (add_recp(queue, addr, EXPAND_WILDCARD) != 0)
340 errlogx(EX_DATAERR, "invalid recipient `%s'", addr);
341
342 goto again;
343}
344
41
42#include "dma.h"
43
44void
45bounce(struct qitem *it, const char *reason)
46{
47 struct queue bounceq;
48 char line[1000];

--- 287 unchanged lines hidden (view full) ---

336 errlog(EX_SOFTWARE, "strdup");
337
338 if (add_recp(queue, addr, EXPAND_WILDCARD) != 0)
339 errlogx(EX_DATAERR, "invalid recipient `%s'", addr);
340
341 goto again;
342}
343
345static int
346writeline(struct queue *queue, const char *line, ssize_t linelen)
347{
348 ssize_t len;
349
350 while (linelen > 0) {
351 len = linelen;
352 if (linelen > 1000) {
353 len = 990;
354 }
355 if (fwrite(line, len, 1, queue->mailf) != 1)
356 return (-1);
357 if (linelen <= 1000)
358 break;
359 if (fwrite("\n", 1, 1, queue->mailf) != 1)
360 return (-1);
361 line += 990;
362 linelen = strlen(line);
363 }
364 return (0);
365}
366
367int
368readmail(struct queue *queue, int nodot, int recp_from_header)
369{
370 struct parse_state parse_state;
344int
345readmail(struct queue *queue, int nodot, int recp_from_header)
346{
347 struct parse_state parse_state;
371 char *line = NULL;
372 ssize_t linelen;
373 size_t linecap = 0;
374 char newline[1000];
348 char line[1000]; /* by RFC2822 */
349 size_t linelen;
375 size_t error;
376 int had_headers = 0;
377 int had_from = 0;
378 int had_messagid = 0;
379 int had_date = 0;
350 size_t error;
351 int had_headers = 0;
352 int had_from = 0;
353 int had_messagid = 0;
354 int had_date = 0;
355 int had_last_line = 0;
380 int nocopy = 0;
381
382 parse_state.state = NONE;
383
384 error = fprintf(queue->mailf,
385 "Received: from %s (uid %d)\n"
386 "\t(envelope-from %s)\n"
387 "\tid %s\n"
388 "\tby %s (%s);\n"
389 "\t%s\n",
390 username, useruid,
391 queue->sender,
392 queue->id,
393 hostname(), VERSION,
394 rfc822date());
395 if ((ssize_t)error < 0)
396 return (-1);
397
398 while (!feof(stdin)) {
356 int nocopy = 0;
357
358 parse_state.state = NONE;
359
360 error = fprintf(queue->mailf,
361 "Received: from %s (uid %d)\n"
362 "\t(envelope-from %s)\n"
363 "\tid %s\n"
364 "\tby %s (%s);\n"
365 "\t%s\n",
366 username, useruid,
367 queue->sender,
368 queue->id,
369 hostname(), VERSION,
370 rfc822date());
371 if ((ssize_t)error < 0)
372 return (-1);
373
374 while (!feof(stdin)) {
399 newline[0] = '\0';
400 if ((linelen = getline(&line, &linecap, stdin)) <= 0)
375 if (fgets(line, sizeof(line) - 1, stdin) == NULL)
401 break;
376 break;
377 if (had_last_line)
378 errlogx(EX_DATAERR, "bad mail input format:"
379 " from %s (uid %d) (envelope-from %s)",
380 username, useruid, queue->sender);
381 linelen = strlen(line);
382 if (linelen == 0 || line[linelen - 1] != '\n') {
383 /*
384 * This line did not end with a newline character.
385 * If we fix it, it better be the last line of
386 * the file.
387 */
388 line[linelen] = '\n';
389 line[linelen + 1] = 0;
390 had_last_line = 1;
391 }
402 if (!had_headers) {
392 if (!had_headers) {
403 if (linelen > 1000)
404 errlogx(EX_DATAERR, "bad mail input format:"
405 " from %s (uid %d) (envelope-from %s)",
406 username, useruid, queue->sender);
407
408 /*
409 * Unless this is a continuation, switch of
410 * the Bcc: nocopy flag.
411 */
412 if (!(line[0] == ' ' || line[0] == '\t'))
413 nocopy = 0;
414
415 if (strprefixcmp(line, "Date:") == 0)

--- 19 unchanged lines hidden (view full) ---

435 parse_state.state = START;
436 if (parse_addrs(&parse_state, line, queue) < 0) {
437 errlogx(EX_DATAERR, "invalid address in header\n");
438 /* NOTREACHED */
439 }
440 }
441 }
442
393 /*
394 * Unless this is a continuation, switch of
395 * the Bcc: nocopy flag.
396 */
397 if (!(line[0] == ' ' || line[0] == '\t'))
398 nocopy = 0;
399
400 if (strprefixcmp(line, "Date:") == 0)

--- 19 unchanged lines hidden (view full) ---

420 parse_state.state = START;
421 if (parse_addrs(&parse_state, line, queue) < 0) {
422 errlogx(EX_DATAERR, "invalid address in header\n");
423 /* NOTREACHED */
424 }
425 }
426 }
427
443 if (line[0] == '\n' && !had_headers) {
428 if (strcmp(line, "\n") == 0 && !had_headers) {
444 had_headers = 1;
445 while (!had_date || !had_messagid || !had_from) {
446 if (!had_date) {
447 had_date = 1;
429 had_headers = 1;
430 while (!had_date || !had_messagid || !had_from) {
431 if (!had_date) {
432 had_date = 1;
448 snprintf(newline, sizeof(newline), "Date: %s\n", rfc822date());
433 snprintf(line, sizeof(line), "Date: %s\n", rfc822date());
449 } else if (!had_messagid) {
450 /* XXX msgid, assign earlier and log? */
451 had_messagid = 1;
434 } else if (!had_messagid) {
435 /* XXX msgid, assign earlier and log? */
436 had_messagid = 1;
452 snprintf(newline, sizeof(newline), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
437 snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
453 (uintmax_t)time(NULL),
454 queue->id,
455 (uintmax_t)random(),
456 hostname());
457 } else if (!had_from) {
458 had_from = 1;
438 (uintmax_t)time(NULL),
439 queue->id,
440 (uintmax_t)random(),
441 hostname());
442 } else if (!had_from) {
443 had_from = 1;
459 snprintf(newline, sizeof(newline), "From: <%s>\n", queue->sender);
444 snprintf(line, sizeof(line), "From: <%s>\n", queue->sender);
460 }
445 }
461 if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1)
462 goto fail;
446 if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
447 return (-1);
463 }
448 }
464 strlcpy(newline, "\n", sizeof(newline));
449 strcpy(line, "\n");
465 }
466 if (!nodot && linelen == 2 && line[0] == '.')
467 break;
468 if (!nocopy) {
450 }
451 if (!nodot && linelen == 2 && line[0] == '.')
452 break;
453 if (!nocopy) {
469 if (newline[0] != '\0') {
470 if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1)
471 goto fail;
472 } else {
473 if (writeline(queue, line, linelen) != 0)
474 goto fail;
475 }
454 if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
455 return (-1);
476 }
477 }
478
479 return (0);
456 }
457 }
458
459 return (0);
480fail:
481 free(line);
482 return (-1);
483}
460}