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

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>)

@github-actions

Copy link
Copy Markdown

Hello! Thank you for this proposed change to cloud-init. This pull request is now marked as stale as it has not seen any activity in 14 days. If no activity occurs within the next 7 days, this pull request will automatically close.

If you are waiting for code review and you are seeing this message, apologies! Please reply, tagging blackboxsw, and he will ensure that someone takes a look soon.

(If the pull request is closed and you would like to continue working on it, please do tag blackboxsw to reopen it.)

@github-actions github-actions Bot added the stale-pr Pull request is stale; will be auto-closed soon label Sep 19, 2026
@Benziza

Benziza commented Sep 19, 2026

Copy link
Copy Markdown
Author

Hi @blackboxsw, this PR is ready for review. Could you please take a look when you have a chance? Thank you!

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

Labels

stale-pr Pull request is stale; will be auto-closed soon

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant