Esempio n. 1
0
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")
	}
}
Esempio n. 2
0
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")
	}
}
Esempio n. 3
0
// 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)
}
Esempio n. 4
0
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")
}