Skip to content

Commit c5792a5

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 c5792a5

File tree

1 file changed

+54
-29
lines changed

1 file changed

+54
-29
lines changed

mail.c

Lines changed: 54 additions & 29 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>
@@ -333,26 +336,49 @@ parse_addrs(struct parse_state *ps, char *s, struct queue *queue)
333336
ps->pos = 0;
334337
addr = strdup(ps->addr);
335338
if (addr == NULL)
336-
errlog(EX_SOFTWARE, NULL);
339+
errlog(EX_SOFTWARE, "strdup");
337340

338341
if (add_recp(queue, addr, EXPAND_WILDCARD) != 0)
339342
errlogx(EX_DATAERR, "invalid recipient `%s'", addr);
340343

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;
357383

358384
parse_state.state = NONE;
@@ -372,24 +398,15 @@ readmail(struct queue *queue, int nodot, int recp_from_header)
372398
return (-1);
373399

374400
while (!feof(stdin)) {
375-
if (fgets(line, sizeof(line) - 1, stdin) == NULL)
401+
newline[0] = '\0';
402+
if ((linelen = getline(&line, &linecap, stdin)) <= 0)
376403
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-
}
392404
if (!had_headers) {
405+
if (linelen > 1000)
406+
errlogx(EX_DATAERR, "bad mail input format:"
407+
" from %s (uid %d) (envelope-from %s)",
408+
username, useruid, queue->sender);
409+
393410
/*
394411
* Unless this is a continuation, switch of
395412
* the Bcc: nocopy flag.
@@ -425,36 +442,44 @@ readmail(struct queue *queue, int nodot, int recp_from_header)
425442
}
426443
}
427444

428-
if (strcmp(line, "\n") == 0 && !had_headers) {
445+
if (line[0] == '\n' && !had_headers) {
429446
had_headers = 1;
430447
while (!had_date || !had_messagid || !had_from) {
431448
if (!had_date) {
432449
had_date = 1;
433-
snprintf(line, sizeof(line), "Date: %s\n", rfc822date());
450+
snprintf(newline, sizeof(newline), "Date: %s\n", rfc822date());
434451
} else if (!had_messagid) {
435452
/* XXX msgid, assign earlier and log? */
436453
had_messagid = 1;
437-
snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
454+
snprintf(newline, sizeof(newline), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
438455
(uintmax_t)time(NULL),
439456
queue->id,
440457
(uintmax_t)random(),
441458
hostname());
442459
} else if (!had_from) {
443460
had_from = 1;
444-
snprintf(line, sizeof(line), "From: <%s>\n", queue->sender);
461+
snprintf(newline, sizeof(newline), "From: <%s>\n", queue->sender);
445462
}
446-
if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
447-
return (-1);
463+
if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1)
464+
goto fail;
448465
}
449-
strcpy(line, "\n");
466+
strlcpy(newline, "\n", sizeof(newline));
450467
}
451468
if (!nodot && linelen == 2 && line[0] == '.')
452469
break;
453470
if (!nocopy) {
454-
if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
455-
return (-1);
471+
if (newline[0] != '\0') {
472+
if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1)
473+
goto fail;
474+
} else {
475+
if (writeline(queue, line, linelen) != 0)
476+
goto fail;
477+
}
456478
}
457479
}
458480

459481
return (0);
482+
fail:
483+
free(line);
484+
return (-1);
460485
}

0 commit comments

Comments
 (0)