Skip to content

Commit a4a30d7

Browse files
committed
Split body of mails not respecting RFC2822
For mails where the body does not respect RFC2822, split at the arbitrary length of 990 This should address #18
1 parent 6748bdd commit a4a30d7

File tree

1 file changed

+54
-28
lines changed

1 file changed

+54
-28
lines changed

mail.c

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
* SUCH DAMAGE.
3434
*/
3535

36+
#include "dfcompat.h"
37+
38+
#include <ctype.h>
3639
#include <errno.h>
3740
#include <inttypes.h>
3841
#include <signal.h>
@@ -341,19 +344,43 @@ parse_addrs(struct parse_state *ps, char *s, struct queue *queue)
341344
goto again;
342345
}
343346

347+
static int
348+
writeline(struct queue *queue, const char *line, ssize_t linelen)
349+
{
350+
ssize_t len;
351+
352+
while (linelen > 0) {
353+
len = linelen;
354+
if (linelen > 1000) {
355+
len = 990;
356+
}
357+
if (fwrite(line, len, 1, queue->mailf) != 1)
358+
return (-1);
359+
if (linelen <= 1000)
360+
break;
361+
if (fwrite("\n", 1, 1, queue->mailf) != 1)
362+
return (-1);
363+
line += 990;
364+
linelen = strlen(line);
365+
}
366+
return (0);
367+
}
368+
344369
int
345370
readmail(struct queue *queue, int nodot, int recp_from_header)
346371
{
347372
struct parse_state parse_state;
348-
char line[1000]; /* by RFC2822 */
349-
size_t linelen;
373+
char *line = NULL;
374+
ssize_t linelen;
375+
size_t linecap = 0;
376+
char newline[1000];
350377
size_t error;
351378
int had_headers = 0;
352379
int had_from = 0;
353380
int had_messagid = 0;
354381
int had_date = 0;
355-
int had_last_line = 0;
356382
int nocopy = 0;
383+
int ret = -1;
357384

358385
parse_state.state = NONE;
359386

@@ -372,24 +399,15 @@ readmail(struct queue *queue, int nodot, int recp_from_header)
372399
return (-1);
373400

374401
while (!feof(stdin)) {
375-
if (fgets(line, sizeof(line) - 1, stdin) == NULL)
402+
newline[0] = '\0';
403+
if ((linelen = getline(&line, &linecap, stdin)) <= 0)
376404
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-
}
392405
if (!had_headers) {
406+
if (linelen > 1000)
407+
errlogx(EX_DATAERR, "bad mail input format:"
408+
" from %s (uid %d) (envelope-from %s)",
409+
username, useruid, queue->sender);
410+
393411
/*
394412
* Unless this is a continuation, switch of
395413
* the Bcc: nocopy flag.
@@ -430,31 +448,39 @@ readmail(struct queue *queue, int nodot, int recp_from_header)
430448
while (!had_date || !had_messagid || !had_from) {
431449
if (!had_date) {
432450
had_date = 1;
433-
snprintf(line, sizeof(line), "Date: %s\n", rfc822date());
451+
snprintf(newline, sizeof(newline), "Date: %s\n", rfc822date());
434452
} else if (!had_messagid) {
435453
/* XXX msgid, assign earlier and log? */
436454
had_messagid = 1;
437-
snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
455+
snprintf(newline, sizeof(newline), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
438456
(uintmax_t)time(NULL),
439457
queue->id,
440458
(uintmax_t)random(),
441459
hostname());
442460
} else if (!had_from) {
443461
had_from = 1;
444-
snprintf(line, sizeof(line), "From: <%s>\n", queue->sender);
462+
snprintf(newline, sizeof(newline), "From: <%s>\n", queue->sender);
445463
}
446-
if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
447-
return (-1);
464+
if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1)
465+
goto fail;
448466
}
449-
strcpy(line, "\n");
467+
strlcpy(newline, "\n", sizeof(newline));
450468
}
451469
if (!nodot && linelen == 2 && line[0] == '.')
452470
break;
453471
if (!nocopy) {
454-
if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
455-
return (-1);
472+
if (newline[0]) {
473+
if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1)
474+
goto fail;
475+
} else {
476+
if (writeline(queue, line, linelen) != 0)
477+
goto fail;
478+
}
456479
}
457480
}
458481

459-
return (0);
482+
ret = 0;
483+
fail:
484+
free(line);
485+
return (ret);
460486
}

0 commit comments

Comments
 (0)