Here is my simple line folding filter. Going with getc() is a lot simpler but this way seems faster and it was fun to play around with. And it seems to work.
This will break long lines exactly at the specified length without regard to whitespace. In the header, a tab (\t) is added after added newlines. This would work for e.g. attachments formatted as one very long line of base64. It could cause problems in other cases. compile: gcc -o email-line-fold email-line-fold.c usage: remote_smtp: transport_filter = '${if > {$max_received_linelength}{998}{/usr/local/bin/email-line-fold}{}}' 998
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <error.h> #define BUFSIZE 4096 int main(int argc, char *argv[]) { char *endptr, *str; long linemax = 0; char buf[BUFSIZE]; char *bufi; char *bufend; char *nl; ssize_t bytes_read = 0; ssize_t bytes_written = 0; size_t bytes_remaining = 0; size_t bytestowrite = 0; int header_done = 0; int length = 0; int lastlength = 0; if (argc < 2) { fprintf(stderr, "Usage: %s linemax\n", argv[0]); exit(EXIT_FAILURE); } str = argv[1]; errno = 0; linemax = strtol(str, &endptr, 0); if (endptr == str) { fprintf(stderr, "Usage: %s linemax\n", argv[0]); fprintf(stderr, "linemax must be a numerical value\n"); exit(EXIT_FAILURE); } if (errno != 0) { perror("strtol"); exit(EXIT_FAILURE); } if (linemax < 2) { fprintf(stderr, "linemax must be at least 2\n"); exit(EXIT_FAILURE); } bufi = &buf[0]; while (1) { if (! bytes_remaining) { if (feof(stdin)) break; bytes_read = fread(buf, 1, BUFSIZE, stdin); if (ferror (stdin)) error(EXIT_FAILURE, errno, "Error while reading"); if (! bytes_read) break; bytes_remaining = bytes_read; bufi = &buf[0]; bufend = &buf[0] + bytes_read - 1; } if (! header_done && nl == bufend && buf[0] == '\n') header_done = 1; while (bytes_remaining) { nl = memchr(bufi, '\n', bytes_remaining); if (nl == NULL) length = bytes_remaining; else length = nl - bufi + 1; if (! header_done && nl != NULL && nl < bufend && nl[1] == '\n') header_done = 1; bytes_remaining -= length; while (length) { int addnl = 0; if (lastlength + length > linemax) { bytestowrite = linemax - lastlength; if (nl == NULL || lastlength + length > (linemax + 1)) addnl = 1; lastlength = 0; } else { bytestowrite = length; if (bufi[length-1] != '\n') lastlength += length; else lastlength = 0; } bytes_written = fwrite(bufi, 1, bytestowrite, stdout); if (ferror (stdout)) error(EXIT_FAILURE, errno, "Error while writing"); if (addnl) if (! header_done) { if (fputs("\n\t", stdout) == EOF) error(EXIT_FAILURE, errno, "Error while writing"); lastlength++; } else { if (putchar('\n') == EOF) error(EXIT_FAILURE, errno, "Error while writing"); } length -= bytestowrite; bufi += bytestowrite; } } } fclose(stdin); fclose(stdout); return 0; }
-- ## List details at https://lists.exim.org/mailman/listinfo/exim-users ## Exim details at http://www.exim.org/ ## Please use the Wiki with this list - http://wiki.exim.org/