Koni Marti: 1 parse: fix content-type parsing error 3 files changed, 86 insertions(+), 1 deletions(-)
Looks good! Thanks a lot Koni! With this patch applied, the email that was causing #44 for me is now displayed correctly. Ivan
Thanks for testing and glad it works. I will send a v2 in a bit where I improve the robustness of the quote replacement, but with the same functionality.
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~rjarry/aerc-devel/patches/32708/mbox | git am -3Learn more about email & git
If an error occurs when parsing the content-type, check if the content-type is quoted; if so, remove quotes. If this is not the case, then return a text/plain content-type as a sane fallback option, so that the message can be at least viewed in plaintext. Fixes: https://todo.sr.ht/~rjarry/aerc/44 Signed-off-by: Koni Marti <koni.marti@gmail.com> --- worker/lib/parse.go | 17 ++++++- worker/lib/parse_test.go | 25 +++++++++++ .../testdata/message/valid/quoted-mime-type | 45 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 worker/lib/testdata/message/valid/quoted-mime-type diff --git a/worker/lib/parse.go b/worker/lib/parse.go index 5d95046..6ddfe06 100644 --- a/worker/lib/parse.go +++ b/worker/lib/parse.go @@ -64,12 +64,27 @@ func splitMIME(m string) (string, string) { return parts[0], parts[1] } +func fixContentType(h message.Header, ct string) (string, map[string]string) { + // check if there are quotes around the content type + if strings.Contains(ct, "\"") { + h.Set("Content-Type", strings.Replace(h.Get("Content-Type"), ct, strings.ReplaceAll(ct, "\"", ""), 1)) + if ctNew, paramsNew, err := h.ContentType(); err == nil { + return ctNew, paramsNew + } + } + // if all else fails, return text/plain + return "text/plain", nil +} + func ParseEntityStructure(e *message.Entity) (*models.BodyStructure, error) { var body models.BodyStructure contentType, ctParams, err := e.Header.ContentType() if err != nil { - return nil, fmt.Errorf("could not parse content type: %v", err) + // try to fix the error; if all measures fail, then return a + // text/plain content type to display at least plaintext + contentType, ctParams = fixContentType(e.Header, contentType) } + mimeType, mimeSubType := splitMIME(contentType) body.MIMEType = mimeType body.MIMESubType = mimeSubType diff --git a/worker/lib/parse_test.go b/worker/lib/parse_test.go index 1219098..7e5bb36 100644 --- a/worker/lib/parse_test.go +++ b/worker/lib/parse_test.go @@ -10,6 +10,31 @@ import ( "git.sr.ht/~rjarry/aerc/models" ) +func TestMessageInfoParser(t *testing.T) { + rootDir := "testdata/message/valid" + msgFiles, err := ioutil.ReadDir(rootDir) + die(err) + + for _, fi := range msgFiles { + if fi.IsDir() { + continue + } + + p := fi.Name() + t.Run(p, func(t *testing.T) { + m := newMockRawMessageFromPath(filepath.Join(rootDir, p)) + mi, err := MessageInfo(m) + if err != nil { + t.Fatal("Failed to create MessageInfo with:", err) + } + + if perr := mi.Error; perr != nil { + t.Fatal("Expected no parsing error, but got:", mi.Error) + } + }) + } +} + func TestMessageInfoHandledError(t *testing.T) { rootDir := "testdata/message/invalid" msgFiles, err := ioutil.ReadDir(rootDir) diff --git a/worker/lib/testdata/message/valid/quoted-mime-type b/worker/lib/testdata/message/valid/quoted-mime-type new file mode 100644 index 0000000..d9af28a --- /dev/null +++ b/worker/lib/testdata/message/valid/quoted-mime-type @@ -0,0 +1,45 @@ +Subject: Your ECOLINES tickets +X-PHP-Originating-Script: 33:functions.inc.php +From: ECOLINES <ecolines@ecolines.lv> +Content-Type: multipart/mixed; + boundary="PHP-mixed-ba319678ca12656cfb8cd46e736ce09d" +Message-Id: <E1nvIQS-0004tm-Bc@legacy.ecolines.net> +Date: Sun, 29 May 2022 15:53:44 +0300 + +--PHP-mixed-ba319678ca12656cfb8cd46e736ce09d +Content-Type: multipart/alternative; boundary="PHP-alt-ba319678ca12656cfb8cd46e736ce09d" + +--PHP-alt-ba319678ca12656cfb8cd46e736ce09d +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 7bit + +Your tickets are attached to this message. Also You can print out Your tickets from our website www.ecolines.net<b +r /> +… + +--PHP-alt-ba319678ca12656cfb8cd46e736ce09d +Content-Type: text/html; charset="UTF-8" +Content-Transfer-Encoding: 7bit + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +… + +--PHP-alt-ba319678ca12656cfb8cd46e736ce09d-- + +--PHP-mixed-ba319678ca12656cfb8cd46e736ce09d +Content-Type: "application/pdf"; name="17634428.pdf" +Content-Disposition: attachment; filename="17634428.pdf" +Content-Transfer-Encoding: base64 + +JVBERi0xLjQKMSAwIG9iago8PAovVGl0bGUgKP7/AFkAbwB1AHIAIAB0AGkAYwBrAGUAdCkKL0Ny +… + +--PHP-mixed-ba319678ca12656cfb8cd46e736ce09d +Content-Type: "application/pdf"; name="invoice-6385490.pdf" +Content-Disposition: attachment; filename="invoice-6385490.pdf" +Content-Transfer-Encoding: base64 + +JVBERi0xLjQKMSAwIG9iago8PAovVGl0bGUgKP7/AEkAbgB2AG8AaQBjAGUpCi9DcmVhdG9yICj+ +… + +--PHP-mixed-ba319678ca12656cfb8cd46e736ce09d-- -- 2.36.1
builds.sr.ht <builds@sr.ht>aerc/patches: SUCCESS in 5m40s [parse: fix content-type parsing error][0] from [Koni Marti][1] [0]: https://lists.sr.ht/~rjarry/aerc-devel/patches/32708 [1]: mailto:koni.marti@gmail.com ✓ #772264 SUCCESS aerc/patches/alpine-edge.yml https://builds.sr.ht/~rjarry/job/772264 ✓ #772265 SUCCESS aerc/patches/debian-stable.yml https://builds.sr.ht/~rjarry/job/772265 ✓ #772266 SUCCESS aerc/patches/fedora-latest.yml https://builds.sr.ht/~rjarry/job/772266 ✓ #772267 SUCCESS aerc/patches/openbsd.yml https://builds.sr.ht/~rjarry/job/772267