Skip to content

fix(make-mime): preserve non-ASCII attachment filenames - #7071

Open
Benziza wants to merge 1 commit into
canonical:mainfrom
Benziza:fix/make-mime-unicode-filenames
Open

fix(make-mime): preserve non-ASCII attachment filenames#7071
Benziza wants to merge 1 commit into
canonical:mainfrom
Benziza:fix/make-mime-unicode-filenames

Conversation

@Benziza

@Benziza Benziza commented Sep 5, 2026

Copy link
Copy Markdown

Proposed Commit Message

fix(make-mime): preserve non-ASCII attachment filenames

Additional Context

make-mime loses filenames such as café.yaml and إعداد.yaml when its output is parsed: get_filename() returns None, and UserDataProcessor substitutes part-001. The attachment content is preserved.

Pass filename separately to add_header so Python applies RFC 2231 encoding, matching the existing pattern in cloudinit/user_data.py. No CLI options change.

Test Steps

tox -e py3 -- tests/unittests/cmd/devel/test_make_mime.py --no-cov
tox -e py3
tox -e check_format
  • Regression tests: 4 failures before the fix; all 12 cases pass afterward on Python 3.12 and 3.14, covering ASCII and Unicode filenames, content type, and payload.
  • Full unit suite (Python 3.14): 5759 passed, 6 skipped, 13 xfailed.
  • Formatting and checks on the changed files pass. Full check_format remains unsuccessful locally: Python 3.12 reports Pylint E1120 in cloudinit/util.py:2142 (also reproduced on unmodified main), while Python 3.14 reports missing crypt imports in unchanged files.
CLI reproduction

Run from the checkout after creating the tox test environment. No VM is required.

.tox/py3/bin/python - <<'PY'
import email
import subprocess
import sys
import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as directory:
    path = Path(directory) / "café.yaml"
    path.write_text("#cloud-config\nhostname: example\n", encoding="utf-8")
    result = subprocess.run(
        [sys.executable, "-m", "cloudinit.cmd.devel.make_mime",
         "-a", str(path) + ":cloud-config"],
        capture_output=True, text=True, check=True,
    )
    part = email.message_from_string(result.stdout).get_payload()[0]
    print("Parsed filename:", part.get_filename())
    assert part.get_filename() == str(path)
    assert part.get_payload(decode=True) == path.read_bytes()
PY

Before the fix, the filename assertion fails because the parsed filename is None. Afterward, both assertions pass. Temporary files are cleaned up automatically.

Merge type

  • Squash merge using "Proposed Commit Message"
  • Rebase and merge unique commits. Requires commit messages per-commit each referencing the pull request number (#<PR_NUM>)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant