Skip to content

Commit 2d90431

Browse files
foxcppemersion
authored andcommitted
Merge support for APPENDLIMIT extension
1 parent 74a7677 commit 2d90431

File tree

6 files changed

+65
-1
lines changed

6 files changed

+65
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ includes:
139139
* [CHILDREN](https://tools.ietf.org/html/rfc3348)
140140
* [UNSELECT](https://tools.ietf.org/html/rfc3691)
141141
* [COMPRESS](https://tools.ietf.org/html/rfc4978)
142+
* [APPENDLIMIT](https://tools.ietf.org/html/rfc7889)
142143

143144
Support for other extensions is provided via separate packages. See below.
144145

@@ -150,7 +151,6 @@ Commands defined in IMAP extensions are available in other packages. See [the
150151
wiki](https://github.com/emersion/go-imap/wiki/Using-extensions#using-client-extensions)
151152
to learn how to use them.
152153

153-
* [APPENDLIMIT](https://github.com/emersion/go-imap-appendlimit)
154154
* [ENABLE](https://github.com/emersion/go-imap-enable)
155155
* [ID](https://github.com/ProtonMail/go-imap-id)
156156
* [IDLE](https://github.com/emersion/go-imap-idle)

backend/appendlimit.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package backend
2+
3+
import (
4+
"errors"
5+
)
6+
7+
// An error that should be returned by User.CreateMessage when the message size
8+
// is too big.
9+
var ErrTooBig = errors.New("Message size exceeding limit")
10+
11+
// A backend that supports retrieving per-user message size limits.
12+
type AppendLimitBackend interface {
13+
Backend
14+
15+
// Get the fixed maximum message size in octets that the backend will accept
16+
// when creating a new message. If there is no limit, return nil.
17+
CreateMessageLimit() *uint32
18+
}
19+
20+
// A user that supports retrieving per-user message size limits.
21+
type AppendLimitUser interface {
22+
User
23+
24+
// Get the fixed maximum message size in octets that the backend will accept
25+
// when creating a new message. If there is no limit, return nil.
26+
//
27+
// This overrides the global backend limit.
28+
CreateMessageLimit() *uint32
29+
}

imap.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const (
1717
StatusUidNext StatusItem = "UIDNEXT"
1818
StatusUidValidity StatusItem = "UIDVALIDITY"
1919
StatusUnseen StatusItem = "UNSEEN"
20+
21+
StatusAppendLimit StatusItem = "APPENDLIMIT"
2022
)
2123

2224
// A FetchItem is a message data item that can be fetched.

mailbox.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ type MailboxStatus struct {
216216
// Together with a UID, it is a unique identifier for a message.
217217
// Must be greater than or equal to 1.
218218
UidValidity uint32
219+
220+
// Per-mailbox limit of message size. Set only if server supports the
221+
// APPENDLIMIT extension.
222+
AppendLimit uint32
219223
}
220224

221225
// Create a new mailbox status that will contain the specified items.
@@ -258,6 +262,8 @@ func (status *MailboxStatus) Parse(fields []interface{}) error {
258262
status.UidNext, err = ParseNumber(f)
259263
case StatusUidValidity:
260264
status.UidValidity, err = ParseNumber(f)
265+
case StatusAppendLimit:
266+
status.AppendLimit, err = ParseNumber(f)
261267
default:
262268
status.Items[k] = f
263269
}
@@ -285,6 +291,8 @@ func (status *MailboxStatus) Format() []interface{} {
285291
v = status.UidNext
286292
case StatusUidValidity:
287293
v = status.UidValidity
294+
case StatusAppendLimit:
295+
v = status.AppendLimit
288296
}
289297

290298
fields = append(fields, RawString(k), v)

server/cmd_auth.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,13 @@ func (cmd *Append) Handle(conn Conn) error {
253253
}
254254

255255
if err := mbox.CreateMessage(cmd.Flags, cmd.Date, cmd.Message); err != nil {
256+
if err == backend.ErrTooBig {
257+
return ErrStatusResp(&imap.StatusResp{
258+
Type: imap.StatusRespNo,
259+
Code: "TOOBIG",
260+
Info: "Message size exceeding limit",
261+
})
262+
}
256263
return err
257264
}
258265

server/conn.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,24 @@ func (c *conn) Close() error {
165165
func (c *conn) Capabilities() []string {
166166
caps := []string{"IMAP4rev1", "LITERAL+", "SASL-IR", "CHILDREN", "UNSELECT", "COMPRESS=DEFLATE"}
167167

168+
appendLimitSet := false
169+
if c.ctx.State == imap.AuthenticatedState {
170+
if u, ok := c.ctx.User.(backend.AppendLimitUser); ok {
171+
if limit := u.CreateMessageLimit(); limit != nil {
172+
caps = append(caps, fmt.Sprintf("APPENDLIMIT=%v", *limit))
173+
appendLimitSet = true
174+
}
175+
}
176+
} else if be, ok := c.Server().Backend.(backend.AppendLimitBackend); ok {
177+
if limit := be.CreateMessageLimit(); limit != nil {
178+
caps = append(caps, fmt.Sprintf("APPENDLIMIT=%v", *limit))
179+
appendLimitSet = true
180+
}
181+
}
182+
if !appendLimitSet {
183+
caps = append(caps, "APPENDLIMIT")
184+
}
185+
168186
if c.ctx.State == imap.NotAuthenticatedState {
169187
if !c.IsTLS() && c.s.TLSConfig != nil {
170188
caps = append(caps, "STARTTLS")

0 commit comments

Comments
 (0)