On 18 April 2017 at 14:31, Alexander Burger <a...@software-lab.de> wrote: > ..[snip].. > > which only folds the next line of a multiline header if the existing > > line ends with ";" and then chomps a single leading char, yet as far > > as I understand it, RFC822 supports [A] folding based on (single or > > multiple) leading TABs or spaces, [B] even if the preceding line > > doesn't end with a ";" : > ..[snip].. > Indeed! This looks like a possible source of the problems.
According to the wording in section 2.2.3 at rfc2822 (supersedes rfc822, but is probably the same anyway for this case): https://tools.ietf.org/html/rfc2822#section-2.2.3 I made an attempt at rewriting the header-folding to use a sliding window method, it successfully passed a few crude "works for me" quick-tests I threw at it, so I've attached the patches (against v17.4.7). My picolisp-fu is rusty so there are probably more elegant/efficient ways to write it. If you want to use any of it you'll probably want to cherrypick what makes sense and ignore what doesn't, but feel free to ask me to explain myself if in doubt. The reading-to-the-end-of-the-"From " line was because I found I needed it while testing against some /var/log/X files on my machine (to skip the timestamp which appears on that line after the email address). It is closely bound to the changed method logic so I kept it included in the main patch rather than splitting it out. The other small patch is because during testing (albeit against my Exim spool files which may vary from your Postfix ones) I noticed that some emails which ended without a blank line would end up with the final line half-overwritten by the "-- ", because there would be a ^M without a corresponding ^J. -- Rowan Thorpe http://twitter.com/rowanthorpe "There is a great difference between worry and concern. A worried person sees a problem, and a concerned person solves a problem." - Harold Stephens
diff -Nu a/misc/mailing b/misc/mailing --- a/misc/mailing +++ b/misc/mailing @@ -20,16 +20,21 @@ (quit "Bad mbox file") ) (char) (while (setq *From (lowc (till " " T))) + (till "^M") (char) (char) # trim rest of line and "\r\n" (off *Name *Subject *Date *MessageID *InReplyTo *MimeVersion *ContentType *ContentTransferEncoding *ContentDisposition *UserAgent ) - (while (trim (split (line) " ")) - (let L @ - (while (= ";" (last (last L))) - (char) # Skip TAB - (conc L (trim (split (line) " "))) ) - (setq *Line (glue " " (cdr L))) - (case (pack (car L)) + (let (L (trim (chop (line))) + N (trim (chop (line))) + M (index " " L) + P (when M (head (- M 1) L)) + L (when M (tail (- 0 M) L)) ) + (until (not P) + (until (nand N (member (car N) '(" " "^I"))) + (conc L (cons " " (flip (trim (flip N))))) + (setq N (trim (chop (line)))) ) + (setq *Line (pack L)) + (case (pack P) ("From:" (setq *Name *Line)) ("Subject:" (setq *Subject *Line)) ("Date:" (setq *Date *Line)) @@ -39,7 +44,11 @@ ("Content-Type:" (setq *ContentType *Line)) ("Content-Transfer-Encoding:" (setq *ContentTransferEncoding *Line)) ("Content-Disposition:" (setq *ContentDisposition *Line)) - ("User-Agent:" (setq *UserAgent *Line)) ) ) ) + ("User-Agent:" (setq *UserAgent *Line)) ) + (setq M (index " " N)) + (setq P (when M (head (- M 1) N))) + (setq L (when M (tail (- 0 M) N))) + (setq N (when N (trim (chop (line))))) ) ) (if (nor (member *From *Mailings) (= "subscribe" (lowc *Subject))) (out "/dev/null" (echo "^JFrom ") (msg *From " discarded")) (unless (setq *Sock (connect *SmtpHost *SmtpPort))
diff -Nu a/misc/mailing b/misc/mailing --- a/misc/mailing +++ b/misc/mailing @@ -96,7 +96,7 @@ (prinl "You are now unsubscribed^M") (prinl "****^M^J^M") ) ) (echo "^JFrom ") - (prinl "-- ^M") + (prinl "^J-- ^M") (prinl "UNSUBSCRIBE: mailto:" *MailingList "?subject=Unsubscribe^M") (prinl ".^M") (prinl "QUIT^M") ) )