-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Attachment support for Resend "Send Email" Action #18284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
WalkthroughAdds attachment support to the Resend Send Email action: accepts file paths and base64 inputs, constructs an attachments array (from resolved file streams and base64 pairs), validates base64 filename pairing, adds a stream-to-buffer helper, imports file utilities and ConfigurationError, and bumps action and package versions. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant A as SendEmail Action
participant FS as getFileStreamAndMetadata
participant B as streamToBuffer
participant R as Resend API
U->>A: run(props including attachmentFiles, attachmentsBase64, base64AttachmentFilenames)
alt attachmentsBase64 provided
A->>A: Validate lengths match
alt mismatch
A-->>U: throw ConfigurationError
end
end
opt attachmentFiles provided
loop for each filePath
A->>FS: getFileStreamAndMetadata(filePath)
FS-->>A: { stream, metadata(name) }
A->>B: streamToBuffer(stream)
B-->>A: Buffer
A->>A: encode Buffer → base64, push { filename: metadata.name, content: base64 } to attachments
end
end
opt base64 attachments provided
A->>A: pair filenames with base64 strings, push { filename, content } to attachments
end
A->>R: POST /emails (body includes attachments)
R-->>A: response
A-->>U: result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Assessment against linked issues
Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/resend/actions/send-email/send-email.ts (1)
46-46: Fix label typo: "CCc" → "Cc"User-facing label is misspelled.
- label: "CCc", + label: "Cc",
🧹 Nitpick comments (6)
components/resend/actions/send-email/send-email.ts (6)
96-96: Add a type toattachmentsfor better TS safetyExplicit typing prevents accidental shape drift.
- const attachments = []; + const attachments: { filename: string; content: string }[] = [];
82-89: Type thestreamToBufferparameterImproves editor/TS checks and intent clarity.
- async streamToBuffer(stream): Promise<Buffer> { + async streamToBuffer(stream: NodeJS.ReadableStream): Promise<Buffer> {
123-136: Only includeattachmentswhen non-emptyKeeps payload minimal and avoids sending an empty array.
- const params = { - $, - data: { - from, - to, - subject, - html, - text, - cc, - bcc, - reply_to: replyTo, - attachments, - }, - }; + const data: Record<string, any> = { + from, + to, + subject, + html, + text, + cc, + bcc, + reply_to: replyTo, + }; + if (attachments.length) data.attachments = attachments; + const params = { $, data };
45-45: Consider arrays for cc/bcc/reply-to to match APIResend accepts
string | string[]forcc,bcc, andreply_to. Mirroringtoas arrays improves consistency. If you prefer not to change the UI, consider accepting both and normalizing before send. (resend.com)- cc: { - type: "string", + cc: { + type: "string[]", @@ - bcc: { - type: "string", + bcc: { + type: "string[]", @@ - replyTo: { - type: "string", + replyTo: { + type: "string[]",Also applies to: 51-51, 57-57
96-109: Optional: includecontent_typewhen availableIf
metadata.typeis present, pass it ascontent_typeto improve client previews. (resend.com)- attachments.push({ - filename: metadata.name, - content: base64, - }); + attachments.push({ + filename: metadata.name, + content: base64, + ...(metadata.type ? { content_type: metadata.type } : {}), + });
62-79: Optional: fail fast on oversize attachmentsResend limits emails to 40MB total after Base64 encoding; consider validating cumulative size and throwing a helpful error. (resend.com)
Also applies to: 111-121
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (2)
components/resend/actions/send-email/send-email.ts(3 hunks)components/resend/package.json(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
- GitHub Check: pnpm publish
- GitHub Check: Lint Code Base
🔇 Additional comments (3)
components/resend/package.json (1)
3-3: Version bump LGTMPackage version updated to 0.1.2 — no concerns.
components/resend/actions/send-email/send-email.ts (2)
3-5: New imports LGTMUsing
getFileStreamAndMetadataandConfigurationErroris appropriate for the new attachment flow.
12-12: Action version bump LGTMBumped to 0.0.2 as expected for the new feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
components/resend/actions/send-email/send-email.ts (1)
111-121: Guard against undefinedbase64AttachmentFilenames(prevents TypeError) and improve error messageIf
attachmentsBase64is set without filenames,base64AttachmentFilenames.lengththrows. Also keep the loop zero-based (good) and retainfilename.- if (attachmentsBase64) { - if (attachmentsBase64.length !== base64AttachmentFilenames.length) { - throw new ConfigurationError("The number of base64-encoded attachments must match the number of base64-encoded attachment filenames"); - } - for (let i = 0; i < attachmentsBase64.length; i++) { - attachments.push({ - filename: base64AttachmentFilenames[i], - content: attachmentsBase64[i], - }); - } - } + if (attachmentsBase64?.length) { + if (!base64AttachmentFilenames?.length || + attachmentsBase64.length !== base64AttachmentFilenames.length) { + throw new ConfigurationError( + `The number of base64 attachments must match the number of filenames (attachmentsBase64=${attachmentsBase64.length}, base64AttachmentFilenames=${base64AttachmentFilenames?.length ?? 0})`, + ); + } + for (let i = 0; i < attachmentsBase64.length; i++) { + attachments.push({ + filename: base64AttachmentFilenames[i], + content: attachmentsBase64[i], + }); + } + }
🧹 Nitpick comments (4)
components/resend/actions/send-email/send-email.ts (4)
82-89: Type the stream param for clarityMinor: add an explicit Node stream type.
- async streamToBuffer(stream): Promise<Buffer> { + async streamToBuffer(stream: NodeJS.ReadableStream): Promise<Buffer> {
97-109: Parallelize file reads and add filename fallbackReading files sequentially can be slow with many attachments. Also guard when
metadata.nameis missing.- if (attachmentFiles) { - for (const file of attachmentFiles) { - const { - stream, metadata, - } = await getFileStreamAndMetadata(file); - const buffer = await this.streamToBuffer(stream); - const base64 = buffer.toString("base64"); - attachments.push({ - filename: metadata.name, - content: base64, - }); - } - } + if (attachmentFiles?.length) { + const fileAttachments = await Promise.all(attachmentFiles.map(async (file) => { + const { stream, metadata } = await getFileStreamAndMetadata(file); + const buffer = await this.streamToBuffer(stream); + return { + filename: metadata?.name ?? "attachment", + content: buffer.toString("base64"), + }; + })); + attachments.push(...fileAttachments); + }
123-136: Avoid sending an emptyattachmentsarraySome APIs are picky about empty arrays. Only include the field when non-empty.
- const params = { - $, - data: { - from, - to, - subject, - html, - text, - cc, - bcc, - reply_to: replyTo, - attachments, - }, - }; + const data: Record<string, any> = { + from, + to, + subject, + html, + text, + cc, + bcc, + reply_to: replyTo, + }; + if (attachments.length) data.attachments = attachments; + const params = { $, data };
69-79: Optional: accept data URLs forattachmentsBase64Users often paste data URLs (e.g., "data:application/pdf;base64,...."). Strip the prefix before sending.
- for (let i = 0; i < attachmentsBase64.length; i++) { - attachments.push({ - filename: base64AttachmentFilenames[i], - content: attachmentsBase64[i], - }); - } + for (let i = 0; i < attachmentsBase64.length; i++) { + const raw = attachmentsBase64[i] ?? ""; + const content = raw.startsWith("data:") ? (raw.split(",", 2)[1] ?? "") : raw; + attachments.push({ + filename: base64AttachmentFilenames[i], + content, + }); + }Also applies to: 111-121
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
components/resend/actions/send-email/send-email.ts(4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Lint Code Base
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
🔇 Additional comments (2)
components/resend/actions/send-email/send-email.ts (2)
3-5: Good import additionsImporting
getFileStreamAndMetadataandConfigurationErroris correct and used appropriately.
46-46: Typo fix LGTMLabel corrected to "Cc".
Resolves #18213
Summary by CodeRabbit
New Features
Bug Fixes
Chores