diff --git a/internal/imap/store.go b/internal/imap/store.go index 005108c3..137c916c 100644 --- a/internal/imap/store.go +++ b/internal/imap/store.go @@ -31,7 +31,7 @@ import ( type storeUserProvider interface { UserID() string GetSpace() (usedSpace, maxSpace uint, err error) - GetMaxUpload() (uint, error) + GetMaxUpload() (int64, error) GetAddress(addressID string) (storeAddressProvider, error) diff --git a/internal/smtp/store.go b/internal/smtp/store.go index 4f0218a6..42a1bbd0 100644 --- a/internal/smtp/store.go +++ b/internal/smtp/store.go @@ -33,4 +33,5 @@ type storeUserProvider interface { attachedPublicKeyName string, parentID string) (*pmapi.Message, []*pmapi.Attachment, error) SendMessage(messageID string, req *pmapi.SendMessageReq) error + GetMaxUpload() (int64, error) } diff --git a/internal/smtp/user.go b/internal/smtp/user.go index 202c3166..62d31407 100644 --- a/internal/smtp/user.go +++ b/internal/smtp/user.go @@ -20,9 +20,11 @@ package smtp import ( + "bytes" "encoding/base64" "fmt" "io" + "io/ioutil" "mime" "net/mail" "strings" @@ -319,6 +321,12 @@ func (su *smtpUser) Send(returnPath string, to []string, messageReader io.Reader return nil } + if ok, err := su.isTotalSizeOkay(message, attReaders); err != nil { + return err + } else if !ok { + return errors.New("message is too large") + } + su.backend.sendRecorder.addMessage(sendRecorderMessageHash) message, atts, err := su.storeUser.CreateDraft(kr, message, attReaders, attachedPublicKey, attachedPublicKeyName, parentID) if err != nil { @@ -527,3 +535,24 @@ func (su *smtpUser) Logout() error { log.Debug("SMTP client logged out user ", su.addressID) return nil } + +func (su *smtpUser) isTotalSizeOkay(message *pmapi.Message, attReaders []io.Reader) (bool, error) { + maxUpload, err := su.storeUser.GetMaxUpload() + if err != nil { + return false, err + } + + var attSize int64 + + for i := range attReaders { + b, err := ioutil.ReadAll(attReaders[i]) + if err != nil { + return false, err + } + + attSize += int64(len(b)) + attReaders[i] = bytes.NewBuffer(b) + } + + return message.Size+attSize <= maxUpload, nil +} diff --git a/internal/store/user.go b/internal/store/user.go index b0b92150..d234776b 100644 --- a/internal/store/user.go +++ b/internal/store/user.go @@ -31,11 +31,11 @@ func (store *Store) GetSpace() (usedSpace, maxSpace uint, err error) { return uint(apiUser.UsedSpace), uint(apiUser.MaxSpace), nil } -// GetMaxUpload returns max size of attachment in bytes. -func (store *Store) GetMaxUpload() (uint, error) { +// GetMaxUpload returns max size of message + all attachments in bytes. +func (store *Store) GetMaxUpload() (int64, error) { apiUser, err := store.client().CurrentUser() if err != nil { return 0, err } - return uint(apiUser.MaxUpload), nil + return apiUser.MaxUpload, nil } diff --git a/test/accounts/fake.json b/test/accounts/fake.json index 60bea18a..79ba3742 100644 --- a/test/accounts/fake.json +++ b/test/accounts/fake.json @@ -2,23 +2,28 @@ "users": { "user": { "ID": "1", - "Name": "user" + "Name": "user", + "MaxUpload": 26214400 }, "user2fa": { "ID": "2", - "Name": "user2fa" + "Name": "user2fa", + "MaxUpload": 26214400 }, "userAddressWithCapitalLetter": { "ID": "3", - "Name": "userAddressWithCapitalLetter" + "Name": "userAddressWithCapitalLetter", + "MaxUpload": 26214400 }, "userMoreAddresses": { "ID": "4", - "Name": "userMoreAddresses" + "Name": "userMoreAddresses", + "MaxUpload": 26214400 }, "userDisabledPrimaryAddress": { "ID": "5", - "Name": "userDisabledPrimaryAddress" + "Name": "userDisabledPrimaryAddress", + "MaxUpload": 26214400 } }, "addresses": { diff --git a/unreleased.md b/unreleased.md index eb902ee8..08229b87 100644 --- a/unreleased.md +++ b/unreleased.md @@ -5,6 +5,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) ## Unreleased ### Added +* GODT-928 Reject messages which are too large. ### Removed * Remove dependency on go-apple-mobileconfig.