Skip to content

HTML body emitted as 8bit on a single >998-octet line breaks DKIM (regression 1.6.15 → 1.7.1) ---> DKIM FAIL #10198

Description

@ShaiMagal

Prerequisites

  • I have searched for duplicate or closed issues
  • I can recreate the issue with all plugins disabled

Describe the issue


Environment

  • Roundcube 1.7.1 (upgraded from 1.6.15)
  • Submission to a local Postfix; DKIM signing via Rspamd milter at submission time

Description

After upgrading 1.6.15 → 1.7.1, HTML emails containing a long HTML signature fail DKIM at the recipient with body hash did not verify. The same signature/content composed in 1.6.15 passes DKIM fine. Downgrading back to 1.6.15 makes the problem disappear, so this looks like a regression in how 1.7.x serializes the message body.

Root cause (analyzed from the raw message)

In 1.7.1 the text/html part is emitted as Content-Transfer-Encoding: 8bit with the body on a single physical line exceeding 998 octets (in our case ~2000+ octets — the whole signature paragraph with inline <img>/links on one line).

RFC 5322 §2.1.1 requires body lines to be ≤ 998 octets. Because 1.7.1 emits longer lines, any MTA in the path that enforces the line-length limit wraps the line (inserts CRLF) — and since this happens after DKIM signing, the body hash no longer matches → DKIM fails. The inserted fold survives relaxed body canonicalization (the whitespace at the fold point is not stripped), so the failure is deterministic, not transient.

1.6.15 does not produce >998-octet body lines with identical content, hence it works.

Steps to reproduce

  1. Roundcube 1.7.1, HTML compose, set an HTML signature long enough that the rendered HTML body contains a single line > 998 octets (e.g. a signature with several inline images/links).
  2. Send to any DKIM-verifying recipient (e.g. Gmail).
  3. Recipient reports dkim=... (body hash did not verify).
  4. Compose the same content in 1.6.15 → passes.

Workaround (confirmed working on 1.7.1)

$config['force_7bit'] = true;

This forces quoted-printable, which soft-wraps at 76 columns, so no body line exceeds 998 octets and nothing gets re-wrapped after signing. After enabling it, the text/html part is Content-Transfer-Encoding: quoted-printable and DKIM passes.

Question for maintainers

Did HTML body line-wrapping/encoding change between 1.6 and 1.7? Emitting HTML body lines > 998 octets in 8bit mode is non-conformant (RFC 5322 §2.1.1) and breaks DKIM in any normal mail path that enforces the SMTP line-length limit. Should long body lines be wrapped (or QP-encoded) by default even in 8bit mode?

I can share the exact signature / raw message privately (not public) on request.

What browser(s) are you seeing the problem on?

No response

What version of PHP are you using?

8.5

What version of Roundcube are you using?

1.17.1

JavaScript errors

No response

PHP errors

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions