Skip to content

Commit 66b34e4

Browse files
committed
Add support for CREATE-SPECIAL-USE
1 parent fff4fe9 commit 66b34e4

File tree

5 files changed

+75
-23
lines changed

5 files changed

+75
-23
lines changed

create.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
package imap
22

33
// CreateOptions contains options for the CREATE command.
4-
type CreateOptions struct{}
4+
type CreateOptions struct {
5+
SpecialUse []MailboxAttr // requires CREATE-SPECIAL-USE
6+
}

imapclient/client.go

-11
Original file line numberDiff line numberDiff line change
@@ -880,17 +880,6 @@ func (c *Client) Login(username, password string) *Command {
880880
return &cmd.cmd
881881
}
882882

883-
// Create sends a CREATE command.
884-
//
885-
// A nil options pointer is equivalent to a zero options value.
886-
func (c *Client) Create(mailbox string, options *imap.CreateOptions) *Command {
887-
cmd := &Command{}
888-
enc := c.beginCommand("CREATE", cmd)
889-
enc.SP().Mailbox(mailbox)
890-
enc.end()
891-
return cmd
892-
}
893-
894883
// Delete sends a DELETE command.
895884
func (c *Client) Delete(mailbox string) *Command {
896885
cmd := &Command{}

imapclient/create.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package imapclient
2+
3+
import (
4+
"github.com/emersion/go-imap/v2"
5+
)
6+
7+
// Create sends a CREATE command.
8+
//
9+
// A nil options pointer is equivalent to a zero options value.
10+
func (c *Client) Create(mailbox string, options *imap.CreateOptions) *Command {
11+
cmd := &Command{}
12+
enc := c.beginCommand("CREATE", cmd)
13+
enc.SP().Mailbox(mailbox)
14+
if options != nil && len(options.SpecialUse) > 0 {
15+
enc.SP().Special('(').Atom("USE").SP().List(len(options.SpecialUse), func(i int) {
16+
enc.Atom(string(options.SpecialUse[i])) // TODO: validate attr
17+
}).Special(')')
18+
}
19+
enc.end()
20+
return cmd
21+
}

imapserver/conn.go

-11
Original file line numberDiff line numberDiff line change
@@ -313,17 +313,6 @@ func (c *Conn) handleLogout(dec *imapwire.Decoder) error {
313313
})
314314
}
315315

316-
func (c *Conn) handleCreate(dec *imapwire.Decoder) error {
317-
var name string
318-
if !dec.ExpectSP() || !dec.ExpectMailbox(&name) || !dec.ExpectCRLF() {
319-
return dec.Err()
320-
}
321-
if err := c.checkState(imap.ConnStateAuthenticated); err != nil {
322-
return err
323-
}
324-
return c.session.Create(name, &imap.CreateOptions{})
325-
}
326-
327316
func (c *Conn) handleDelete(dec *imapwire.Decoder) error {
328317
var name string
329318
if !dec.ExpectSP() || !dec.ExpectMailbox(&name) || !dec.ExpectCRLF() {

imapserver/create.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package imapserver
2+
3+
import (
4+
"strings"
5+
6+
"github.com/emersion/go-imap/v2"
7+
"github.com/emersion/go-imap/v2/internal"
8+
"github.com/emersion/go-imap/v2/internal/imapwire"
9+
)
10+
11+
func (c *Conn) handleCreate(dec *imapwire.Decoder) error {
12+
var (
13+
name string
14+
options imap.CreateOptions
15+
)
16+
if !dec.ExpectSP() || !dec.ExpectMailbox(&name) {
17+
return dec.Err()
18+
}
19+
if dec.SP() {
20+
var name string
21+
if !dec.ExpectSpecial('(') || !dec.ExpectAtom(&name) || !dec.ExpectSP() {
22+
return dec.Err()
23+
}
24+
switch strings.ToUpper(name) {
25+
case "USE":
26+
err := dec.ExpectList(func() error {
27+
flag, err := internal.ReadFlag(dec)
28+
if err != nil {
29+
return err
30+
}
31+
options.SpecialUse = append(options.SpecialUse, imap.MailboxAttr(flag))
32+
return nil
33+
})
34+
if err != nil {
35+
return err
36+
}
37+
default:
38+
return newClientBugError("unknown CREATE parameter")
39+
}
40+
if !dec.ExpectSpecial(')') {
41+
return dec.Err()
42+
}
43+
}
44+
if !dec.ExpectCRLF() {
45+
return dec.Err()
46+
}
47+
if err := c.checkState(imap.ConnStateAuthenticated); err != nil {
48+
return err
49+
}
50+
return c.session.Create(name, &options)
51+
}

0 commit comments

Comments
 (0)