aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/emersion/go-imap/commands
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/emersion/go-imap/commands')
-rw-r--r--vendor/github.com/emersion/go-imap/commands/append.go93
-rw-r--r--vendor/github.com/emersion/go-imap/commands/authenticate.go124
-rw-r--r--vendor/github.com/emersion/go-imap/commands/capability.go18
-rw-r--r--vendor/github.com/emersion/go-imap/commands/check.go18
-rw-r--r--vendor/github.com/emersion/go-imap/commands/close.go18
-rw-r--r--vendor/github.com/emersion/go-imap/commands/commands.go2
-rw-r--r--vendor/github.com/emersion/go-imap/commands/copy.go47
-rw-r--r--vendor/github.com/emersion/go-imap/commands/create.go38
-rw-r--r--vendor/github.com/emersion/go-imap/commands/delete.go38
-rw-r--r--vendor/github.com/emersion/go-imap/commands/enable.go23
-rw-r--r--vendor/github.com/emersion/go-imap/commands/expunge.go16
-rw-r--r--vendor/github.com/emersion/go-imap/commands/fetch.go63
-rw-r--r--vendor/github.com/emersion/go-imap/commands/idle.go17
-rw-r--r--vendor/github.com/emersion/go-imap/commands/list.go60
-rw-r--r--vendor/github.com/emersion/go-imap/commands/login.go36
-rw-r--r--vendor/github.com/emersion/go-imap/commands/logout.go18
-rw-r--r--vendor/github.com/emersion/go-imap/commands/move.go48
-rw-r--r--vendor/github.com/emersion/go-imap/commands/noop.go18
-rw-r--r--vendor/github.com/emersion/go-imap/commands/rename.go51
-rw-r--r--vendor/github.com/emersion/go-imap/commands/search.go57
-rw-r--r--vendor/github.com/emersion/go-imap/commands/select.go45
-rw-r--r--vendor/github.com/emersion/go-imap/commands/starttls.go18
-rw-r--r--vendor/github.com/emersion/go-imap/commands/status.go58
-rw-r--r--vendor/github.com/emersion/go-imap/commands/store.go50
-rw-r--r--vendor/github.com/emersion/go-imap/commands/subscribe.go63
-rw-r--r--vendor/github.com/emersion/go-imap/commands/uid.go44
-rw-r--r--vendor/github.com/emersion/go-imap/commands/unselect.go17
27 files changed, 1098 insertions, 0 deletions
diff --git a/vendor/github.com/emersion/go-imap/commands/append.go b/vendor/github.com/emersion/go-imap/commands/append.go
new file mode 100644
index 0000000..d70b584
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/append.go
@@ -0,0 +1,93 @@
+package commands
+
+import (
+ "errors"
+ "time"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// Append is an APPEND command, as defined in RFC 3501 section 6.3.11.
+type Append struct {
+ Mailbox string
+ Flags []string
+ Date time.Time
+ Message imap.Literal
+}
+
+func (cmd *Append) Command() *imap.Command {
+ var args []interface{}
+
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+ args = append(args, imap.FormatMailboxName(mailbox))
+
+ if cmd.Flags != nil {
+ flags := make([]interface{}, len(cmd.Flags))
+ for i, flag := range cmd.Flags {
+ flags[i] = imap.RawString(flag)
+ }
+ args = append(args, flags)
+ }
+
+ if !cmd.Date.IsZero() {
+ args = append(args, cmd.Date)
+ }
+
+ args = append(args, cmd.Message)
+
+ return &imap.Command{
+ Name: "APPEND",
+ Arguments: args,
+ }
+}
+
+func (cmd *Append) Parse(fields []interface{}) (err error) {
+ if len(fields) < 2 {
+ return errors.New("No enough arguments")
+ }
+
+ // Parse mailbox name
+ if mailbox, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if mailbox, err = utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ } else {
+ cmd.Mailbox = imap.CanonicalMailboxName(mailbox)
+ }
+
+ // Parse message literal
+ litIndex := len(fields) - 1
+ var ok bool
+ if cmd.Message, ok = fields[litIndex].(imap.Literal); !ok {
+ return errors.New("Message must be a literal")
+ }
+
+ // Remaining fields a optional
+ fields = fields[1:litIndex]
+ if len(fields) > 0 {
+ // Parse flags list
+ if flags, ok := fields[0].([]interface{}); ok {
+ if cmd.Flags, err = imap.ParseStringList(flags); err != nil {
+ return err
+ }
+
+ for i, flag := range cmd.Flags {
+ cmd.Flags[i] = imap.CanonicalFlag(flag)
+ }
+
+ fields = fields[1:]
+ }
+
+ // Parse date
+ if len(fields) > 0 {
+ if date, ok := fields[0].(string); !ok {
+ return errors.New("Date must be a string")
+ } else if cmd.Date, err = time.Parse(imap.DateTimeLayout, date); err != nil {
+ return err
+ }
+ }
+ }
+
+ return
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/authenticate.go b/vendor/github.com/emersion/go-imap/commands/authenticate.go
new file mode 100644
index 0000000..b66f21f
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/authenticate.go
@@ -0,0 +1,124 @@
+package commands
+
+import (
+ "bufio"
+ "encoding/base64"
+ "errors"
+ "io"
+ "strings"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-sasl"
+)
+
+// AuthenticateConn is a connection that supports IMAP authentication.
+type AuthenticateConn interface {
+ io.Reader
+
+ // WriteResp writes an IMAP response to this connection.
+ WriteResp(res imap.WriterTo) error
+}
+
+// Authenticate is an AUTHENTICATE command, as defined in RFC 3501 section
+// 6.2.2.
+type Authenticate struct {
+ Mechanism string
+ InitialResponse []byte
+}
+
+func (cmd *Authenticate) Command() *imap.Command {
+ args := []interface{}{imap.RawString(cmd.Mechanism)}
+ if cmd.InitialResponse != nil {
+ var encodedResponse string
+ if len(cmd.InitialResponse) == 0 {
+ // Empty initial response should be encoded as "=", not empty
+ // string.
+ encodedResponse = "="
+ } else {
+ encodedResponse = base64.StdEncoding.EncodeToString(cmd.InitialResponse)
+ }
+
+ args = append(args, imap.RawString(encodedResponse))
+ }
+ return &imap.Command{
+ Name: "AUTHENTICATE",
+ Arguments: args,
+ }
+}
+
+func (cmd *Authenticate) Parse(fields []interface{}) error {
+ if len(fields) < 1 {
+ return errors.New("Not enough arguments")
+ }
+
+ var ok bool
+ if cmd.Mechanism, ok = fields[0].(string); !ok {
+ return errors.New("Mechanism must be a string")
+ }
+ cmd.Mechanism = strings.ToUpper(cmd.Mechanism)
+
+ if len(fields) != 2 {
+ return nil
+ }
+
+ encodedResponse, ok := fields[1].(string)
+ if !ok {
+ return errors.New("Initial response must be a string")
+ }
+ if encodedResponse == "=" {
+ cmd.InitialResponse = []byte{}
+ return nil
+ }
+
+ var err error
+ cmd.InitialResponse, err = base64.StdEncoding.DecodeString(encodedResponse)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (cmd *Authenticate) Handle(mechanisms map[string]sasl.Server, conn AuthenticateConn) error {
+ sasl, ok := mechanisms[cmd.Mechanism]
+ if !ok {
+ return errors.New("Unsupported mechanism")
+ }
+
+ scanner := bufio.NewScanner(conn)
+
+ response := cmd.InitialResponse
+ for {
+ challenge, done, err := sasl.Next(response)
+ if err != nil || done {
+ return err
+ }
+
+ encoded := base64.StdEncoding.EncodeToString(challenge)
+ cont := &imap.ContinuationReq{Info: encoded}
+ if err := conn.WriteResp(cont); err != nil {
+ return err
+ }
+
+ if !scanner.Scan() {
+ if err := scanner.Err(); err != nil {
+ return err
+ }
+ return errors.New("unexpected EOF")
+ }
+
+ encoded = scanner.Text()
+ if encoded != "" {
+ if encoded == "*" {
+ return &imap.ErrStatusResp{Resp: &imap.StatusResp{
+ Type: imap.StatusRespBad,
+ Info: "negotiation cancelled",
+ }}
+ }
+ response, err = base64.StdEncoding.DecodeString(encoded)
+ if err != nil {
+ return err
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/capability.go b/vendor/github.com/emersion/go-imap/commands/capability.go
new file mode 100644
index 0000000..3359c0a
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/capability.go
@@ -0,0 +1,18 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// Capability is a CAPABILITY command, as defined in RFC 3501 section 6.1.1.
+type Capability struct{}
+
+func (c *Capability) Command() *imap.Command {
+ return &imap.Command{
+ Name: "CAPABILITY",
+ }
+}
+
+func (c *Capability) Parse(fields []interface{}) error {
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/check.go b/vendor/github.com/emersion/go-imap/commands/check.go
new file mode 100644
index 0000000..b90df7c
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/check.go
@@ -0,0 +1,18 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// Check is a CHECK command, as defined in RFC 3501 section 6.4.1.
+type Check struct{}
+
+func (cmd *Check) Command() *imap.Command {
+ return &imap.Command{
+ Name: "CHECK",
+ }
+}
+
+func (cmd *Check) Parse(fields []interface{}) error {
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/close.go b/vendor/github.com/emersion/go-imap/commands/close.go
new file mode 100644
index 0000000..cc60658
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/close.go
@@ -0,0 +1,18 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// Close is a CLOSE command, as defined in RFC 3501 section 6.4.2.
+type Close struct{}
+
+func (cmd *Close) Command() *imap.Command {
+ return &imap.Command{
+ Name: "CLOSE",
+ }
+}
+
+func (cmd *Close) Parse(fields []interface{}) error {
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/commands.go b/vendor/github.com/emersion/go-imap/commands/commands.go
new file mode 100644
index 0000000..a62b248
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/commands.go
@@ -0,0 +1,2 @@
+// Package commands implements IMAP commands defined in RFC 3501.
+package commands
diff --git a/vendor/github.com/emersion/go-imap/commands/copy.go b/vendor/github.com/emersion/go-imap/commands/copy.go
new file mode 100644
index 0000000..5258f35
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/copy.go
@@ -0,0 +1,47 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// Copy is a COPY command, as defined in RFC 3501 section 6.4.7.
+type Copy struct {
+ SeqSet *imap.SeqSet
+ Mailbox string
+}
+
+func (cmd *Copy) Command() *imap.Command {
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+
+ return &imap.Command{
+ Name: "COPY",
+ Arguments: []interface{}{cmd.SeqSet, imap.FormatMailboxName(mailbox)},
+ }
+}
+
+func (cmd *Copy) Parse(fields []interface{}) error {
+ if len(fields) < 2 {
+ return errors.New("No enough arguments")
+ }
+
+ if seqSet, ok := fields[0].(string); !ok {
+ return errors.New("Invalid sequence set")
+ } else if seqSet, err := imap.ParseSeqSet(seqSet); err != nil {
+ return err
+ } else {
+ cmd.SeqSet = seqSet
+ }
+
+ if mailbox, err := imap.ParseString(fields[1]); err != nil {
+ return err
+ } else if mailbox, err := utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ } else {
+ cmd.Mailbox = imap.CanonicalMailboxName(mailbox)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/create.go b/vendor/github.com/emersion/go-imap/commands/create.go
new file mode 100644
index 0000000..a1e6fe2
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/create.go
@@ -0,0 +1,38 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// Create is a CREATE command, as defined in RFC 3501 section 6.3.3.
+type Create struct {
+ Mailbox string
+}
+
+func (cmd *Create) Command() *imap.Command {
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+
+ return &imap.Command{
+ Name: "CREATE",
+ Arguments: []interface{}{mailbox},
+ }
+}
+
+func (cmd *Create) Parse(fields []interface{}) error {
+ if len(fields) < 1 {
+ return errors.New("No enough arguments")
+ }
+
+ if mailbox, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if mailbox, err := utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ } else {
+ cmd.Mailbox = imap.CanonicalMailboxName(mailbox)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/delete.go b/vendor/github.com/emersion/go-imap/commands/delete.go
new file mode 100644
index 0000000..60f4da8
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/delete.go
@@ -0,0 +1,38 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// Delete is a DELETE command, as defined in RFC 3501 section 6.3.3.
+type Delete struct {
+ Mailbox string
+}
+
+func (cmd *Delete) Command() *imap.Command {
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+
+ return &imap.Command{
+ Name: "DELETE",
+ Arguments: []interface{}{imap.FormatMailboxName(mailbox)},
+ }
+}
+
+func (cmd *Delete) Parse(fields []interface{}) error {
+ if len(fields) < 1 {
+ return errors.New("No enough arguments")
+ }
+
+ if mailbox, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if mailbox, err := utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ } else {
+ cmd.Mailbox = imap.CanonicalMailboxName(mailbox)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/enable.go b/vendor/github.com/emersion/go-imap/commands/enable.go
new file mode 100644
index 0000000..980195e
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/enable.go
@@ -0,0 +1,23 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// An ENABLE command, defined in RFC 5161 section 3.1.
+type Enable struct {
+ Caps []string
+}
+
+func (cmd *Enable) Command() *imap.Command {
+ return &imap.Command{
+ Name: "ENABLE",
+ Arguments: imap.FormatStringList(cmd.Caps),
+ }
+}
+
+func (cmd *Enable) Parse(fields []interface{}) error {
+ var err error
+ cmd.Caps, err = imap.ParseStringList(fields)
+ return err
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/expunge.go b/vendor/github.com/emersion/go-imap/commands/expunge.go
new file mode 100644
index 0000000..af550a4
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/expunge.go
@@ -0,0 +1,16 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// Expunge is an EXPUNGE command, as defined in RFC 3501 section 6.4.3.
+type Expunge struct{}
+
+func (cmd *Expunge) Command() *imap.Command {
+ return &imap.Command{Name: "EXPUNGE"}
+}
+
+func (cmd *Expunge) Parse(fields []interface{}) error {
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/fetch.go b/vendor/github.com/emersion/go-imap/commands/fetch.go
new file mode 100644
index 0000000..4eb3ab9
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/fetch.go
@@ -0,0 +1,63 @@
+package commands
+
+import (
+ "errors"
+ "strings"
+
+ "github.com/emersion/go-imap"
+)
+
+// Fetch is a FETCH command, as defined in RFC 3501 section 6.4.5.
+type Fetch struct {
+ SeqSet *imap.SeqSet
+ Items []imap.FetchItem
+}
+
+func (cmd *Fetch) Command() *imap.Command {
+ // Handle FETCH macros separately as they should not be serialized within parentheses
+ if len(cmd.Items) == 1 && (cmd.Items[0] == imap.FetchAll || cmd.Items[0] == imap.FetchFast || cmd.Items[0] == imap.FetchFull) {
+ return &imap.Command{
+ Name: "FETCH",
+ Arguments: []interface{}{cmd.SeqSet, imap.RawString(cmd.Items[0])},
+ }
+ } else {
+ items := make([]interface{}, len(cmd.Items))
+ for i, item := range cmd.Items {
+ items[i] = imap.RawString(item)
+ }
+
+ return &imap.Command{
+ Name: "FETCH",
+ Arguments: []interface{}{cmd.SeqSet, items},
+ }
+ }
+}
+
+func (cmd *Fetch) Parse(fields []interface{}) error {
+ if len(fields) < 2 {
+ return errors.New("No enough arguments")
+ }
+
+ var err error
+ if seqset, ok := fields[0].(string); !ok {
+ return errors.New("Sequence set must be an atom")
+ } else if cmd.SeqSet, err = imap.ParseSeqSet(seqset); err != nil {
+ return err
+ }
+
+ switch items := fields[1].(type) {
+ case string: // A macro or a single item
+ cmd.Items = imap.FetchItem(strings.ToUpper(items)).Expand()
+ case []interface{}: // A list of items
+ cmd.Items = make([]imap.FetchItem, 0, len(items))
+ for _, v := range items {
+ itemStr, _ := v.(string)
+ item := imap.FetchItem(strings.ToUpper(itemStr))
+ cmd.Items = append(cmd.Items, item.Expand()...)
+ }
+ default:
+ return errors.New("Items must be either a string or a list")
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/idle.go b/vendor/github.com/emersion/go-imap/commands/idle.go
new file mode 100644
index 0000000..4d9669f
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/idle.go
@@ -0,0 +1,17 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// An IDLE command.
+// Se RFC 2177 section 3.
+type Idle struct{}
+
+func (cmd *Idle) Command() *imap.Command {
+ return &imap.Command{Name: "IDLE"}
+}
+
+func (cmd *Idle) Parse(fields []interface{}) error {
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/list.go b/vendor/github.com/emersion/go-imap/commands/list.go
new file mode 100644
index 0000000..52686e9
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/list.go
@@ -0,0 +1,60 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// List is a LIST command, as defined in RFC 3501 section 6.3.8. If Subscribed
+// is set to true, LSUB will be used instead.
+type List struct {
+ Reference string
+ Mailbox string
+
+ Subscribed bool
+}
+
+func (cmd *List) Command() *imap.Command {
+ name := "LIST"
+ if cmd.Subscribed {
+ name = "LSUB"
+ }
+
+ enc := utf7.Encoding.NewEncoder()
+ ref, _ := enc.String(cmd.Reference)
+ mailbox, _ := enc.String(cmd.Mailbox)
+
+ return &imap.Command{
+ Name: name,
+ Arguments: []interface{}{ref, mailbox},
+ }
+}
+
+func (cmd *List) Parse(fields []interface{}) error {
+ if len(fields) < 2 {
+ return errors.New("No enough arguments")
+ }
+
+ dec := utf7.Encoding.NewDecoder()
+
+ if mailbox, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if mailbox, err := dec.String(mailbox); err != nil {
+ return err
+ } else {
+ // TODO: canonical mailbox path
+ cmd.Reference = imap.CanonicalMailboxName(mailbox)
+ }
+
+ if mailbox, err := imap.ParseString(fields[1]); err != nil {
+ return err
+ } else if mailbox, err := dec.String(mailbox); err != nil {
+ return err
+ } else {
+ cmd.Mailbox = imap.CanonicalMailboxName(mailbox)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/login.go b/vendor/github.com/emersion/go-imap/commands/login.go
new file mode 100644
index 0000000..d0af0b5
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/login.go
@@ -0,0 +1,36 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+)
+
+// Login is a LOGIN command, as defined in RFC 3501 section 6.2.2.
+type Login struct {
+ Username string
+ Password string
+}
+
+func (cmd *Login) Command() *imap.Command {
+ return &imap.Command{
+ Name: "LOGIN",
+ Arguments: []interface{}{cmd.Username, cmd.Password},
+ }
+}
+
+func (cmd *Login) Parse(fields []interface{}) error {
+ if len(fields) < 2 {
+ return errors.New("Not enough arguments")
+ }
+
+ var err error
+ if cmd.Username, err = imap.ParseString(fields[0]); err != nil {
+ return err
+ }
+ if cmd.Password, err = imap.ParseString(fields[1]); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/logout.go b/vendor/github.com/emersion/go-imap/commands/logout.go
new file mode 100644
index 0000000..e826719
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/logout.go
@@ -0,0 +1,18 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// Logout is a LOGOUT command, as defined in RFC 3501 section 6.1.3.
+type Logout struct{}
+
+func (c *Logout) Command() *imap.Command {
+ return &imap.Command{
+ Name: "LOGOUT",
+ }
+}
+
+func (c *Logout) Parse(fields []interface{}) error {
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/move.go b/vendor/github.com/emersion/go-imap/commands/move.go
new file mode 100644
index 0000000..613a870
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/move.go
@@ -0,0 +1,48 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// A MOVE command.
+// See RFC 6851 section 3.1.
+type Move struct {
+ SeqSet *imap.SeqSet
+ Mailbox string
+}
+
+func (cmd *Move) Command() *imap.Command {
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+
+ return &imap.Command{
+ Name: "MOVE",
+ Arguments: []interface{}{cmd.SeqSet, mailbox},
+ }
+}
+
+func (cmd *Move) Parse(fields []interface{}) (err error) {
+ if len(fields) < 2 {
+ return errors.New("No enough arguments")
+ }
+
+ seqset, ok := fields[0].(string)
+ if !ok {
+ return errors.New("Invalid sequence set")
+ }
+ if cmd.SeqSet, err = imap.ParseSeqSet(seqset); err != nil {
+ return err
+ }
+
+ mailbox, ok := fields[1].(string)
+ if !ok {
+ return errors.New("Mailbox name must be a string")
+ }
+ if cmd.Mailbox, err = utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ }
+
+ return
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/noop.go b/vendor/github.com/emersion/go-imap/commands/noop.go
new file mode 100644
index 0000000..da6a1c2
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/noop.go
@@ -0,0 +1,18 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// Noop is a NOOP command, as defined in RFC 3501 section 6.1.2.
+type Noop struct{}
+
+func (c *Noop) Command() *imap.Command {
+ return &imap.Command{
+ Name: "NOOP",
+ }
+}
+
+func (c *Noop) Parse(fields []interface{}) error {
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/rename.go b/vendor/github.com/emersion/go-imap/commands/rename.go
new file mode 100644
index 0000000..37a5fa7
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/rename.go
@@ -0,0 +1,51 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// Rename is a RENAME command, as defined in RFC 3501 section 6.3.5.
+type Rename struct {
+ Existing string
+ New string
+}
+
+func (cmd *Rename) Command() *imap.Command {
+ enc := utf7.Encoding.NewEncoder()
+ existingName, _ := enc.String(cmd.Existing)
+ newName, _ := enc.String(cmd.New)
+
+ return &imap.Command{
+ Name: "RENAME",
+ Arguments: []interface{}{imap.FormatMailboxName(existingName), imap.FormatMailboxName(newName)},
+ }
+}
+
+func (cmd *Rename) Parse(fields []interface{}) error {
+ if len(fields) < 2 {
+ return errors.New("No enough arguments")
+ }
+
+ dec := utf7.Encoding.NewDecoder()
+
+ if existingName, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if existingName, err := dec.String(existingName); err != nil {
+ return err
+ } else {
+ cmd.Existing = imap.CanonicalMailboxName(existingName)
+ }
+
+ if newName, err := imap.ParseString(fields[1]); err != nil {
+ return err
+ } else if newName, err := dec.String(newName); err != nil {
+ return err
+ } else {
+ cmd.New = imap.CanonicalMailboxName(newName)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/search.go b/vendor/github.com/emersion/go-imap/commands/search.go
new file mode 100644
index 0000000..72f026c
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/search.go
@@ -0,0 +1,57 @@
+package commands
+
+import (
+ "errors"
+ "io"
+ "strings"
+
+ "github.com/emersion/go-imap"
+)
+
+// Search is a SEARCH command, as defined in RFC 3501 section 6.4.4.
+type Search struct {
+ Charset string
+ Criteria *imap.SearchCriteria
+}
+
+func (cmd *Search) Command() *imap.Command {
+ var args []interface{}
+ if cmd.Charset != "" {
+ args = append(args, imap.RawString("CHARSET"), imap.RawString(cmd.Charset))
+ }
+ args = append(args, cmd.Criteria.Format()...)
+
+ return &imap.Command{
+ Name: "SEARCH",
+ Arguments: args,
+ }
+}
+
+func (cmd *Search) Parse(fields []interface{}) error {
+ if len(fields) == 0 {
+ return errors.New("Missing search criteria")
+ }
+
+ // Parse charset
+ if f, ok := fields[0].(string); ok && strings.EqualFold(f, "CHARSET") {
+ if len(fields) < 2 {
+ return errors.New("Missing CHARSET value")
+ }
+ if cmd.Charset, ok = fields[1].(string); !ok {
+ return errors.New("Charset must be a string")
+ }
+ fields = fields[2:]
+ }
+
+ var charsetReader func(io.Reader) io.Reader
+ charset := strings.ToLower(cmd.Charset)
+ if charset != "utf-8" && charset != "us-ascii" && charset != "" {
+ charsetReader = func(r io.Reader) io.Reader {
+ r, _ = imap.CharsetReader(charset, r)
+ return r
+ }
+ }
+
+ cmd.Criteria = new(imap.SearchCriteria)
+ return cmd.Criteria.ParseWithCharset(fields, charsetReader)
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/select.go b/vendor/github.com/emersion/go-imap/commands/select.go
new file mode 100644
index 0000000..e881eff
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/select.go
@@ -0,0 +1,45 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// Select is a SELECT command, as defined in RFC 3501 section 6.3.1. If ReadOnly
+// is set to true, the EXAMINE command will be used instead.
+type Select struct {
+ Mailbox string
+ ReadOnly bool
+}
+
+func (cmd *Select) Command() *imap.Command {
+ name := "SELECT"
+ if cmd.ReadOnly {
+ name = "EXAMINE"
+ }
+
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+
+ return &imap.Command{
+ Name: name,
+ Arguments: []interface{}{imap.FormatMailboxName(mailbox)},
+ }
+}
+
+func (cmd *Select) Parse(fields []interface{}) error {
+ if len(fields) < 1 {
+ return errors.New("No enough arguments")
+ }
+
+ if mailbox, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if mailbox, err := utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ } else {
+ cmd.Mailbox = imap.CanonicalMailboxName(mailbox)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/starttls.go b/vendor/github.com/emersion/go-imap/commands/starttls.go
new file mode 100644
index 0000000..d900e5e
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/starttls.go
@@ -0,0 +1,18 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// StartTLS is a STARTTLS command, as defined in RFC 3501 section 6.2.1.
+type StartTLS struct{}
+
+func (cmd *StartTLS) Command() *imap.Command {
+ return &imap.Command{
+ Name: "STARTTLS",
+ }
+}
+
+func (cmd *StartTLS) Parse(fields []interface{}) error {
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/status.go b/vendor/github.com/emersion/go-imap/commands/status.go
new file mode 100644
index 0000000..672dce5
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/status.go
@@ -0,0 +1,58 @@
+package commands
+
+import (
+ "errors"
+ "strings"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// Status is a STATUS command, as defined in RFC 3501 section 6.3.10.
+type Status struct {
+ Mailbox string
+ Items []imap.StatusItem
+}
+
+func (cmd *Status) Command() *imap.Command {
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+
+ items := make([]interface{}, len(cmd.Items))
+ for i, item := range cmd.Items {
+ items[i] = imap.RawString(item)
+ }
+
+ return &imap.Command{
+ Name: "STATUS",
+ Arguments: []interface{}{imap.FormatMailboxName(mailbox), items},
+ }
+}
+
+func (cmd *Status) Parse(fields []interface{}) error {
+ if len(fields) < 2 {
+ return errors.New("No enough arguments")
+ }
+
+ if mailbox, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if mailbox, err := utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ } else {
+ cmd.Mailbox = imap.CanonicalMailboxName(mailbox)
+ }
+
+ items, ok := fields[1].([]interface{})
+ if !ok {
+ return errors.New("STATUS command parameter is not a list")
+ }
+ cmd.Items = make([]imap.StatusItem, len(items))
+ for i, f := range items {
+ if s, ok := f.(string); !ok {
+ return errors.New("Got a non-string field in a STATUS command parameter")
+ } else {
+ cmd.Items[i] = imap.StatusItem(strings.ToUpper(s))
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/store.go b/vendor/github.com/emersion/go-imap/commands/store.go
new file mode 100644
index 0000000..aeee3e6
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/store.go
@@ -0,0 +1,50 @@
+package commands
+
+import (
+ "errors"
+ "strings"
+
+ "github.com/emersion/go-imap"
+)
+
+// Store is a STORE command, as defined in RFC 3501 section 6.4.6.
+type Store struct {
+ SeqSet *imap.SeqSet
+ Item imap.StoreItem
+ Value interface{}
+}
+
+func (cmd *Store) Command() *imap.Command {
+ return &imap.Command{
+ Name: "STORE",
+ Arguments: []interface{}{cmd.SeqSet, imap.RawString(cmd.Item), cmd.Value},
+ }
+}
+
+func (cmd *Store) Parse(fields []interface{}) error {
+ if len(fields) < 3 {
+ return errors.New("No enough arguments")
+ }
+
+ seqset, ok := fields[0].(string)
+ if !ok {
+ return errors.New("Invalid sequence set")
+ }
+ var err error
+ if cmd.SeqSet, err = imap.ParseSeqSet(seqset); err != nil {
+ return err
+ }
+
+ if item, ok := fields[1].(string); !ok {
+ return errors.New("Item name must be a string")
+ } else {
+ cmd.Item = imap.StoreItem(strings.ToUpper(item))
+ }
+
+ if len(fields[2:]) == 1 {
+ cmd.Value = fields[2]
+ } else {
+ cmd.Value = fields[2:]
+ }
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/subscribe.go b/vendor/github.com/emersion/go-imap/commands/subscribe.go
new file mode 100644
index 0000000..6540969
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/subscribe.go
@@ -0,0 +1,63 @@
+package commands
+
+import (
+ "errors"
+
+ "github.com/emersion/go-imap"
+ "github.com/emersion/go-imap/utf7"
+)
+
+// Subscribe is a SUBSCRIBE command, as defined in RFC 3501 section 6.3.6.
+type Subscribe struct {
+ Mailbox string
+}
+
+func (cmd *Subscribe) Command() *imap.Command {
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+
+ return &imap.Command{
+ Name: "SUBSCRIBE",
+ Arguments: []interface{}{imap.FormatMailboxName(mailbox)},
+ }
+}
+
+func (cmd *Subscribe) Parse(fields []interface{}) error {
+ if len(fields) < 0 {
+ return errors.New("No enough arguments")
+ }
+
+ if mailbox, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if cmd.Mailbox, err = utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ }
+ return nil
+}
+
+// An UNSUBSCRIBE command.
+// See RFC 3501 section 6.3.7
+type Unsubscribe struct {
+ Mailbox string
+}
+
+func (cmd *Unsubscribe) Command() *imap.Command {
+ mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
+
+ return &imap.Command{
+ Name: "UNSUBSCRIBE",
+ Arguments: []interface{}{imap.FormatMailboxName(mailbox)},
+ }
+}
+
+func (cmd *Unsubscribe) Parse(fields []interface{}) error {
+ if len(fields) < 0 {
+ return errors.New("No enogh arguments")
+ }
+
+ if mailbox, err := imap.ParseString(fields[0]); err != nil {
+ return err
+ } else if cmd.Mailbox, err = utf7.Encoding.NewDecoder().String(mailbox); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/uid.go b/vendor/github.com/emersion/go-imap/commands/uid.go
new file mode 100644
index 0000000..979af14
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/uid.go
@@ -0,0 +1,44 @@
+package commands
+
+import (
+ "errors"
+ "strings"
+
+ "github.com/emersion/go-imap"
+)
+
+// Uid is a UID command, as defined in RFC 3501 section 6.4.8. It wraps another
+// command (e.g. wrapping a Fetch command will result in a UID FETCH).
+type Uid struct {
+ Cmd imap.Commander
+}
+
+func (cmd *Uid) Command() *imap.Command {
+ inner := cmd.Cmd.Command()
+
+ args := []interface{}{imap.RawString(inner.Name)}
+ args = append(args, inner.Arguments...)
+
+ return &imap.Command{
+ Name: "UID",
+ Arguments: args,
+ }
+}
+
+func (cmd *Uid) Parse(fields []interface{}) error {
+ if len(fields) < 0 {
+ return errors.New("No command name specified")
+ }
+
+ name, ok := fields[0].(string)
+ if !ok {
+ return errors.New("Command name must be a string")
+ }
+
+ cmd.Cmd = &imap.Command{
+ Name: strings.ToUpper(name), // Command names are case-insensitive
+ Arguments: fields[1:],
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/emersion/go-imap/commands/unselect.go b/vendor/github.com/emersion/go-imap/commands/unselect.go
new file mode 100644
index 0000000..da5c63d
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/commands/unselect.go
@@ -0,0 +1,17 @@
+package commands
+
+import (
+ "github.com/emersion/go-imap"
+)
+
+// An UNSELECT command.
+// See RFC 3691 section 2.
+type Unselect struct{}
+
+func (cmd *Unselect) Command() *imap.Command {
+ return &imap.Command{Name: "UNSELECT"}
+}
+
+func (cmd *Unselect) Parse(fields []interface{}) error {
+ return nil
+}