leahneukirchen / mblaze

Unix utilities to deal with Maildir
Other
419 stars 48 forks source link

mmime breaks headers #257

Closed rapenne-s closed 4 months ago

rapenne-s commented 4 months ago

hi,

when I apply mmime (from OpenBSD packages) on an email sent from tuta.io, a newline is added to the field DKIM-Signature, which breaks the email

my sample email to reproduce it (I slightly modified the original to redact some addresses)

Return-Path: <test@tuta.io>
Delivered-To: solene
Received: from localhost
    by smth.redacted.something with LMTP
    id 9oG6LQu97GVYPQAA23Ik0Q
    (envelope-from <test@tuta.io>)
    for <solene>; Sat, 09 Mar 2024 20:48:27 +0100
Return-Path: <test@tuta.io>
Delivered-To: contact@redacted.something
Received: from w1.tutanota.de (w1.tutanota.de [81.3.6.162])
    by smth.redacted.something (OpenSMTPD) with ESMTPS id 51454e78 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO)
    for <contact@redacted.something>;
    Sat, 9 Mar 2024 20:48:26 +0100 (CET)
Received: from tutadb.w10.tutanota.de (unknown [192.168.1.10])
    by w1.tutanota.de (Postfix) with ESMTP id 6F6DCFBFC70
    for <contact@redacted.something>; Sat,  9 Mar 2024 19:48:25 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1710013705;
    s=s1; d=tuta.io;
    h=From:From:To:To:Subject:Subject:Content-Description:Content-ID:Content-Type:Content-Type:Content-Transfer-Encoding:Cc:Date:Date:In-Reply-To:MIME-Version:MIME-Version:Message-ID:Message-ID:Reply-To:References:Sender;
    bh=Jr8DQlZ7RwdJv94m7ZT/v+cv/WFsgjxpMRsHvnNfgGY=;
    b=NXRl0YxYtVsWrR8v7tVKnvsnCSrBqqaf2h3m8OVGlzG0OqMqGcWg7fVk6x4nTYV+
    +05afZrGfIwcfFwIe/LLvT0d3/12t4+cs/FQvmEcFUN+n2buQwt5sn8f76UUlvNMrGz
    Xbq8HAdwhA364yWABa7DrF1EGysC8bEDJcCtSs/Wz3TL2A/MEeItEF+VijtgWUwoOwn
    rFKkCg5Df+IOd4gEBS/KYLbzcMB1dvqy+ut2LA2+NZpzJQPgbJzWAYieT9KYgoS+hKS
    5FfknNT+hKZz18IBEWH1UWbI+CcLRR8Sr80x2DZUKq8ryC5RmV5/uAc5Up03b/KZGRU
    NsiBAQCx3w==
Date: Sat, 9 Mar 2024 20:48:25 +0100 (CET)
From: test@tuta.io
To: Contact <contact@redacted.something>
Message-ID: <NsZkace--3-9@tuta.io>
Subject: test
MIME-Version: 1.0
Content-Type: multipart/alternative; 
    boundary="----=_Part_417017_2033693008.1710013705448"

------=_Part_417017_2033693008.1710013705448
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

test
-- 

------=_Part_417017_2033693008.1710013705448
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 7bit

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
<div dir="auto">test</div><div dir="auto"><br></div><div dir="auto">-- <br></div></body>
</html>

------=_Part_417017_2033693008.1710013705448--

If you pipe it to mmime you obtain this result:

Return-Path: <test@tuta.io>
Delivered-To: solene
Received: from localhost
    by smth.redacted.something with LMTP
    id 9oG6LQu97GVYPQAA23Ik0Q
    (envelope-from <test@tuta.io>)
    for <solene>; Sat, 09 Mar 2024 20:48:27 +0100
Return-Path: <test@tuta.io>
Delivered-To: contact@redacted.something
Received: from w1.tutanota.de (w1.tutanota.de [81.3.6.162])
    by smth.redacted.something (OpenSMTPD) with ESMTPS id 51454e78
 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO)
    for <contact@redacted.something>;
    Sat, 9 Mar 2024 20:48:26 +0100 (CET)
Received: from tutadb.w10.tutanota.de (unknown [192.168.1.10])
    by w1.tutanota.de (Postfix) with ESMTP id 6F6DCFBFC70
    for <contact@redacted.something>; Sat,  9 Mar 2024 19:48:25 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
 t=1710013705;
    s=s1; d=tuta.io;

    h=From:From:To:To:Subject:Subject:Content-Description:Content-ID:Content-Type:Content-Type:Content-Transfer-Encoding:Cc:Date:Date:In-Reply-To:MIME-Version:MIME-Version:Message-ID:Message-ID:Reply-To:References:Sender;
    bh=Jr8DQlZ7RwdJv94m7ZT/v+cv/WFsgjxpMRsHvnNfgGY=;
    b=NXRl0YxYtVsWrR8v7tVKnvsnCSrBqqaf2h3m8OVGlzG0OqMqGcWg7fVk6x4nTYV+
    +05afZrGfIwcfFwIe/LLvT0d3/12t4+cs/FQvmEcFUN+n2buQwt5sn8f76UUlvNMrGz
    Xbq8HAdwhA364yWABa7DrF1EGysC8bEDJcCtSs/Wz3TL2A/MEeItEF+VijtgWUwoOwn
    rFKkCg5Df+IOd4gEBS/KYLbzcMB1dvqy+ut2LA2+NZpzJQPgbJzWAYieT9KYgoS+hKS
    5FfknNT+hKZz18IBEWH1UWbI+CcLRR8Sr80x2DZUKq8ryC5RmV5/uAc5Up03b/KZGRU
    NsiBAQCx3w==
Date: Sat, 9 Mar 2024 20:48:25 +0100 (CET)
From: test@tuta.io
To: Contact <contact@redacted.something>
Message-ID: <NsZkace--3-9@tuta.io>
Subject: test
MIME-Version: 1.0
    boundary="----=_Part_417017_2033693008.1710013705448"
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----_=_3e0505e6347f3ecf153c1566_=_"

This is a multipart message in MIME format.

------_=_3e0505e6347f3ecf153c1566_=_
Content-Type: multipart/alternative; 
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

------=3D_Part_417017_2033693008.1710013705448
Content-Type: text/plain; charset=3DUTF-8
Content-Transfer-Encoding: 7bit

test
--=20

------=3D_Part_417017_2033693008.1710013705448
Content-Type: text/html; charset=3DUTF-8
Content-Transfer-Encoding: 7bit

<html>
  <head>
    <meta http-equiv=3D"content-type" content=3D"text/html; charset=3DUTF-8=
">
  </head>
  <body>
<div dir=3D"auto">test</div><div dir=3D"auto"><br></div><div dir=3D"auto">-=
- <br></div></body>
</html>

------=3D_Part_417017_2033693008.1710013705448--

------_=_3e0505e6347f3ecf153c1566_=_--
rapenne-s commented 4 months ago

The extra newline character comes from this line in mmime.c https://github.com/leahneukirchen/mblaze/blob/master/mmime.c#L352

However, removing it breaks the tests and I don't think it's the right solution anyway :sweat_smile:

leahneukirchen commented 4 months ago

Ok, I can reproduce this. Let me see how to solve this properly.

rapenne-s commented 4 months ago

I got a diff with which the tests pass, not sure it's good though

diff --git a/mmime.c b/mmime.c
index 6334569..b521efc 100644
--- a/mmime.c
+++ b/mmime.c
@@ -347,7 +347,7 @@ print_header(char *line) {
                if (!highbit) {
                        if (e-s >= 998)
                                goto force_qp;
-                       if (e-s >= 78 - linelen) {
+                       if (e-s >= 78 - linelen && linelen > 0) {
                                // wrap in advance before long word
                                printf("\n");
                                linelen = 0;
leahneukirchen commented 4 months ago

yes, sounds reasonable. in theory, one could wrap the h= after :, but this requires special knowledge.

leahneukirchen commented 4 months ago

want to make a PR or shall i just pick it up?

rapenne-s commented 4 months ago

want to make a PR or shall i just pick it up?

please fix it, I feel I randomly fixed it without understanding the consequences ;)

leahneukirchen commented 4 months ago

Nah, your code is correct: it checks we are not at the beginning of a line.

leahneukirchen commented 4 months ago

Fixed in cf5493b.