1package commands
2
3import (
4	"errors"
5	"time"
6
7	"github.com/emersion/go-imap"
8	"github.com/emersion/go-imap/utf7"
9)
10
11// Append is an APPEND command, as defined in RFC 3501 section 6.3.11.
12type Append struct {
13	Mailbox string
14	Flags   []string
15	Date    time.Time
16	Message imap.Literal
17}
18
19func (cmd *Append) Command() *imap.Command {
20	var args []interface{}
21
22	mailbox, _ := utf7.Encoding.NewEncoder().String(cmd.Mailbox)
23	args = append(args, imap.FormatMailboxName(mailbox))
24
25	if cmd.Flags != nil {
26		flags := make([]interface{}, len(cmd.Flags))
27		for i, flag := range cmd.Flags {
28			flags[i] = imap.RawString(flag)
29		}
30		args = append(args, flags)
31	}
32
33	if !cmd.Date.IsZero() {
34		args = append(args, cmd.Date)
35	}
36
37	args = append(args, cmd.Message)
38
39	return &imap.Command{
40		Name:      "APPEND",
41		Arguments: args,
42	}
43}
44
45func (cmd *Append) Parse(fields []interface{}) (err error) {
46	if len(fields) < 2 {
47		return errors.New("No enough arguments")
48	}
49
50	// Parse mailbox name
51	if mailbox, err := imap.ParseString(fields[0]); err != nil {
52		return err
53	} else if mailbox, err = utf7.Encoding.NewDecoder().String(mailbox); err != nil {
54		return err
55	} else {
56		cmd.Mailbox = imap.CanonicalMailboxName(mailbox)
57	}
58
59	// Parse message literal
60	litIndex := len(fields) - 1
61	var ok bool
62	if cmd.Message, ok = fields[litIndex].(imap.Literal); !ok {
63		return errors.New("Message must be a literal")
64	}
65
66	// Remaining fields a optional
67	fields = fields[1:litIndex]
68	if len(fields) > 0 {
69		// Parse flags list
70		if flags, ok := fields[0].([]interface{}); ok {
71			if cmd.Flags, err = imap.ParseStringList(flags); err != nil {
72				return err
73			}
74
75			for i, flag := range cmd.Flags {
76				cmd.Flags[i] = imap.CanonicalFlag(flag)
77			}
78
79			fields = fields[1:]
80		}
81
82		// Parse date
83		if len(fields) > 0 {
84			if date, ok := fields[0].(string); !ok {
85				return errors.New("Date must be a string")
86			} else if cmd.Date, err = time.Parse(imap.DateTimeLayout, date); err != nil {
87				return err
88			}
89		}
90	}
91
92	return
93}
94