Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions imap/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,13 @@ func defaultCommands() map[string]*CommandConfig {
// RFC 3691
"UNSELECT": &CommandConfig{States: sel, Exclusive: true},

// RFC 4314
"SETACL": &CommandConfig{States: auth},
"DELETEACL": &CommandConfig{States: auth},
"GETACL": &CommandConfig{States: auth, Filter: LabelFilter("ACL")},
"LISTRIGHTS": &CommandConfig{States: auth, Filter: NameFilter},
"MYRIGHTS": &CommandConfig{States: auth, Filter: NameFilter},

// RFC 4315
"UID EXPUNGE": &CommandConfig{States: sel, Filter: NameFilter},

Expand Down
1 change: 1 addition & 0 deletions imap/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ The following RFCs are implemented by this package:
http://tools.ietf.org/html/rfc3501 -- INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1
http://tools.ietf.org/html/rfc3516 -- IMAP4 Binary Content Extension
http://tools.ietf.org/html/rfc3691 -- Internet Message Access Protocol (IMAP) UNSELECT command
http://tools.ietf.org/html/rfc4314 -- IMAP4 Access Control List (ACL) Extension
http://tools.ietf.org/html/rfc4315 -- Internet Message Access Protocol (IMAP) - UIDPLUS extension
http://tools.ietf.org/html/rfc4616 -- The PLAIN Simple Authentication and Security Layer (SASL) Mechanism
http://tools.ietf.org/html/rfc4959 -- IMAP Extension for Simple Authentication and Security Layer (SASL) Initial Client Response
Expand Down
52 changes: 52 additions & 0 deletions imap/imap.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,58 @@ func (c *Client) ID(info ...string) (cmd *Command, err error) {
return c.Send("ID", f)
}

// SetAcl command changes the access control list on the specified
// mailbox so that the specified Acl.identifier is granted permissions as
// specified in Acl.Rights.
// See RFC 4314 for additional information.
func (c *Client) SetAcl(mbox string, acl *Acl) (cmd *Command, err error) {
if !c.Caps["ACL"] {
return nil, NotAvailableError("ACL")
}
return c.Send("SETACL", c.Quote(UTF7Encode(mbox)), c.Quote(acl.Identifier), c.Quote(acl.Rights))
}

// DeleteAcl command removes any <identifier,rights> pair for the
// specified identifier from the access control list for the specified mailbox
// See RFC 4314 for additional information.
func (c *Client) DeleteAcl(mbox string, identifier string) (cmd *Command, err error) {
if !c.Caps["ACL"] {
return nil, NotAvailableError("ACL")
}
return c.Send("DELETEACL", c.Quote(UTF7Encode(mbox)), c.Quote(identifier))
}

// GetAcl returns identifier right pairs of ACL
// Each pair contains the identifier for which the entry applies followed by the
// set of rights that the identifier has.
// See RFC 4314 for additional information.
func (c *Client) GetAcl(mbox string) (cmd *Command, err error) {
if !c.Caps["ACL"] {
return nil, NotAvailableError("ACL")
}
return c.Send("GETACL", c.Quote(UTF7Encode(mbox)))
}

// ListRights command takes a mailbox name and an identifier and
// returns information about what rights can be granted to the
// identifier in the ACL for the mailbox.
// See RFC 4314 for additional information.
func (c *Client) ListRights(mbox string, identifier string) (cmd *Command, err error) {
if !c.Caps["ACL"] {
return nil, NotAvailableError("ACL")
}
return c.Send("LISTRIGHTS", c.Quote(UTF7Encode(mbox)), c.Quote(identifier))
}

// MyRights command returns the set of rights that the user has to mailbox
// See RFC 4314 for additional information.
func (c *Client) MyRights(mbox string) (cmd *Command, err error) {
if !c.Caps["ACL"] {
return nil, NotAvailableError("ACL")
}
return c.Send("MYRIGHTS", c.Quote(UTF7Encode(mbox)))
}

// CompressDeflate enables data compression using the DEFLATE algorithm. The
// compression level must be between -1 and 9 (see compress/flate). See RFC 4978
// for additional information.
Expand Down
82 changes: 82 additions & 0 deletions imap/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,88 @@ func (rsp *Response) QuotaRoot() (mbox string, roots []string) {
return
}

// Acl represents a single identifier right pair a mailbox
// returned in a GETACL response, as described in RFC 4314.
type Acl struct {
Identifier string // Identifier (user)
Rights string // Rights
}

// Acl returns the mailbox name and an array of Acl pairs.
// Each Acl pair contains and identifier for which the entry applies
// and set of rights that the identifier has.
func (rsp *Response) Acl() (mbox string, acl []*Acl) {
type vt struct {
mbox string
acl []*Acl
}
v, ok := rsp.Decoded.(*vt)
if !ok && rsp.Decoded == nil && rsp.Label == "ACL" {
mbox = AsMailbox(rsp.Fields[1])
acllist := rsp.Fields[2:]
if len(acllist)%2 != 0 {
return
}
acl = make([]*Acl, len(acllist)/2)
for i := 0; i < len(acllist); i += 2 {
acl[i/2] = &Acl{
Identifier: AsString(acllist[i]),
Rights: AsString(acllist[i+1]),
}
}
} else if ok {
mbox, acl = v.mbox, v.acl
}
return
}

// ListRights response occurs as a result of a LISTRIGHTS command.
// The first two strings are the mailbox name and identifier for which
// this rights list applies. Following is an array containing the
// (possibly empty) set of rights the identifier will always be granted
// in the mailbox.
func (rsp *Response) ListRights() (mbox string, rights string, optional []string) {
type vt struct {
mbox string
rights string
optional []string
}
v, ok := rsp.Decoded.(*vt)
if !ok && rsp.Decoded == nil && rsp.Label == "LISTRIGHTS" {
mbox = AsMailbox(rsp.Fields[2])
rights = AsString(rsp.Fields[3])
if len(rsp.Fields) < 4 {
return
}
optional = make([]string, len(rsp.Fields)-4)
for i := 4; i < len(rsp.Fields); i++ {
optional[i-4] = AsString(rsp.Fields[i])
}

} else if ok {
mbox, rights, optional = v.mbox, v.rights, v.optional
}
return
}

// MyRights response occurs as a result of a MYRIGHTS command. The
// first string is the mailbox name for which these rights apply. The
// second string is the set of rights that the client has.
func (rsp *Response) MyRights() (mbox string, rights string) {
type vt struct {
mbox string
rights string
}
v, ok := rsp.Decoded.(*vt)
if !ok && rsp.Decoded == nil && rsp.Label == "MYRIGHTS" {
mbox = AsMailbox(rsp.Fields[1])
rights = AsString(rsp.Fields[2])
} else if ok {
mbox, rights = v.mbox, v.rights
}
return
}

// ResponseError wraps a Response pointer for use in an error context, such as
// when a command fails with a NO or BAD status condition. For Status and Done
// response types, the value of Response.Info may be presented to the user.
Expand Down