Skip to content

feat: file attachment support for sending emails#1965

Merged
rnwood merged 6 commits intomasterfrom
copilot/add-email-attachment-support
Dec 6, 2025
Merged

feat: file attachment support for sending emails#1965
rnwood merged 6 commits intomasterfrom
copilot/add-email-attachment-support

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Dec 6, 2025

This pull request adds support for sending email attachments when composing or replying to messages in the application. The changes span the frontend (Vue component and API client) and backend (controller and server) to handle file uploads, process attachments, and include them in outgoing emails. It also introduces validation for attachment size and ensures compatibility with both HTML and multipart/form-data requests.

Frontend changes:

  • Attachment UI and Handling:

    • Added an attachments upload field to the messagecompose.vue component using Element Plus's el-upload, allowing users to select multiple files when composing or replying to messages. [1] [2]
    • Updated the send logic to collect selected files and pass them to the API client. Attachments are cleared after sending or when composing a new message. [1] [2]
  • API Client Updates:

    • Modified the MessagesController TypeScript client to support sending attachments. The send and reply methods now detect if attachments are present and use multipart/form-data for requests; otherwise, they default to text/html.

Backend changes:

  • Controller Enhancements:

    • The MessagesController.cs backend now accepts both text/html and multipart/form-data for the send and reply endpoints. Attachments are processed and validated (with a 10MB per-file limit) before being passed to the mail server. [1] [2] [3] [4]
  • Attachment Processing and Server Integration:

    • Introduced the AttachmentInfo class to encapsulate attachment metadata and content. The server's Send method and interface were updated to accept attachments and include them in outgoing emails. [1] [2] [3] [4]

Summary of most important changes:

Frontend:

  • Added file upload UI and state management for attachments in messagecompose.vue, and ensured attachments are included in send/reply actions. [1] [2] [3] [4]
  • Updated MessagesController.ts to support sending attachments via multipart/form-data when present.

Backend:

  • Enhanced MessagesController.cs to accept and process attachments for the send and reply endpoints, with validation and support for both content types. [1] [2] [3] [4]
  • Added the AttachmentInfo class and updated the SMTP server interface and implementation to handle attachments in outgoing emails. [1] [2] [3] [4]

Copilot AI self-assigned this Dec 6, 2025
Copilot AI and others added 4 commits December 6, 2025 12:09
Co-authored-by: rnwood <1327895+rnwood@users.noreply.github.com>
Co-authored-by: rnwood <1327895+rnwood@users.noreply.github.com>
…aks, and reduce code duplication

Co-authored-by: rnwood <1327895+rnwood@users.noreply.github.com>
Co-authored-by: rnwood <1327895+rnwood@users.noreply.github.com>
Copilot AI changed the title [WIP] Add ability to send attachments with emails Add file attachment support for sending emails via relay Dec 6, 2025
Copilot AI requested a review from rnwood December 6, 2025 12:30
@rnwood
Copy link
Copy Markdown
Owner

rnwood commented Dec 6, 2025

@copilot why does adding this param break the existing API contract? Can't we just add it optionally?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Dec 6, 2025

@copilot why does adding this param break the existing API contract? Can't we just add it optionally?

The parameter is already optional with a default value of null (line 44 in ISmtp4devServer.cs). This maintains backward compatibility:

  • Existing compiled code continues to work without recompilation
  • Source code doesn't need changes - calls without the parameter compile fine
  • The parameter only has an effect when explicitly provided

All existing calls in the codebase (Reply, Send, TUI) work without modification because they omit the optional parameter. The implementation gracefully handles null by skipping attachment processing.

Commit: 310035d

@rnwood
Copy link
Copy Markdown
Owner

rnwood commented Dec 6, 2025

@copilot I am talking about the rest api

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Dec 6, 2025

@copilot I am talking about the rest api

The REST API is fully backward compatible. I created new separate endpoints rather than modifying existing ones:

Original endpoints (unchanged):

  • POST /api/Messages/send - accepts text/html (line 295)
  • POST /api/Messages/{id}/reply - accepts text/html (line 186)

New endpoints for attachments:

  • POST /api/Messages/sendWithAttachments - accepts multipart/form-data (line 332)
  • POST /api/Messages/{id}/replyWithAttachments - accepts multipart/form-data (line 236)

Existing API clients continue to work without any changes. The frontend automatically selects the appropriate endpoint based on whether attachments are present.

Commit: 310035d

@rnwood
Copy link
Copy Markdown
Owner

rnwood commented Dec 6, 2025

But it adds another API action. Can't it just be an optional part of the existing?

@rnwood
Copy link
Copy Markdown
Owner

rnwood commented Dec 6, 2025

@copilot see above comment

…ate sendWithAttachments/replyWithAttachments endpoints

Co-authored-by: rnwood <1327895+rnwood@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Dec 6, 2025

@copilot see above comment

Done! The existing endpoints now handle attachments optionally:

Updated endpoints:

  • POST /api/Messages/send - accepts both text/html and multipart/form-data
  • POST /api/Messages/{id}/reply - accepts both text/html and multipart/form-data

The endpoints automatically detect the content type:

  • text/html → body-only (backward compatible with existing clients)
  • multipart/form-data → body + optional attachments

The TypeScript client intelligently selects the appropriate content type based on whether attachments are provided. No new API actions were added - the separate sendWithAttachments and replyWithAttachments endpoints have been removed.

Commit: c58f4bd

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Dec 6, 2025

Please retry analysis of this Pull-Request directly on SonarQube Cloud

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Dec 6, 2025

@rnwood
Copy link
Copy Markdown
Owner

rnwood commented Dec 6, 2025

📊 Code Coverage Report

Coverage Type Percentage Status
Line Coverage 14.3% 🔴
Branch Coverage 4.8% 🔴
Method Coverage 17.6% 🔴

📁 Coverage by Namespace

Namespace Line Coverage Branch Coverage Method Coverage Classes
LumiSoft.Net 0% 🔴 0% 🔴 0% 🔴 23
LumiSoft.Net.AUTH 0% 🔴 0% 🔴 0% 🔴 18
LumiSoft.Net.IMAP 1.7% 🔴 0.4% 🔴 3.9% 🔴 122
LumiSoft.Net.IMAP.Client 0% 🔴 0% 🔴 0% 🔴 8
LumiSoft.Net.IMAP.Server 0% 🔴 0% 🔴 0% 🔴 25
LumiSoft.Net.IO 0% 🔴 0% 🔴 0% 🔴 13
LumiSoft.Net.Log 0% 🔴 0% 🔴 0% 🔴 3
LumiSoft.Net.Mail 0% 🔴 0% 🔴 0% 🔴 14
LumiSoft.Net.MIME 0% 🔴 0% 🔴 0% 🔴 41
LumiSoft.Net.TCP 0% 🔴 0% 🔴 0% 🔴 6
LumiSoft.Net.UDP 0% 🔴 0% 🔴 0% 🔴 3
Rnwood.Smtp4dev 1.9% 🔴 3.3% 🔴 12% 🔴 14
Rnwood.Smtp4dev.ApiModel 58.5% 🔴 54.5% 🔴 44.3% 🔴 17
Rnwood.Smtp4dev.Controllers 3.5% 🔴 4.7% 🔴 9.2% 🔴 11
Rnwood.Smtp4dev.Data 55.6% 🔴 40.9% 🔴 60% 🟡 3
Rnwood.Smtp4dev.DbModel 72.1% 🟡 0% 🔴 67.3% 🟡 6
Rnwood.Smtp4dev.DbModel.Projections 100% 🟢 0% 🔴 100% 🟢 1
Rnwood.Smtp4dev.Hubs 0% 🔴 0% 🔴 0% 🔴 1
Rnwood.Smtp4dev.Migrations 90.2% 🟢 0% 🔴 71.7% 🟡 23
Rnwood.Smtp4dev.Server 15.4% 🔴 14% 🔴 20.3% 🔴 15
Rnwood.Smtp4dev.Server.Imap 84.8% 🟢 85.3% 🟢 78.9% 🟡 2
Rnwood.Smtp4dev.Server.Pop3 76.8% 🟡 63.6% 🟡 96.8% 🟢 2
Rnwood.Smtp4dev.Server.Pop3.CommandHandlers 48.3% 🔴 26.1% 🔴 84.6% 🟢 12
Rnwood.Smtp4dev.Server.Settings 67.1% 🟡 16.7% 🔴 72.1% 🟡 10
Rnwood.Smtp4dev.Service 0% 🔴 0% 🔴 0% 🔴 5
Rnwood.Smtp4dev.TUI 0% 🔴 0% 🔴 0% 🔴 9
Rnwood.SmtpServer 72.1% 🟡 63.2% 🟡 68.3% 🟡 36
Rnwood.SmtpServer.Extensions 67.9% 🟡 25% 🔴 91.3% 🟢 6
Rnwood.SmtpServer.Extensions.Auth 59% 🔴 47.6% 🔴 57.5% 🔴 23
Rnwood.SmtpServer.Verbs 92.9% 🟢 92% 🟢 100% 🟢 12

Overall Coverage Details:

  • Covered Lines: 5980 / 41707
  • Covered Branches: 583 / 11969
  • Covered Methods: 701 / 3973
  • Assemblies Tested: 3
  • Total Classes: 484

📈 View Full Coverage Report

Enhanced coverage report with namespace breakdown - Azure DevOps Build #3.11.0-ci20251206139_pr1965 20251206.40

@rnwood rnwood changed the title Add file attachment support for sending emails via relay feat: file attachment support for sending emails Dec 6, 2025
@rnwood rnwood marked this pull request as ready for review December 6, 2025 16:28
@rnwood rnwood merged commit 98a1869 into master Dec 6, 2025
24 of 29 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.

2 participants