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") ) )

Reply via email to