- Introduced new functionality for managing email attachments and drafts in the mail API. - Added handlers for listing, uploading, and downloading message attachments in `internal/api/mail/handlers_attachments.go`. - Implemented draft management endpoints for creating, updating, and deleting drafts in `internal/api/mail/handlers_drafts.go`. - Created new service methods for handling draft and attachment operations in `internal/api/mail/drafts.go` and `internal/api/mail/storage.go`. - Added validation and error handling for draft and attachment operations. - Included unit tests for draft and folder functionalities in `internal/api/mail/drafts_test.go` and `internal/api/mail/folders_test.go`. - Updated API routes to support new draft and attachment features, enhancing overall mail management capabilities.
93 lines
2.9 KiB
Go
93 lines
2.9 KiB
Go
package mail
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/ultisuite/ulti-backend/internal/api/apivalidate"
|
|
)
|
|
|
|
type draftRequest struct {
|
|
AccountID string `json:"account_id"`
|
|
IdentityID string `json:"identity_id"`
|
|
To []string `json:"to"`
|
|
Cc []string `json:"cc"`
|
|
Bcc []string `json:"bcc"`
|
|
Subject string `json:"subject"`
|
|
BodyText string `json:"body_text"`
|
|
BodyHTML string `json:"body_html"`
|
|
InReplyTo string `json:"in_reply_to"`
|
|
Attachments any `json:"attachments"`
|
|
}
|
|
|
|
func validateDraftRecipients(req *draftRequest) []apivalidate.FieldDetail {
|
|
var details []apivalidate.FieldDetail
|
|
for i, addr := range req.To {
|
|
if d := validateRecipient(addr); d != nil {
|
|
d.Field = "to[" + strconv.Itoa(i) + "]"
|
|
details = append(details, *d)
|
|
}
|
|
}
|
|
for i, addr := range req.Cc {
|
|
if d := validateRecipient(addr); d != nil {
|
|
d.Field = "cc[" + strconv.Itoa(i) + "]"
|
|
details = append(details, *d)
|
|
}
|
|
}
|
|
for i, addr := range req.Bcc {
|
|
if d := validateRecipient(addr); d != nil {
|
|
d.Field = "bcc[" + strconv.Itoa(i) + "]"
|
|
details = append(details, *d)
|
|
}
|
|
}
|
|
return details
|
|
}
|
|
|
|
func validateDraftContent(req *draftRequest) []apivalidate.FieldDetail {
|
|
var details []apivalidate.FieldDetail
|
|
if len(req.Subject) > maxSubjectLen {
|
|
details = append(details, apivalidate.FieldDetail{Field: "subject", Message: "too long"})
|
|
}
|
|
if len(req.BodyText) > maxBodyField {
|
|
details = append(details, apivalidate.FieldDetail{Field: "body_text", Message: "too long"})
|
|
}
|
|
if len(req.BodyHTML) > maxBodyField {
|
|
details = append(details, apivalidate.FieldDetail{Field: "body_html", Message: "too long"})
|
|
}
|
|
if req.InReplyTo != "" && len(req.InReplyTo) > 998 {
|
|
details = append(details, apivalidate.FieldDetail{Field: "in_reply_to", Message: "too long"})
|
|
}
|
|
if req.Attachments != nil {
|
|
if b, err := json.Marshal(req.Attachments); err != nil {
|
|
details = append(details, apivalidate.FieldDetail{Field: "attachments", Message: "invalid"})
|
|
} else if len(b) > maxSendRequestBody {
|
|
details = append(details, apivalidate.FieldDetail{Field: "attachments", Message: "too large"})
|
|
}
|
|
}
|
|
return details
|
|
}
|
|
|
|
func validateCreateDraft(req *draftRequest) *apivalidate.ValidationError {
|
|
var details []apivalidate.FieldDetail
|
|
if strings.TrimSpace(req.AccountID) == "" {
|
|
details = append(details, apivalidate.FieldDetail{Field: "account_id", Message: "required"})
|
|
}
|
|
details = append(details, validateDraftRecipients(req)...)
|
|
details = append(details, validateDraftContent(req)...)
|
|
if len(details) == 0 {
|
|
return nil
|
|
}
|
|
return apivalidate.NewValidationError(details...)
|
|
}
|
|
|
|
func validateUpdateDraft(req *draftRequest) *apivalidate.ValidationError {
|
|
var details []apivalidate.FieldDetail
|
|
details = append(details, validateDraftRecipients(req)...)
|
|
details = append(details, validateDraftContent(req)...)
|
|
if len(details) == 0 {
|
|
return nil
|
|
}
|
|
return apivalidate.NewValidationError(details...)
|
|
}
|