Skip to content

feat: add custom return path flag and CID/URL attachment syntax#352

Merged
felipefreitag merged 2 commits into
mainfrom
feat-return-path-and-cid-attachments
Jul 23, 2026
Merged

feat: add custom return path flag and CID/URL attachment syntax#352
felipefreitag merged 2 commits into
mainfrom
feat-return-path-and-cid-attachments

Conversation

@felipefreitag

@felipefreitag felipefreitag commented Jul 22, 2026

Copy link
Copy Markdown
Member

Summary

Closes two gaps where the CLI couldn't express features the SDK already supports:

  • domains create --custom-return-path <subdomain> — same flag domains claim create already has; sets the Return-Path subdomain (e.g. bounce) at creation.

  • Inline/CID and hosted-URL attachments on emails send--attachment now accepts optional curl-style suffix params, and https:// values are passed as hosted attachments:

    resend emails send ... --html "<img src=cid:logo>" --attachment "./logo.png;cid=logo;type=image/png"
    resend emails send ... --attachment "https://example.com/report.pdf;filename=report.pdf;type=application/pdf"
  • --attachments-file <path|-> — JSON-array escape hatch (file or stdin) for scripted use or paths containing a literal ;key=; accepts both snake_case and camelCase fields, mirroring emails batch --file.

Design notes

  • The parser splits only on recognized ;cid= / ;type= / ;filename= tokens, so Windows paths, plain semicolons/equals, and MIME parameters (type=text/plain;charset=utf-8) parse correctly. Unrecognized ;key= errors (invalid_attachment) instead of silently mis-attaching.
  • Suffix values must be double-quoted — the only quoting form that works across bash, PowerShell, and cmd. Help text, SKILL.md, and all examples reflect that.
  • Dry-run now shows contentId/contentType/path per attachment; raw content stays redacted as byteLength.
  • domains update is untouched: the SDK's UpdateDomainsOptions has no customReturnPath.
  • Documented two API quirks discovered while testing: an unreachable attachment URL fails the email after the send returns an ID, and filename/MIME type are not derived from URLs (stored as attachment-0 / application/octet-stream).

Testing

  • 14 new parser unit tests, 9 new command tests; full suite: 1070 passed, typecheck and lint clean.
  • Verified against the live API: CID attachment round-tripped with content_id: "logo" and content_disposition: "inline"; base64 JSON-file attachment delivered; hosted-URL attachment (sample invoice.pdf) delivered; domains create --custom-return-path bounce returned SPF/MX records on bounce.<domain> instead of the default send. (test domain deleted afterwards).

Summary by cubic

Adds --custom-return-path to domains create and extends emails send to support CID/URL attachments and a JSON attachments file. Tightens attachment parsing and improves dry-run output.

  • New Features

    • domains create --custom-return-path <subdomain> sets the Return-Path subdomain (e.g., bounce).
    • emails send --attachment accepts ;cid=, ;type=, ;filename= suffixes and https:// URLs as hosted attachments (quote values).
    • --attachments-file <path|-> reads a JSON array of attachments; snake_case and camelCase fields are accepted.
    • Dry-run prints attachment metadata (contentId, contentType, path) with content redacted as byteLength. For URL attachments, the API fetches after send; pass ;filename= and ;type=, and check failures with emails get <id>.
  • Bug Fixes

    • Rejects unknown or duplicate ;key= params (except MIME params in ;type=) with invalid_attachment.
    • Errors on an empty --attachments-file, including in the --template conflict check.
    • Forwards an explicit empty --custom-return-path to the API.

Written for commit d74616f. Summary will update on new commits.

Review in cubic

- domains create: new --custom-return-path <subdomain> flag (same as
  domains claim create)
- emails send --attachment: optional ;cid=, ;type=, ;filename= params
  on paths, plus https:// URLs passed as hosted attachments
- emails send --attachments-file: JSON array escape hatch (file or
  stdin) accepting snake_case and camelCase fields
- dry-run now summarizes contentId/contentType/path (content stays
  redacted as byteLength)
- document URL attachment caveats (async fetch failure, no derived
  filename/type) in help text and agent skill

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 9 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/commands/emails/send.ts">

<violation number="1" location="src/commands/emails/send.ts:325">
P2: Unknown suffixes following a valid suffix are accepted as part of the preceding value, so `--attachment "a.png;cid=logo;foo=bar"` does not return `invalid_attachment`. Validate parameter-like tokens in every suffix value (while preserving MIME parameters in `;type=`) before constructing metadata.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

(value) => {
let spec: AttachmentSpec;
try {
spec = parseAttachmentSpec(value);

@cubic-dev-ai cubic-dev-ai Bot Jul 22, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Unknown suffixes following a valid suffix are accepted as part of the preceding value, so --attachment "a.png;cid=logo;foo=bar" does not return invalid_attachment. Validate parameter-like tokens in every suffix value (while preserving MIME parameters in ;type=) before constructing metadata.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/commands/emails/send.ts, line 325:

<comment>Unknown suffixes following a valid suffix are accepted as part of the preceding value, so `--attachment "a.png;cid=logo;foo=bar"` does not return `invalid_attachment`. Validate parameter-like tokens in every suffix value (while preserving MIME parameters in `;type=`) before constructing metadata.</comment>

<file context>
@@ -295,21 +318,58 @@ export const sendCommand = new Command('send')
+      (value) => {
+        let spec: AttachmentSpec;
+        try {
+          spec = parseAttachmentSpec(value);
+        } catch (err) {
+          return outputError(
</file context>
Fix with cubic

Comment thread src/commands/emails/send.ts Outdated
Comment thread src/lib/attachments.ts Outdated
Comment thread src/commands/domains/create.ts Outdated
- reject stray ;key= tokens inside cid and filename values (type stays
  permissive for MIME parameters)
- stop silently ignoring an explicit empty --attachments-file value,
  including in the --template conflict check
- forward explicit empty --custom-return-path to the API
- mention camelCase aliases in the unsupported-field error
@felipefreitag
felipefreitag merged commit 6a2d0c7 into main Jul 23, 2026
18 of 19 checks passed
@felipefreitag
felipefreitag deleted the feat-return-path-and-cid-attachments branch July 23, 2026 11:21
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.

2 participants