Skip to content

feat: support attachments when composing mail - #73

Open
bastigfz wants to merge 1 commit into
Delivr-Project:mainfrom
bastigfz:feat/compose-attachments
Open

feat: support attachments when composing mail#73
bastigfz wants to merge 1 commit into
Delivr-Project:mainfrom
bastigfz:feat/compose-attachments

Conversation

@bastigfz

@bastigfz bastigfz commented Sep 1, 2026

Copy link
Copy Markdown

No description provided.

@bastigfz
bastigfz requested a review from a team September 1, 2026 20:57
@LeiCraft
LeiCraft requested a lite review from Copilot September 2, 2026 07:17

Copilot AI 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.

🟡 Changes recommended

There are correctness issues in the mail route spec generation (z.toJSONSchema usage) and in the send flow where a null SMTP result can still return HTTP 200.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR adds support for composing and sending emails with attachments by accepting multipart/form-data on the mail creation endpoint, enforcing a configurable total attachment size limit, and ensuring draft sending relays the stored raw RFC822 source to preserve MIME structure.

Changes:

  • Add multipart/form-data support for POST .../mails with attachment ingestion and a max combined attachment size limit (DLA_MAX_ATTACHMENT_SIZE_MB).
  • Send drafts via SMTP using the exact stored message source (IMAPAccount.getMailSource() + SMTPAccount.sendRaw()), preserving attachments/inline parts.
  • Extend test coverage to validate multipart attachment creation and document the new env var in example.env.
File summaries
File Description
tests/helpers/preload.ts Sets DLA_MAX_ATTACHMENT_SIZE_MB for the test environment.
tests/api.routes.test.ts Adds an integration test that creates a multipart draft with an attachment and verifies attachment metadata.
src/utils/mails/backends/smtp.ts Adds sendRaw() to relay a stored RFC822 source via SMTP with an explicit envelope.
src/utils/mails/backends/imap.ts Adds getMailSource() to fetch a message’s raw RFC822 source from IMAP.
src/utils/config.ts Registers DLA_MAX_ATTACHMENT_SIZE_MB in the config schema.
src/api/versions/v1/routes/mail-accounts/mailboxes/mails/model.ts Defines an OpenAPI schema for multipart create-mail requests with attachments.
src/api/versions/v1/routes/mail-accounts/mailboxes/mails/index.ts Implements multipart parsing, size limiting, MailComposer attachment wiring, and raw-source sending for drafts.
example.env Documents DLA_MAX_ATTACHMENT_SIZE_MB and its default.
Review details

Suppressed comments (1)

src/api/versions/v1/routes/mail-accounts/mailboxes/mails/index.ts:176

  • z.toJSONSchema(...) is not used anywhere else in the repo and is likely not available on the Zod export; this can break OpenAPI generation or compilation. Use resolver(MailsModel.Create.Body) (from hono-openapi) for consistency with the rest of the API spec helpers.
                "application/json": { schema: z.toJSONSchema(MailsModel.Create.Body) as OpenAPIV3_1.SchemaObject },
  • Files reviewed: 8/8 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +19 to +20
import { ConfigHandler } from "../../../../../../../utils/config";
import type { OpenAPIV3_1 } from "openapi-types";
Comment on lines +395 to +398
// Send the exact stored source so MIME attachments and inline parts survive.
const source = await imap.getMailSource(mailbox.path, mailData.uid);
if (!source) return APIResponse.notFound(c, "Mail with specified UID not found");
const result = await smtp.sendRaw(source, mailData);
Comment on lines +88 to +92
const limit = maxAttachmentSize();
const totalSize = files.reduce((sum, file) => sum + file.size, 0);
if (totalSize > limit) {
return {
ok: false,
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