func cmdCopy(args commandArgs, c *Conn) { if !c.assertSelected(args.ID(), readWrite) { return } // Check if the target mailbox exists. targetMailbox := args.Arg(copyArgMailbox) mbox, err := c.User.MailboxByName(targetMailbox) if err != nil { c.writeResponse(args.ID(), "NO [TRYCREATE] "+err.Error()) return } // Check if connection is writable. if c.mailboxWritable != readWrite { c.writeResponse(args.ID(), "NO read-only connection") return } // Fetch the messages. seqSet, err := types.InterpretSequenceSet(args.Arg(copyArgRange)) if err != nil { c.writeResponse(args.ID(), "NO "+err.Error()) return } searchByUID := strings.ToUpper(args.Arg(copyArgUID)) == "UID " var msgs []mailstore.Message if searchByUID { msgs = c.SelectedMailbox.MessageSetByUID(seqSet) } else { msgs = c.SelectedMailbox.MessageSetBySequenceNumber(seqSet) } if len(msgs) == 0 { c.writeResponse(args.ID(), "NO no messages found") return } for _, msg := range msgs { _, err := mbox.NewMessage(). SetBody(msg.Body()). SetHeaders(msg.Header()). AddFlags(msg.Flags() & types.FlagRecent). Save() if err != nil { // TODO Reverse all previous operations if it failed. c.writeResponse(args.ID(), "NO "+err.Error()) return } } if searchByUID { c.writeResponse(args.ID(), "OK UID COPY Completed") } else { c.writeResponse(args.ID(), "OK COPY Completed") } }
func cmdFetch(args commandArgs, c *Conn) { if !c.assertSelected(args.ID(), readOnly) { return } // Fetch the messages seqSet, err := types.InterpretSequenceSet(args.Arg(fetchArgRange)) if err != nil { c.writeResponse(args.ID(), "NO "+err.Error()) return } searchByUID := strings.ToUpper(args.Arg(fetchArgUID)) == "UID " var msgs []mailstore.Message if searchByUID { msgs = c.SelectedMailbox.MessageSetByUID(seqSet) } else { msgs = c.SelectedMailbox.MessageSetBySequenceNumber(seqSet) } fetchParamString := args.Arg(fetchArgParams) if searchByUID && !strings.Contains(fetchParamString, "UID") { fetchParamString += " UID" } for _, msg := range msgs { fetchParams, err := fetch(fetchParamString, c, msg) if err != nil { if err == ErrUnrecognisedParameter { c.writeResponse(args.ID(), "BAD Unrecognised Parameter") return } c.writeResponse(args.ID(), "BAD") return } if c.mailboxWritable == readWrite { msg = msg.RemoveFlags(types.FlagRecent) msg, err = msg.Save() if err != nil { // TODO: this error is not fatal, but should still be logged } } fullReply := fmt.Sprintf("%d FETCH (%s)", msg.SequenceNumber(), fetchParams) c.writeResponse("", fullReply) } if searchByUID { c.writeResponse(args.ID(), "OK UID FETCH Completed") } else { c.writeResponse(args.ID(), "OK FETCH Completed") } }
// Run a query and return the result. func (x *MessageSetByUIDTestCase) Run(tc TestContext) []mailstore.Message { set, err := types.InterpretSequenceSet(x.set) if err != nil { return nil } mailbox := tc.MakeMailbox("test inbox", x.emails, x.nextID) if mailbox == nil { return nil } return mailbox.MessageSetByUID(set) }
func cmdStoreFlags(args commandArgs, c *Conn) { if !c.assertSelected(args.ID(), ReadWrite) { return } operation := args.Arg(storeArgOperation) flags := args.Arg(storeArgFlags) uid := strings.ToUpper(args.Arg(storeArgUID)) == "UID " seqSetStr := args.Arg(storeArgRange) silent := false if args.Arg(storeArgSilent) == ".SILENT" { silent = true } var msgs []mailstore.Message seqSet, err := types.InterpretSequenceSet(seqSetStr) if err != nil { c.writeResponse(args.ID(), "NO "+err.Error()) return } if uid { msgs = c.SelectedMailbox.MessageSetByUID(seqSet) } else { msgs = c.SelectedMailbox.MessageSetBySequenceNumber(seqSet) } flagField := types.FlagsFromString(flags) for _, msg := range msgs { if operation == "+" { msg = msg.AddFlags(flagField) } else if operation == "-" { msg = msg.RemoveFlags(flagField) } else { msg = msg.OverwriteFlags(flagField) } msg.Save() if err != nil { c.writeResponse(args.ID(), "NO "+err.Error()) return } // Auto-fetch for the client if !silent { newFlags, err := fetch("FLAGS", c, msg) if err != nil { c.writeResponse(args.ID(), "NO "+err.Error()) return } fetchResponse := fmt.Sprintf("%d FETCH (%s)", msg.SequenceNumber(), newFlags, ) c.writeResponse("", fetchResponse) } } c.writeResponse(args.ID(), "OK STORE Completed") }