Skip to content

Commit b85b1c9

Browse files
committed
move appendlimit to sessionAppendLimit
1 parent 0ba2faa commit b85b1c9

File tree

6 files changed

+91
-5
lines changed

6 files changed

+91
-5
lines changed

cmd/imapmemserver/main.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@ func main() {
6868
return memServer.NewSession(), nil, nil
6969
},
7070
Caps: imap.CapSet{
71-
imap.CapIMAP4rev1: {},
72-
imap.CapIMAP4rev2: {},
73-
imap.Cap("APPENDLIMIT=104857600"): {},
71+
imap.CapIMAP4rev1: {},
72+
imap.CapIMAP4rev2: {},
7473
},
7574
TLSConfig: tlsConfig,
7675
InsecureAuth: insecureAuth,

imapserver/capability.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,14 @@ func (c *Conn) availableCaps() []imap.Cap {
8787

8888
// Capabilities which require backend support and apply to both
8989
// IMAP4rev1 and IMAP4rev2
90-
if limit, ok := available.AppendLimit(); ok {
90+
if appendLimitSession, ok := c.session.(SessionAppendLimit); ok {
91+
if appendLimitSession.DiscloseLimit() {
92+
limit := appendLimitSession.AppendLimit()
93+
caps = append(caps, imap.Cap(fmt.Sprintf("APPENDLIMIT=%d", limit)))
94+
} else {
95+
caps = append(caps, imap.CapAppendLimit)
96+
}
97+
} else if limit, ok := available.AppendLimit(); ok {
9198
if limit != nil {
9299
caps = append(caps, imap.Cap(fmt.Sprintf("APPENDLIMIT=%d", *limit)))
93100
} else {

imapserver/imapmemserver/server.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,25 @@ type serverSession struct {
4747
}
4848

4949
var _ imapserver.Session = (*serverSession)(nil)
50+
var _ imapserver.SessionAppendLimit = (*serverSession)(nil)
51+
52+
// AppendLimit implements the SessionAppendLimit interface.
53+
func (sess *serverSession) AppendLimit() uint32 {
54+
if sess.UserSession != nil {
55+
return sess.UserSession.AppendLimit()
56+
}
57+
// Default value for unauthenticated sessions
58+
return 104857600 // 100 MiB
59+
}
60+
61+
// DiscloseLimit implements the SessionAppendLimit interface.
62+
func (sess *serverSession) DiscloseLimit() bool {
63+
if sess.UserSession != nil {
64+
return sess.UserSession.DiscloseLimit()
65+
}
66+
// Default for unauthenticated sessions - true means we show the limit
67+
return true
68+
}
5069

5170
func (sess *serverSession) Login(username, password string) error {
5271
u := sess.server.user(username)

imapserver/imapmemserver/session.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,35 @@ type (
1717
type UserSession struct {
1818
*user // immutable
1919
*mailbox // may be nil
20+
21+
// appendLimit is the maximum size in bytes that can be uploaded to this server
22+
// in an APPEND command
23+
appendLimit uint32
24+
25+
// discloseLimit indicates whether the append limit should be advertised in the
26+
// CAPABILITY response
27+
discloseLimit bool
2028
}
2129

2230
var _ imapserver.SessionIMAP4rev2 = (*UserSession)(nil)
31+
var _ imapserver.SessionAppendLimit = (*UserSession)(nil)
2332

2433
// NewUserSession creates a new user session.
2534
func NewUserSession(user *User) *UserSession {
26-
return &UserSession{user: user}
35+
return &UserSession{
36+
user: user,
37+
appendLimit: 104857600, // 100 MiB default
38+
discloseLimit: true, // By default, disclose the limit in CAPABILITY
39+
}
40+
}
41+
42+
// NewUserSessionWithAppendLimit creates a new user session with a custom append limit.
43+
func NewUserSessionWithAppendLimit(user *User, appendLimit uint32, discloseLimit bool) *UserSession {
44+
return &UserSession{
45+
user: user,
46+
appendLimit: appendLimit,
47+
discloseLimit: discloseLimit,
48+
}
2749
}
2850

2951
func (sess *UserSession) Close() error {
@@ -138,3 +160,19 @@ func (sess *UserSession) Idle(w *imapserver.UpdateWriter, stop <-chan struct{})
138160
}
139161
return sess.mailbox.Idle(w, stop)
140162
}
163+
164+
// AppendLimit implements the SessionAppendLimit interface.
165+
// It returns the maximum size in bytes that can be uploaded to this server in an APPEND command.
166+
func (sess *UserSession) AppendLimit() uint32 {
167+
// If appendLimit is not set (0), return a default large value
168+
if sess.appendLimit == 0 {
169+
return 104857600 // 100 MiB default
170+
}
171+
return sess.appendLimit
172+
}
173+
174+
// DiscloseLimit implements the SessionAppendLimit interface.
175+
// It indicates whether the append limit should be advertised in the CAPABILITY response.
176+
func (sess *UserSession) DiscloseLimit() bool {
177+
return sess.discloseLimit
178+
}

imapserver/session.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,18 @@ type SessionUnauthenticate interface {
114114
// Authenticated state
115115
Unauthenticate() error
116116
}
117+
118+
// SessionAppendLimit is an IMAP session which has the same APPEND limit for
119+
// all mailboxes.
120+
type SessionAppendLimit interface {
121+
Session
122+
123+
// AppendLimit returns the maximum size in bytes that can be uploaded to this server
124+
// in an APPEND command.
125+
AppendLimit() uint32
126+
127+
// DiscloseLimit indicates whether the limit should be advertised in the CAPABILITY
128+
// response. If false, only "APPENDLIMIT" will be listed, without the actual limit.
129+
// If true, "APPENDLIMIT=<limit>" will be listed.
130+
DiscloseLimit() bool
131+
}

imapserver/status.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ func (c *Conn) handleStatus(dec *imapwire.Decoder) error {
4545
return err
4646
}
4747

48+
// Check if AppendLimit was requested and the session supports it
49+
if options.AppendLimit && data.AppendLimit == nil {
50+
if appendLimitSession, ok := c.session.(SessionAppendLimit); ok {
51+
limit := appendLimitSession.AppendLimit()
52+
data.AppendLimit = &limit
53+
}
54+
}
55+
4856
return c.writeStatus(data, &options)
4957
}
5058

0 commit comments

Comments
 (0)