Skip to content

Save attachments named after a path into subfolders - #53

Merged
odrobnik merged 3 commits into
mainfrom
fix/attachment-path-filenames
Oct 9, 2026
Merged

odrobnik merged 3 commits into
mainfrom
fix/attachment-path-filenames

Conversation

@odrobnik

@odrobnik odrobnik commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Outlook names a file attached from a folder after its Windows path: zpo-berufung\reference\akt.md. Once SwiftMail keeps those backslashes (Cocoanetics/SwiftMail#254), saving such a file goes wrong in two ways:

  • post attachment --output dir/ writes one file whose name contains backslashes.
  • post eml --part N --output dir/ goes through suggestedFilename, which strips \ and /, so the folders run together (zpo-berufungreferenceakt.md).

Separately, post attachment passed the sender's name straight to appendingPathComponent, so a name like ../../.zshrc could write outside the output directory.

Fix

  • New OutputPath.destination(for:attachmentNamed:), used by post attachment and post eml/msg --part. When --output names a directory, the attachment's name is split on \ and / and the file is written into those subfolders, which are created as needed. When --output names a file, nothing changes.
  • OutputPath.relativePath(forAttachmentNamed:) is the only place that decides what of a name is kept. It drops empty components, ., .. and a leading drive letter, sanitizes each component, and falls back to attachment. The result always stays inside the output directory.
  • The --output help for both commands says that folders in a name become subfolders.
  • destination(for:named:) is unchanged, so fetch, pdf and .eml exports behave as before.

Tests

  • OutputPathTests: an Outlook path becomes subfolders; traversal attempts (../../.zshrc, /etc/passwd, C:\…, UNC paths, ..\..) stay inside; plain names are unchanged; a file --output ignores the name.
  • Full suite: 67 tests pass (4 skipped, as on main).

Checked end to end with the real 74-attachment Outlook mail. post eml --part built against SwiftMail#254 saved zpo-berufung/training/README.md, …/training/entscheidungen/LIESMICH.md, …/judikatur/zpo-501.md and …/reference/aufbau.md, each byte-identical to the sender's ZIP.

Main is merged in, so this now builds on SwiftMail 1.16.0 (88c45cb, with #254). With that build, post attachment 21835 --output dir/ saved zpo-berufung/training/entscheidungen/LIESMICH.md and zpo-berufung/training/muster/LIESMICH.md as two separate files from the real mail.

🤖 Generated with Claude Code

Outlook names a file attached from a folder after its Windows path
(zpo-berufung\reference\akt.md). When --output names a directory,
`post attachment` and `post eml --part` now split such a name on \ and /
and write the file into those subfolders, instead of one file with
backslashes in its name (attachment) or the folders run together
(eml --part, through suggestedFilename).

Only relativePath(forAttachmentNamed:) decides what of a sender's name is
used: empty components, ".", ".." and a leading drive letter are dropped
and each component is sanitized, so a name can no longer reach outside
the output directory ("../../x" used to go straight into
appendingPathComponent).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T11:02:10.512479Z b3402fe PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b3402fed6d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/post/Commands/LocalMessageFile.swift Outdated
Comment thread Sources/post/Commands/LocalMessageFile.swift Outdated
odrobnik and others added 2 commits October 9, 2026 13:07
`part.filename ?? part.suggestedFilename` took `filename=""` as the name,
which relativePath turned into a bare `attachment`. An empty name now
counts as none, in `post eml/msg --part` and in downloadAttachment, so
the part is named `part_2.pdf` as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@odrobnik
odrobnik merged commit fa06c53 into main Oct 9, 2026
2 checks passed
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