@@ -21,6 +21,64 @@ type Logger interface {
2121 Printf (format string , args ... interface {})
2222}
2323
24+ // SupportedCaps describes capabilities supported by the server.
25+ type SupportedCaps struct {
26+ // IMAP protocol version
27+ IMAP4rev1 bool // RFC 3501
28+ IMAP4rev2 bool // RFC 9051
29+
30+ // Capabilities which are part of IMAP4rev2 and need to be explicitly
31+ // enabled by IMAP4rev1-only servers
32+ Namespace bool // RFC 2342
33+ UIDPlus bool // RFC 4315
34+ ESearch bool // RFC 4731
35+ SearchRes bool // RFC 5182
36+ ListExtended bool // RFC 5258
37+ ListStatus bool // RFC 5819
38+ Move bool // RFC 6851
39+ StatusSize bool // RFC 8438
40+ Binary bool // RFC 3516
41+ Children bool // RFC 3348
42+
43+ // Capabilities which need to be explicitly enabled on both IMAP4rev1 and
44+ // IMAP4rev2 servers
45+ SpecialUse bool // RFC 6154
46+ CreateSpecialUse bool // RFC 6154
47+ LiteralPlus bool // RFC 7888
48+ Unauthenticate bool // RFC 8437
49+ AppendLimit bool // RFC 7889
50+ }
51+
52+ func (caps * SupportedCaps ) set () imap.CapSet {
53+ m := map [imap.Cap ]bool {
54+ imap .CapIMAP4rev1 : caps .IMAP4rev1 ,
55+ imap .CapIMAP4rev2 : caps .IMAP4rev2 ,
56+ imap .CapNamespace : caps .Namespace ,
57+ imap .CapUIDPlus : caps .UIDPlus ,
58+ imap .CapESearch : caps .ESearch ,
59+ imap .CapSearchRes : caps .SearchRes ,
60+ imap .CapListExtended : caps .ListExtended ,
61+ imap .CapListStatus : caps .ListStatus ,
62+ imap .CapMove : caps .Move ,
63+ imap .CapStatusSize : caps .StatusSize ,
64+ imap .CapBinary : caps .Binary ,
65+ imap .CapChildren : caps .Children ,
66+ imap .CapSpecialUse : caps .SpecialUse ,
67+ imap .CapCreateSpecialUse : caps .CreateSpecialUse ,
68+ imap .CapLiteralPlus : caps .LiteralPlus ,
69+ imap .CapUnauthenticate : caps .Unauthenticate ,
70+ imap .CapAppendLimit : caps .AppendLimit ,
71+ }
72+
73+ set := make (imap.CapSet , len (m ))
74+ for name , ok := range m {
75+ if ok {
76+ set [name ] = struct {}{}
77+ }
78+ }
79+ return set
80+ }
81+
2482// Options contains server options.
2583//
2684// The only required field is NewSession.
@@ -29,18 +87,7 @@ type Options struct {
2987 NewSession func (* Conn ) (Session , * GreetingData , error )
3088 // Supported capabilities. If nil, only IMAP4rev1 is advertised. This set
3189 // must contain at least IMAP4rev1 or IMAP4rev2.
32- //
33- // The following capabilities are part of IMAP4rev2 and need to be
34- // explicitly enabled by IMAP4rev1-only servers:
35- //
36- // - NAMESPACE
37- // - UIDPLUS
38- // - ESEARCH
39- // - LIST-EXTENDED
40- // - LIST-STATUS
41- // - MOVE
42- // - STATUS=SIZE
43- Caps imap.CapSet
90+ Caps * SupportedCaps
4491 // Logger is a logger to print error messages. If nil, log.Default is used.
4592 Logger Logger
4693 // TLSConfig is a TLS configuration for STARTTLS. If nil, STARTTLS is
@@ -68,11 +115,11 @@ func (options *Options) wrapReadWriter(rw io.ReadWriter) io.ReadWriter {
68115 }
69116}
70117
71- func (options * Options ) caps () imap. CapSet {
118+ func (options * Options ) caps () * SupportedCaps {
72119 if options .Caps != nil {
73120 return options .Caps
74121 }
75- return imap. CapSet { imap . CapIMAP4rev1 : {} }
122+ return & SupportedCaps { IMAP4rev1 : true }
76123}
77124
78125// Server is an IMAP server.
@@ -89,7 +136,7 @@ type Server struct {
89136
90137// New creates a new server.
91138func New (options * Options ) * Server {
92- if caps := options .caps (); ! caps .Has (imap .CapIMAP4rev2 ) && ! caps .Has (imap .CapIMAP4rev1 ) {
139+ if caps := options .caps (). set () ; ! caps .Has (imap .CapIMAP4rev2 ) && ! caps .Has (imap .CapIMAP4rev1 ) {
93140 panic ("imapserver: at least IMAP4rev1 must be supported" )
94141 }
95142 return & Server {
0 commit comments