Added files.
This commit is contained in:
114
imapserver/capability.go
Normal file
114
imapserver/capability.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package imapserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/emersion/go-imap/v2"
|
||||
"github.com/emersion/go-imap/v2/internal/imapwire"
|
||||
)
|
||||
|
||||
func (c *Conn) handleCapability(dec *imapwire.Decoder) error {
|
||||
if !dec.ExpectCRLF() {
|
||||
return dec.Err()
|
||||
}
|
||||
|
||||
enc := newResponseEncoder(c)
|
||||
defer enc.end()
|
||||
enc.Atom("*").SP().Atom("CAPABILITY")
|
||||
for _, c := range c.availableCaps() {
|
||||
enc.SP().Atom(string(c))
|
||||
}
|
||||
return enc.CRLF()
|
||||
}
|
||||
|
||||
// availableCaps returns the capabilities supported by the server.
|
||||
//
|
||||
// They depend on the connection state.
|
||||
//
|
||||
// Some extensions (e.g. SASL-IR, ENABLE) don't require backend support and
|
||||
// thus are always enabled.
|
||||
func (c *Conn) availableCaps() []imap.Cap {
|
||||
available := c.server.options.caps()
|
||||
|
||||
var caps []imap.Cap
|
||||
addAvailableCaps(&caps, available, []imap.Cap{
|
||||
imap.CapIMAP4rev2,
|
||||
imap.CapIMAP4rev1,
|
||||
})
|
||||
if len(caps) == 0 {
|
||||
panic("imapserver: must support at least IMAP4rev1 or IMAP4rev2")
|
||||
}
|
||||
|
||||
if available.Has(imap.CapIMAP4rev1) {
|
||||
caps = append(caps, []imap.Cap{
|
||||
imap.CapSASLIR,
|
||||
imap.CapLiteralMinus,
|
||||
}...)
|
||||
}
|
||||
if c.canStartTLS() {
|
||||
caps = append(caps, imap.CapStartTLS)
|
||||
}
|
||||
if c.canAuth() {
|
||||
mechs := []string{"PLAIN"}
|
||||
if authSess, ok := c.session.(SessionSASL); ok {
|
||||
mechs = authSess.AuthenticateMechanisms()
|
||||
}
|
||||
for _, mech := range mechs {
|
||||
caps = append(caps, imap.Cap("AUTH="+mech))
|
||||
}
|
||||
} else if c.state == imap.ConnStateNotAuthenticated {
|
||||
caps = append(caps, imap.CapLoginDisabled)
|
||||
}
|
||||
if c.state == imap.ConnStateAuthenticated || c.state == imap.ConnStateSelected {
|
||||
if available.Has(imap.CapIMAP4rev1) {
|
||||
// IMAP4rev1-specific capabilities that don't require backend
|
||||
// support and are not applicable to IMAP4rev2
|
||||
caps = append(caps, []imap.Cap{
|
||||
imap.CapUnselect,
|
||||
imap.CapEnable,
|
||||
imap.CapIdle,
|
||||
imap.CapUTF8Accept,
|
||||
}...)
|
||||
|
||||
// IMAP4rev1-specific capabilities which require backend support
|
||||
// and are not applicable to IMAP4rev2
|
||||
addAvailableCaps(&caps, available, []imap.Cap{
|
||||
imap.CapNamespace,
|
||||
imap.CapUIDPlus,
|
||||
imap.CapESearch,
|
||||
imap.CapSearchRes,
|
||||
imap.CapListExtended,
|
||||
imap.CapListStatus,
|
||||
imap.CapMove,
|
||||
imap.CapStatusSize,
|
||||
imap.CapBinary,
|
||||
imap.CapChildren,
|
||||
})
|
||||
}
|
||||
|
||||
// Capabilities which require backend support and apply to both
|
||||
// IMAP4rev1 and IMAP4rev2
|
||||
addAvailableCaps(&caps, available, []imap.Cap{
|
||||
imap.CapSpecialUse,
|
||||
imap.CapCreateSpecialUse,
|
||||
imap.CapLiteralPlus,
|
||||
imap.CapUnauthenticate,
|
||||
})
|
||||
|
||||
if appendLimitSession, ok := c.session.(SessionAppendLimit); ok {
|
||||
limit := appendLimitSession.AppendLimit()
|
||||
caps = append(caps, imap.Cap(fmt.Sprintf("APPENDLIMIT=%d", limit)))
|
||||
} else {
|
||||
addAvailableCaps(&caps, available, []imap.Cap{imap.CapAppendLimit})
|
||||
}
|
||||
}
|
||||
return caps
|
||||
}
|
||||
|
||||
func addAvailableCaps(caps *[]imap.Cap, available imap.CapSet, l []imap.Cap) {
|
||||
for _, c := range l {
|
||||
if available.Has(c) {
|
||||
*caps = append(*caps, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user