Skip to content
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

feat(email_sender): add max size to the attachments #13

Merged
merged 2 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 51 additions & 23 deletions email_sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ import (
"github.com/microcosm-cc/bluemonday"
)

const DefaultMaxAttachmentSize = 25 * 1024 * 1024 // 25 MB

// EmailSender interface defines the method to send an email.
// Implement this interface to create different email sending strategies.
type EmailSender interface {
Expand All @@ -77,15 +79,17 @@ type EmailSender interface {
// Use this struct to specify the sender, recipient, subject, and content of the email,
// as well as any attachments.
type EmailMessage struct {
From string `json:"from"` // Sender email address.
To []string `json:"to"` // Recipient email addresses.
CC []string `json:"cc"` // CC recipients email addresses.
BCC []string `json:"bcc"` // BCC recipients email addresses.
ReplyTo string `json:"replyTo"` // Reply-To email address.
Subject string `json:"subject"` // Email subject.
Text string `json:"text"` // Plain text content of the email.
HTML string `json:"html"` // HTML content of the email (optional).
Attachments []Attachment `json:"attachments"` // Attachments to be included in the email (optional).
From string `json:"from"` // Sender email address.
To []string `json:"to"` // Recipient email addresses.
CC []string `json:"cc"` // CC recipients email addresses.
BCC []string `json:"bcc"` // BCC recipients email addresses.
ReplyTo string `json:"replyTo"` // Reply-To email address.
Subject string `json:"subject"` // Email subject.
Text string `json:"text"` // Plain text content of the email.
HTML string `json:"html"` // HTML content of the email (optional).
Attachments []Attachment `json:"attachments"` // Attachments to be included in the email (optional).
maxAttachmentSize int // Maximum size for attachments.

}

// NewEmailMessage creates a new EmailMessage with the required fields.
Expand All @@ -100,9 +104,10 @@ type EmailMessage struct {
// - *EmailMessage: A pointer to the newly created EmailMessage struct.
func NewEmailMessage(from string, to []string, subject string, body string) *EmailMessage {
email := &EmailMessage{
From: from,
To: to,
Subject: subject,
From: from,
To: to,
Subject: subject,
maxAttachmentSize: DefaultMaxAttachmentSize,
}

if isHTML(body) {
Expand Down Expand Up @@ -130,15 +135,16 @@ func NewEmailMessage(from string, to []string, subject string, body string) *Ema
// - *EmailMessage: A pointer to the newly created EmailMessage struct.
func NewFullEmailMessage(from string, to []string, subject string, cc []string, bcc []string, replyTo string, textBody string, htmlBody string, attachments []Attachment) *EmailMessage {
return &EmailMessage{
From: from,
To: to,
CC: cc,
BCC: bcc,
ReplyTo: replyTo,
Subject: subject,
Text: textBody,
HTML: htmlBody,
Attachments: attachments,
From: from,
To: to,
CC: cc,
BCC: bcc,
ReplyTo: replyTo,
Subject: subject,
Text: textBody,
HTML: htmlBody,
Attachments: attachments,
maxAttachmentSize: DefaultMaxAttachmentSize,
}
}

Expand Down Expand Up @@ -371,7 +377,18 @@ func (e *EmailMessage) GetHTML() string {
return bluemonday.UGCPolicy().Sanitize(e.HTML)
}

// GetAttachments returns the attachments to be included in the email.
// SetMaxAttachmentSize sets the maximum attachment size.
// Parameters:
// - size: The maximum size for attachments in bytes. If set to a value less than 0, all attachments are allowed.
// Returns:
// - *EmailMessage: The EmailMessage struct pointer.
func (e *EmailMessage) SetMaxAttachmentSize(size int) *EmailMessage {
e.maxAttachmentSize = size
return e
}

// GetAttachments returns the attachments to be included in the email,
// filtering out those that exceed the maximum size.
// If the EmailMessage is nil, it returns an empty slice.
//
// Returns:
Expand All @@ -380,7 +397,18 @@ func (e *EmailMessage) GetAttachments() []Attachment {
if e == nil {
return []Attachment{}
}
return e.Attachments
// if maxAttachmentSize return the attachments without the limit
if e.maxAttachmentSize < 0 {
return e.Attachments
}
// return only the attachments withing the max size limit
var validAttachments []Attachment
for _, attachment := range e.Attachments {
if len(attachment.Content) <= e.maxAttachmentSize {
validAttachments = append(validAttachments, attachment)
}
}
return validAttachments
}

// Attachment represents an email attachment with its filename and content.
Expand Down
35 changes: 35 additions & 0 deletions email_sender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ func TestEmailMessageGetters(t *testing.T) {
Attachments: []Attachment{
{Filename: "test.txt", Content: []byte("test content")},
},
maxAttachmentSize: DefaultMaxAttachmentSize,
}

t.Run("GetFrom", func(t *testing.T) {
Expand Down Expand Up @@ -510,3 +511,37 @@ func TestEmailHTMLBodySanitizers(t *testing.T) {
assert.Equal(t, expected, result)
})
}

func TestSetMaxAttachmentSize(t *testing.T) {
email := &EmailMessage{}
t.Run("SetMaxAttachmentSize", func(t *testing.T) {
expected := 10 * 1024 * 1024 // 10 MB
email.SetMaxAttachmentSize(expected)
assert.Equal(t, expected, email.maxAttachmentSize)
})
}

func TestGetAttachmentsWithMaxSize(t *testing.T) {
email := &EmailMessage{
Attachments: []Attachment{
{Filename: "small.txt", Content: []byte("small content")},
{Filename: "large.txt", Content: make([]byte, 30*1024*1024)}, // 30 MB
},
maxAttachmentSize: 25 * 1024 * 1024, // 25 MB
}

t.Run("GetAttachments with size limit", func(t *testing.T) {
expected := []Attachment{
{Filename: "small.txt", Content: []byte("small content")},
}
result := email.GetAttachments()
assert.Equal(t, expected, result)
})

t.Run("GetAttachments with no size limit", func(t *testing.T) {
email.SetMaxAttachmentSize(-1)
expected := email.Attachments
result := email.GetAttachments()
assert.Equal(t, expected, result)
})
}
Loading