RainLoop / rainloop-webmail

Simple, modern & fast web-based email client
http://rainloop.net
MIT License
4.12k stars 894 forks source link

DKIM hash mismatch (failure) on sent emails, only when composed as HTML #2004

Open ChristopherW opened 4 years ago

ChristopherW commented 4 years ago

RainLoop version, browser, OS: 1.14.0 Community on CentOS 6 (connecting to a CentOS 7 mailserver over IMAP). Locally: latest Chrome, Windows 10.

Expected behavior and actual behavior: Email sent in RainLoop should pass with a valid DKIM header when assessed by the receiving server. Actual behaviour: GMail or any other MX (e.g. Postfix) indicates either an unprotected key or a DKIM failure when the email is received and headers are inspected.

Steps to reproduce the problem: Send an email with RainLoop using the HTML composer.

Logs or screenshots:

Email sent via RainLoop which fails DKIM on receipt (certain details redacted):

Delivered-To: example@example.com
Received: by 2002:a1c:e48a:0:0:0:0:0 with SMTP id b132csp29081wmh;
        Thu, 14 May 2020 14:44:11 -0700 (PDT)
X-Google-Smtp-Source: ABdhPJyWI5y6tGLmymsG8WK8XYooYtaM+D7x45e9Crug5EGpi43KZ7o0aftLiKU+GxtWC33zN2Sz
X-Received: by 2002:a1c:25c3:: with SMTP id l186mr371812wml.103.1589492651452;
        Thu, 14 May 2020 14:44:11 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1589492651; cv=none;
        d=google.com; s=arc-20160816;
        b=ZiiGtebWthUAd+DzhPX+KTg6/nfdxoMwL29IinQ66mc0NrYAx5tEnBDQd5oCH43Mxd
         uNiSVw5nwhGBp+y+JgbPvwdwIIi6l5IzLPIrG4ghPlQ3XeA8VRy3Pc+LMojcW51k0TKZ
         lDG8HFxXV30bMHZRJkmo39gZ8QUeZKx7OCIHVK131FYS+h34htd90lMWhuYp57yvg4L5
         M4i6qnmuC2dYsK36HmOD67FrsqL9HS6KXwAjycXgfZoIzU1+3UQNRrD1pNXmdfFatNdV
         tY1Ln+AZTQCpWnv3TAl3txchyHJR6ZuAcc/GhJKz6qwS4dEWCDcAVv4uMagSOCclJQEc
         0Nfg==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=cc:to:subject:message-id:from:date:mime-version:dkim-signature
         :dkim-filter;
        bh=fwCr5wmnstiImNtS70ri3wcP+NKpA56WUwdPDIjURnE=;
        b=diDJbHNjX7EgwMc8Z77SqJ0Jb32MSMwOuZUDNNuprbBThgURckLlpGOTtDLFVtOUxR
         etzQgvnw79lIUwt3RgCoEbrzeb1S5mWRcH3ftXU8eA2/y2Zfec8rxRd2yb9OzuLuaNq6
         hWi7IJcCVDDgIMW19RpXzlNlAOBwvMgo9zvPLIpYbkcj93Ot4VkWKiaB1oVa45hq3s35
         zFrd4LJ+G7FStYEKRid1ru7dNISwIKRiw1Jj/VfdkcEv2RSngMBl3JgVokCt8/nfiatf
         FXLXQXkxU3g3IUXk8CLwQkNE+iO5tj70HEck6ZoyKZ8CrkGsrwrFdeN+nAGx4tzTbWPp
         2geA==
ARC-Authentication-Results: i=1; mx.google.com;
       dkim=fail header.i=@example.com header.s=default header.b=vOMz502D;
       spf=pass (google.com: domain of christopher.woods@example.com designates deaf::beef as permitted sender) smtp.mailfrom=christopher.woods@example.com;
       dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com
Return-Path: <christopher.woods@example.com>
Received: from l03.example.org.uk (l03.example.org.uk. [deaf::beef])
        by mx.google.com with ESMTPS id q2si44241wrp.37.2020.05.14.14.44.11
        for <example@example.com>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Thu, 14 May 2020 14:44:11 -0700 (PDT)
Received-SPF: pass (google.com: domain of christopher.woods@example.com designates deaf::beef as permitted sender) client-ip=deaf::beef;
Authentication-Results: mx.google.com;
       dkim=fail header.i=@example.com header.s=default header.b=vOMz502D;
       spf=pass (google.com: domain of christopher.woods@example.com designates deaf::beef as permitted sender) smtp.mailfrom=christopher.woods@example.com;
       dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com
Received: from wm.example.org.uk (l02a.example.co.uk [IPv6:dead::beef]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by l03.example.org.uk (Postfix) with ESMTPSA id D7E9A18FB; Thu, 14 May 2020 22:44:10 +0100 (BST)
DKIM-Filter: OpenDKIM Filter v2.11.0 l03.example.org.uk D7E9A18FB
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=default; t=1589492650; bh=fwCr5wmnstiImNtS70ri3wcP+NKpA56WUwdPDIjURnE=; h=Date:From:Subject:To:Cc:From; b=vOMz502DZQQ0yUgQCjjJLEhTNP2mFB3SGfRt6JsxyVM/9WoJbQYoFoV0SfGkOMZ/0
     vFw4+Ddr1+xsWLcCwntDXX1fyIkHZILnT/6CsF+FDoS9x8wbLGkcn6cKY3RDi/wjYj
     vnQYw1qNUlNQmwq91ITNXCWK5QH0ds2K1TAHhMG7kEIp9n35rxA0nkxMcsrZCE8QEx
     QTpedijgNQOjHiTByzKutzZZJaiMZTA7K0SyfE5K8Fr8st/ouqPF+OMyvSIm3wAykn
     2K5lGo0bzAlWOpmG0hXWRwdzs9H8BoYaQkDyJ1/ZeegdJ7wj0ZazGnoxuOLdUoY0cH
     3q2caRmEX8L+g==
MIME-Version: 1.0
Date: Thu, 14 May 2020 21:44:10 +0000
Content-Type: multipart/alternative; boundary="--=_RainLoop_900_870903297.1589492650"
X-Mailer: RainLoop/1.14.0
From: Chris Woods <christopher.woods@example.com>
Message-ID: <3b7aba427bd5a00516d900c241181263@example.com>
Subject: DKIM test 4 after resign and new private key
To: example@testdomain.com
Cc: christopher@testdomain.org.uk
X-Originating-IP: 1.2.3.4
X-Greylist: Default is to whitelist mail, not delayed by milter-greylist-4.6.2 (l03.example.org.uk [0.0.0.0]); Thu, 14 May 2020 22:44:10 +0100 (BST)
X-Greylist: inspected by milter-greylist-4.6.2 (l03.example.org.uk [0.0.0.0]); Thu, 14 May 2020 22:44:10 +0100 (BST) for IP:'dead::beef' DOMAIN:'l02a.example.co.uk' HELO:'wm.example.org.uk' FROM:'christopher.woods@example.com' RCPT:''

----=_RainLoop_900_870903297.1589492650
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable

Hello World.

----=_RainLoop_900_870903297.1589492650
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html><html><head><meta http-equiv=3D"Content-Type" content=3D"tex=
t/html; charset=3Dutf-8" /></head><body><div data-html-editor-font-wrapper=
=3D"true" style=3D"font-family: arial, sans-serif; font-size: 13px;">Hello =
World.<br><br><signature></signature> </div></body></html>

----=_RainLoop_900_870903297.1589492650--

Email sent via IMAP client (Aquamail Pro on Android) which passes DKIM:

Delivered-To: example@testdomain.com
Received: by 2002:a1c:e48a:0:0:0:0:0 with SMTP id b132csp30811wmh;
        Thu, 14 May 2020 14:47:07 -0700 (PDT)
X-Google-Smtp-Source: ABdhPJwadgewN1I57wE8J/Y5vdHn6deuZNe+V6JbolWh+bry8YnPj/2YdopZEhQgXJlRhiGUmYiT
X-Received: by 2002:adf:cd83:: with SMTP id q3mr518048wrj.187.1589492827849;
        Thu, 14 May 2020 14:47:07 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1589492827; cv=none;
        d=google.com; s=arc-20160816;
        b=DrubsYbAhCA+0VQKWTwWQRJ1HYRaSUDHYcRLiC7wH69VZmAMRcy/49xYM/XEEp050u
         R7v8wdHzufR4vasyLEpu/mg9NzotYxp/SkYmKXlqv+JtVHJoKlJ80Q9ysEWMqm24nRav
         I4HMZOZpiWij/se60oThbsAvThPJYc71qdFxPUyxwsyEok0w/BLtT4N4ivgZPiFB5/n1
         WkXUjGe/X0mreMFrEHfnZuTin3cAfKPD21SlxlfMKlCC0+npKAl1ZDihiOXg8gn4TdXx
         F9Af9q6mvtf42piCU8XmOqbn49Ph5pe4ZmsgL96Q6l+Y4fKMfwMpMoWp6TOrGaPvRTJB
         4WxQ==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=content-transfer-encoding:mime-version:subject:user-agent
         :message-id:date:to:from:dkim-signature:dkim-filter;
        bh=aO0KCAQi3M7BpcQG0u8YTtZELbNP0ZSQsLtemczcTCc=;
        b=yFCbNvIPmq6HNRot14MR4cOw/0bxrNcADNsjXnojOynm0ZNDxPfx3XyYGg/HhP+b6F
         dJg+XK/JkAOJpGfQ5MSA05n6WCe3GRTOSBVz4iA+vq9mgLGsak1Qrr36f1wsdolZRDTN
         Pj4aWxPnXLRVx7IIM1rAdlWTWq23R/NhKoQVmyX/OXd59kB8lcYOvtq7lv5tek0JzEpt
         mZd1tq8TCnV67lnVEoFIA69sGhnTaLTyAvmzNEfJDBtYXHM1fNcZwsxsNmvtMZIPKClK
         hyMDpgXcDH6SHsA7AQVKRM5fOt9bgHHmSWYUjPwa1L9/bbIu0rKAxNFsqwva1tqUXPuj
         HibQ==
ARC-Authentication-Results: i=1; mx.google.com;
       dkim=pass header.i=@example.com header.s=default header.b=RZocZEb5;
       spf=pass (google.com: domain of christopher.woods@example.com designates 172.19.1.2 as permitted sender) smtp.mailfrom=christopher.woods@example.com;
       dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=example.com
Return-Path: <christopher.woods@example.com>
Received: from l03.example.org.uk (l03.example.org.uk. [172.19.1.2])
        by mx.google.com with ESMTPS id l19si27926946wmj.1.2020.05.14.14.47.07
        for <example@testdomain.com>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Thu, 14 May 2020 14:47:07 -0700 (PDT)
Received-SPF: pass (google.com: domain of christopher.woods@example.com designates 172.19.1.2 as permitted sender) client-ip=172.19.1.2;
Authentication-Results: mx.google.com;
       dkim=pass header.i=@example.com header.s=default header.b=RZocZEb5;
       spf=pass (google.com: domain of christopher.woods@example.com designates 172.19.1.2 as permitted sender) smtp.mailfrom=christopher.woods@example.com;
       dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=example.com
Received: from [192.168.2.106] (unknown [10.55.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by l03.example.org.uk (Postfix) with ESMTPSA id 39BB718FB for <example@testdomain.com>; Thu, 14 May 2020 22:47:07 +0100 (BST)
DKIM-Filter: OpenDKIM Filter v2.11.0 l03.example.org.uk 39BB718FB
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=default; t=1589492827; bh=aO0KCAQi3M7BpcQG0u8YTtZELbNP0ZSQsLtemczcTCc=; h=From:To:Date:Subject:From; b=RZocZEb55SjrwL8jMiicd4CtBNyhl0IihYxnG1oLjs0LZJhcU3QCVHRFkVPMiyqN0
     eUrDcb8TSDSkGPi3u+OmweUeu+zRnLXMWD0VXNVdO9rYKaJrFKPmukKPFv82PIOc1w
     TMidz9TEcb0+Px9nw2pLN1wCAz2fHN5oJ7BFsiXzix0StuLpcfYO9Olk14FDr2HYM/
     PJa7bz9oEVvSDyFxxYdZJjIwOuIiTxByfsY/8HU2tSlVfGkCGMkjvy1blGNNpiebor
     GFzgFEK4a30kclAAuFpb4G7uOS29idFRVhaicXZmB6s1uz8oYxDFFzlvJhLjJ7v3hr
     4nZdhYMwaXLbA==
From: Chris Woods <christopher.woods@example.com>
To: <example@testdomain.com>
Date: Thu, 14 May 2020 22:47:06 +0100
Message-ID: <1721526d918.27f7.408c82f8974a469642cbb90aed154c75@example.com>
User-Agent: AquaMail/1.24.1-1586-beta (build: 102400007)
Subject: DKIM test from client, not webmail
MIME-Version: 1.0
Content-Type: text/plain; format=flowed; charset="us-ascii"
Content-Transfer-Encoding: 8bit
X-Greylist: Default is to whitelist mail, not delayed by milter-greylist-4.6.2 (l03.example.org.uk [0.0.0.0]); Thu, 14 May 2020 22:47:07 +0100 (BST)
X-Greylist: inspected by milter-greylist-4.6.2 (l03.example.org.uk [0.0.0.0]); Thu, 14 May 2020 22:47:07 +0100 (BST) for IP:'10.55.0.1' DOMAIN:'[10.55.0.1]' HELO:'[192.168.2.106]' FROM:'christopher.woods@example.com' RCPT:''

hi world.

To rule out DKIM, DNSSEC or Postfix, I regenerated all DKIM keys, DNSSEC resigned all records and triple-checked everything had propagated. All servers restarted and checked for correct operation.

It seems, reliably, that when an email is sent using RainLoop composed in HTML mode, something is happening which is making the header hash mismatch. Sent in plaintext, DKIM validates perfectly. Emails sent as plaintext or HTML with other clients always pass DKIM. Perhaps it's how RL is encoding HTML special chars?

Happy to do more testing and provide unredacted logs privately.

Philippe34 commented 4 years ago

@ChristopherW I've tried to verify with my Rainloop 14.0 et my mail servers the issue that you described. When I send emails with Rainloop, my mail server always add DKIM signature with html or non formatted text. An example, with an email sent to gmail address.

You can see: dkim=pass header.i=@test.domain.fr

Delivered-To: user@gmail.com
Received: by 2002:a50:450:0:0:0:0:0 with SMTP id 16csp1533072ecr;
        Thu, 4 Jun 2020 06:59:24 -0700 (PDT)
X-Google-Smtp-Source: ABdhPJznV04zMySnsO/s2pfgDXz9rFr7j72fKhsIIgvJE/oAfKN8nj93S/C10rbfMS5J3TdprdUq
X-Received: by 2002:a5d:468d:: with SMTP id u13mr4933188wrq.73.1591279164552;
        Thu, 04 Jun 2020 06:59:24 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1591279164; cv=none;
        d=google.com; s=arc-20160816;
        b=Jgb6USVHykNBsH8u9xEbzAZb+7PKm00f9euLNCdJjHsNxZ20Yg96neA1AU6+i2rjPx
         jFL2HMhtqR1ShFLL48T1MBkUrvfD6qZBoYrTgTj6P4z4VkUtCFXIxQgNETAvHeyuXR8W
         i4Epgm38mJx6rL8t+lT5GYm+atkHqIipVUvNGu6XKhHA3A+NQtBlA7iVeQXLKfU3lNLU
         gr3NvniyZMM9Qv1ro4FN9THayTvMio4htRFkrm5nYCZaUJc5v44v0Im+XqwrUSTp2uKW
         SWXoOzAZnnHI0QaQk+fvgWapE2+do0ooTUjAoVEBu+m0yv4BG+U/VOcHeX6YPlRSwfAh
         Xz0A==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=to:subject:message-id:from:date:mime-version:dkim-signature;
        bh=FJbfrtv+cxhW55iMi9reQkkVGvIcTprMdhm5f/b5NjE=;
        b=EZb63hXCf1lZcB3Hsl/zwBBlWBMr2amsiy6y32gN125yhNsKSz2T012on9QXwgaBMA
         U/KPBmg1a+jMZE2EKULWtXiWseve1+747BrQkWmp5CXVrnH5fnIVvckR94wNWqWuYknu
         v25JA+zu0QMmzVCf+ezfJyErxoxtfjSo71YCDH2sMqG2vxZDv9vOqHkD6IwhIv25wmDy
         QDcOFZJCutUWHn84OGM+Wx+R0Df1VbhEIXgObTYFw2ly7E1yrTvKhP81xGeOYwG6ZraR
         /6GieyFDmFaNs9FdGhc3Jutqh5z8j/v+lKmc+fhRHTUsiG2CUAXxzs1tHHQbW9Nxmy2e
         VU3A==
ARC-Authentication-Results: i=1; mx.google.com;
       dkim=pass header.i=@test.domain.fr header.s=mail header.b=NF56conH;
       spf=pass (google.com: domain of sender@test.domain.fr designates 162.38.xxx.xxx as permitted sender) smtp.mailfrom=sender@testdomain.fr
...
Received-SPF: pass (google.com: domain of sender@test.domain.fr designates YYY as permitted sender) client-ip=XXX;
Authentication-Results: mx.google.com;
       dkim=pass header.i=@test.domain.fr header.s=mail header.b=NF56conH;
       spf=pass (google.com: domain of sender@test.domain.fr designates YYY as permitted sender) smtp.mailfrom=sender@test.domain.fr
....
Received: from localhost (localhost [127.0.0.1])
    by ZZZ (Postfix) with ESMTP id 2B7D6827AF
    for <user@gmail.com>; Thu,  4 Jun 2020 15:59:24 +0200 (CEST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=
    test.domain.fr; h=subject:subject:message-id:from:from
    :x-mailer:content-type:content-type:date:date:mime-version
    :received:received; s=mail; t=1591279164; x=1593093565; bh=FJbfr
    tv+cxhW55iMi9reQkkVGvIcTprMdhm5f/b5NjE=; b=NF56conH//cSuNqwOJ2Qx
    AAIx0m6CtzVazzancbMjkp8clKsszxkbB67zS4t6szVjb2igT1BWrdjVhgJYjnU7
    SDEGthAZ7HEMJTz4giBNyoTFjACkX9PY8MRtTtLQoxiVda4ENdqOUw7a73EW2KnK
    AiH1a3T4jSQFVIlWBFIQxo=
...
Received: from ZZZ ([127.0.0.1])
    by localhost (ZZZ [127.0.0.1]) (amavisd-new, port 10024)
    with LMTP id bDCr7ASXtA3F for <user@gmail.com>;
    Thu,  4 Jun 2020 15:59:24 +0200 (CEST)
Received: from webmail.test.domain.fr (localhost [127.0.0.1])
    by ... (Postfix) with ESMTPSA id 002858278D
    for <user@gmail.com>; Thu,  4 Jun 2020 15:59:23 +0200 (CEST)
MIME-Version: 1.0
Date: Thu, 04 Jun 2020 13:59:23 +0000
Content-Type: multipart/alternative;
 boundary="--=_RainLoop_470_752577190.1591279163"
X-Mailer: RainLoop/1.14.0
From: sender@test.domain.fr
Message-ID: <18595cd57ad2e84a01ed8edf30eb02ea@test.domain.fr>
Subject: Rainloop HTMl DKIM
To: "user" <user@gmail.com>
X-Virus-Status: Clean

----=_RainLoop_470_752577190.1591279163
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable

Hello Word

----=_RainLoop_470_752577190.1591279163
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html><html><head><meta http-equiv=3D"Content-Type" content=3D"t=
ext/html; charset=3Dutf-8" /></head><body><div data-html-editor-font-wrap=
per=3D"true" style=3D"font-family: arial, sans-serif; font-size: 13px;"> =
<strong>Hello Word </strong><br><br><br><br><br><br><signature></signatur=
e> </div></body></html>

----=_RainLoop_470_752577190.1591279163--

I use Postfix + Amavisd-new (DKIM). So I suppose Rainloop sends correctly HTML messages.

ChristopherW commented 4 years ago

Salut @Philippe34, merci pour la réponse et le test.

I'm still not sure why the DKIM was only failing to validate in certain cases. I'll continue to run my own tests to see if I can figure out what the cause was.

andrewborell commented 4 years ago

Sorry im late to this party. I dont think its rainloop that would modify your header after it was queued in postfix ( or whatever smtp you use ). I would guess that the mail header is modified by a spam filter after its signed and before it leaves your mail server.