Postfix – DKIM Signature Failure Only on CRON Jobs

gmailopendkimpostfixubuntu-18.04

I originally posted this on askubuntu but there's been no response there.


I have successfully installed Postfix and OpenDkim on my server, and it's correctly signing mail from several different domains. The host we'll call webhost.example.com. It's running Ubuntu 18.04.2 LTS, Postfix 3.3.0 and OpenDKIM v2.11.0

Today I wanted to get output from some CRON jobs sent to my Gmail account so I set up the required entries in the KeyTable and SigningTable and generated the keys and tested it with a one line email to myself.

echo "Test message" | mail -s "Test message" fred.bloggs@example.com

This should generate an email from ubuntu@webhost.example.com. It does, correctly signed by OpenDKIM, and delivered to my Gmail account where it successfully passes validation.

Here's what I get at GMail:

Delivered-To: fred.bloggs@example.com
Received: by 2002:a5d:48c4:0:0:0:0:0 with SMTP id p4csp257074wrs;
        Tue, 19 Mar 2019 21:00:38 -0700 (PDT)
X-Google-Smtp-Source: APXvYqzzFOWDKe9HXwsYXMKgDAYZjyoHVQj0EcFTzj7zrlnhiY0QBCN2DaEXqiXjh8T71ZiLDzqc
X-Received: by 2002:a62:5789:: with SMTP id i9mr27645136pfj.75.1553054437831;
        Tue, 19 Mar 2019 21:00:37 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1553054437; cv=none;
        d=google.com; s=arc-20160816;
        b=bBqJW5ba0CKQdhBlKSOmx8A+D++aHf/NwbCWSD5V0Mq/+E2NSAwtSU9Yi/sOpp0dAl
         VZ2fbB1PNjhB1KGTT2vwoOambDbYUwWB2nIMG5w3aFlUVoOFgYLmLFZwHx6EeTm+nKbQ
         tu6XzdsjT0Vl9HtH44hXed4WU5eRe4KGcblkKSswF3xQ3k57PPOSOea0qdqSN+K3Usj1
         yv9B81pxTRKdBa3Ihkxmy6q0BPfiwwVRD1rb22/swhC/QS7O7M/9AKGxlxBhl1zgks9a
         55Sm1ghGyN3HFoDlZ8bWNo0qImV4bQPsDaTVDykueHOxC2tXBdxA8559io4QKwBU2yc1
         TFFA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=from:date:message-id:to:subject:dkim-signature;
        bh=vMryiu7Ey0Nro6WC0HJ1+2DMJ4hQ10+LmaSady45MSs=;
        b=RN6/AsO7ejyBlwkSuPyLIgktIttKp2ar60+D0vyf4Le/RP543qL/OQUSC5su1tbc7l
         fbEaCSnDuuBpB0OlJiBjQHeu0y3+FvK4cjmElRgPMyMFbk3q6PxbEXLrgeKs9tiKFHSG
         TFAu+Czb32yhOVgmJQNwQ4cpyOKEZmfz7eXFwXBvw69D4qGUrW6q7j54xoQGl8kTVDM5
         kUz/N4JoiS9rAFNxft/fg0druQaoMCFhuPR8d5a7NYJBp3vV+bWyonLD2kGbqxFujU97
         RjAMko+eMvuWS7zWOnqYF3Di3MyGDLBlue4+rXz65o0VxrTS/MZhsKZFG/LzlBdi4vPF
         0thA==
ARC-Authentication-Results: i=1; mx.google.com;
       dkim=pass header.i=@webhost.example.com header.s=webhost header.b=eMU0P6hB;
       spf=pass (google.com: domain of ubuntu@webhost.example.com designates 13.238.180.128 as permitted sender) smtp.mailfrom=ubuntu@webhost.example.com;
       dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=example.com
Return-Path: <ubuntu@webhost.example.com>
Received: from webhost.example.com (ec2-13-238-180-128.ap-southeast-2.compute.amazonaws.com. [13.238.180.128])
        by mx.google.com with ESMTP id j134si770928pgc.42.2019.03.19.21.00.37
        for <fred.bloggs@example.com>;
        Tue, 19 Mar 2019 21:00:37 -0700 (PDT)
Received-SPF: pass (google.com: domain of ubuntu@webhost.example.com designates 13.238.180.128 as permitted sender) client-ip=13.238.180.128;
Authentication-Results: mx.google.com;
       dkim=pass header.i=@webhost.example.com header.s=webhost header.b=eMU0P6hB;
       spf=pass (google.com: domain of ubuntu@webhost.example.com designates 13.238.180.128 as permitted sender) smtp.mailfrom=ubuntu@webhost.example.com;
       dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=example.com
Received: by webhost.example.com (Postfix, from userid 1000)
    id 3E9A8FA106; Wed, 20 Mar 2019 04:00:36 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
    d=webhost.example.com; s=webhost; t=1553054436;
    bh=vMryiu7Ey0Nro6WC0HJ1+2DMJ4hQ10+LmaSady45MSs=;
    h=Subject:To:Date:From:From;
    b=eMU0P6hBtTMDVSU5aw1dTR7CSlrBSHjK4And4uaFeo+HnSnD5+bBAKObTk3WxeLgr
     Tf/1/httpjXNUdphU5STlFSqeunuZJafxDqLVzuoYHJOCuQ8vfGoZqyI2hGaJ9ql8E
     dSp1j1mOVRBYC8KpSYbnA+Uc2+ut68mQDDRc2pZQWdQLzmxWwCiz+tAAXdHQFVsx+D
     sobOHN/cq9CgJNkEs0qnjsE9zdnTdMrO+1AbnJBCHKeQBZAoDdg4OjjlMmg4kTmLli
     fyVtcYBHaY8OjM15qiKL0YvjzfnCP50L7VjT9EBAhtJn2d9lYGyhQ/sLbwx91nL/yG
     OTxMRE82pD6wQ==
Subject: This is a test message
To: <fred.bloggs@example.com>
X-Mailer: mail (GNU Mailutils 3.4)
Message-Id: <20190320040036.3E9A8FA106@webhost.example.com>
Date: Wed, 20 Mar 2019 04:00:36 +0000 (UTC)
From: Ubuntu <ubuntu@webhost.example.com>

This is a test message. You know the drill!

So far, so good.

I set up my cron jobs and add the line

MAILTO=fred.bloggs@example.com

The output is generated, signed and mailed, but GMail fails the DKIM validation with

dkim=neutral (body hash did not verify) header.i=@webhost.example.com header.s=webhost header.b=tXJM8ih0;

Here's the complete email. If it's useful this is output from a curl request.

Delivered-To: fred.bloggs@example.com
Received: by 2002:a5d:48c4:0:0:0:0:0 with SMTP id p4csp776152wrs;
        Wed, 20 Mar 2019 07:14:04 -0700 (PDT)
X-Google-Smtp-Source: APXvYqyZdMJuwpApjkjfxfh/rsHg67hLBtQSS5j0BUCq8NaaxUqV+sIDf7CPy+sYjS2b817v9pAu
X-Received: by 2002:a63:5541:: with SMTP id f1mr7627593pgm.38.1553091244323;
        Wed, 20 Mar 2019 07:14:04 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1553091244; cv=none;
        d=google.com; s=arc-20160816;
        b=h3SPkfLIm9BjWS+SlJc4Wd/8XFE2YT3QNSOkzzLY858wldyOXMn3OR8rFcU6UVmbEL
         stCPHuXM7ouP0s7ICTC4TAyv+DiqWNokBsRkwXjdP6+mEEmXlP6VUk8H/+nL89BrMp4E
         FhzVM4sE5/3VphjuXPom0Ux+e+WrLDWBZbKMbMOLSMkbmCL6B3/llK3FMwPfAGPzS2O8
         o+cfm6r15W0aND02eIvNg6px2kNmD+wHAI993/BZJ3vIPvNzsEHFUWwbD10iYkIUwmvA
         DMUVB3jx+pXtFhv17+Fpx0zsSx5806vieOVoLxXAnlJgdykNH/DuZY3NM1DVyR1Renxw
         eTPg==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=date:message-id:content-transfer-encoding:mime-version:subject:to
         :from:dkim-signature;
        bh=lkMik4Dz2hOPxvMLwTHlE8QE1l4G/X7DcjAYikPMEMc=;
        b=N85+olM3406vk7LhpV03QNxCZQLELh+ZLjUIUg1xt5u7z/aJZS0CRa1q4JJcBn8Fm0
         nRBvMLFJXIrm0Y11s5kET6Xvzkk9G/szfJNqthy7e80mHs2Q7xgfYeVpYmQmL3DxjVjm
         mzlnJVzVyx0XLMcAKaneb0CkOIsuOo6nkCGMakPsS9e+vMpfdnBggZZQv1zqkGHzTnML
         +QMIVMEH7kgQphYo6GiCVb1LWThuwYyI+nSclPDw9fNLRPGTNqbiBqWQuEdgM3/K46Zy
         gY4SgTXwL+MOCVgIbN33ZG3FuVHwyr5bQZGrpR48HXS68zYA5jbcgF9eFDBtuBOQPDo+
         HkKw==
ARC-Authentication-Results: i=1; mx.google.com;
       dkim=neutral (body hash did not verify) header.i=@webhost.example.com header.s=webhost header.b=tXJM8ih0;
       spf=pass (google.com: domain of ubuntu@webhost.example.com designates 13.238.180.128 as permitted sender) smtp.mailfrom=ubuntu@webhost.example.com;
       dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=example.com
Return-Path: <ubuntu@webhost.example.com>
Received: from webhost.example.com (ec2-13-238-180-128.ap-southeast-2.compute.amazonaws.com. [13.238.180.128])
        by mx.google.com with ESMTP id b7si1705816pgl.20.2019.03.20.07.14.03
        for <fred.bloggs@example.com>;
        Wed, 20 Mar 2019 07:14:04 -0700 (PDT)
Received-SPF: pass (google.com: domain of ubuntu@webhost.example.com designates 13.238.180.128 as permitted sender) client-ip=13.238.180.128;
Authentication-Results: mx.google.com;
       dkim=neutral (body hash did not verify) header.i=@webhost.example.com header.s=webhost header.b=tXJM8ih0;
       spf=pass (google.com: domain of ubuntu@webhost.example.com designates 13.238.180.128 as permitted sender) smtp.mailfrom=ubuntu@webhost.example.com;
       dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=example.com
Received: by webhost.example.com (Postfix, from userid 1000)
    id 0FACCFA104; Wed, 20 Mar 2019 14:14:02 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
    d=webhost.example.com; s=webhost; t=1553091242;
    bh=20rEKrmO1yPqlIJwX4HLsjr/kx4SaM/AaK17/OmPhLA=;
    h=From:To:Subject:Date:From;
    b=tXJM8ih006AjxwXJNAD30k7Fjo/HYTsi5bEfOCaxr0D8BiEAA/mIiDvaexjHPWNQ6
     B5DrCGlhvLVZIRs1Zp2v4pbYYYvpmrzOTB99vXk0lEEGTRIwdhvAYKT31Jt2N5VMq3
     hifps7hj3TD/Eevks82VvcIu2xJWXFPNEZMGvjcRa3hFSE2IIcfOhMJhwX5Rcnx+F4
     wjtxqROgxXpHxgJkXzkVe3HbpKVK5eOrsBoeRnUhR4SWa2f7UKhT4k28KOuTQo8bG3
     E63PoPwcOQU4cPiiqnPEdWO7ERvSHetgh/1yjpigcbch9SWwQHwA4FPSmcfOfLeIov
     +wxrbVKHXtzMA==
From: root@webhost.example.com (Cron Daemon)
To: fred.bloggs@example.com
Subject: Cron <ubuntu@webhost> curl https://invoicing2018.example.com/tasks/run
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Cron-Env: <MAILTO=fred.bloggs@example.com>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/home/ubuntu>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=ubuntu>
Message-Id: <20190320141402.0FACCFA104@webhost.example.com>
Date: Wed, 20 Mar 2019 14:14:02 +0000 (UTC)

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0

The emails from cron also fail the Port25 verifier in the same way

So, the question is:

Why does my DKIM configuration correctly sign everything but output from CRON?

What can I do to fix this?

I could try using a script to run the curl request and send the email with mail, but I have a number of other cron jobs to add yet and I'd rather fix the underlying problem before trying work-arounds.

Best Answer

The authentication results done by mx.google.com imply there's something different in the respecitve body between the messages you send on the command line and the ones which are send by a cron job: "body hash did not verify".

One common problem with OpenDKIM are irregular line endings. RFC 5322 states that "CR and LF MUST only occur together as CRLF; they MUST NOT appear independently in the body." So maybe the messages send by you manually have correct line endings, but the ones send by a cron job do not. You can try to set "FixCRLF yes" in the config of OpenDKIM.

Despite whether this is the cause, you can enable "KeepTemporaryFiles" in OpenDKIM: "Instructs the filter to create temporary files containing the header and body canonicalizations of messages that are signed or verified. The location of these files can be set using the TemporaryDirectory parameter. Intended only for debugging verification problems." That way you can compare the original body and the one delivered to GMail and probably find out what's the difference that causes the validation error.