Пример #1
0
// getEmails will fetch the full bodies of all emails listed in the given command.
func getEmails(client *imap.Client, cmd *imap.Command) ([]map[string]interface{}, error) {
	var emails []map[string]interface{}
	seq := new(imap.SeqSet)
	for _, rsp := range cmd.Data {
		for _, uid := range rsp.SearchResults() {
			seq.AddNum(uid)
		}
	}
	if seq.Empty() {
		return emails, nil
	}
	fCmd, err := imap.Wait(client.UIDFetch(seq, "INTERNALDATE", "BODY[]", "UID", "RFC822.HEADER"))
	if err != nil {
		return emails, err
	}

	var email map[string]interface{}
	for _, msgData := range fCmd.Data {
		msgFields := msgData.MessageInfo().Attrs
		email, err = newEmailMessage(msgFields)
		if err != nil {
			return emails, err
		}
		emails = append(emails, email)

		// mark message as read
		fSeq := new(imap.SeqSet)
		fSeq.AddNum(imap.AsNumber(msgFields["UID"]))
		_, err = imap.Wait(client.UIDStore(fSeq, "+FLAGS", "\\SEEN"))
		if err != nil {
			return emails, err
		}
	}
	return emails, nil
}
Пример #2
0
func FetchAllUIDs(c *imap.Client) (uids []uint32, err error) {
	maxmessages := 150000
	uids = make([]uint32, maxmessages)

	set, errS := imap.NewSeqSet("1:*")
	if errS != nil {
		err = errS
		return
	}

	cmd, errF := c.UIDFetch(set, "RFC822.SIZE")
	if errF != nil {
		err = errF
		return
	}

	messagenum := uint32(0)
	for cmd.InProgress() {
		errC := c.Recv(-1)
		if errC != nil {
			continue
		}
		for _, rsp := range cmd.Data {
			uid := imap.AsNumber(rsp.MessageInfo().Attrs["UID"])
			uids[messagenum] = uid
		}
		cmd.Data = nil
		messagenum++
	}

	uids = uids[:messagenum]
	return
}
Пример #3
0
func FetchMessages(c *imap.Client, uidSet *imap.SeqSet) (fetched []MsgData, err error) {
	cmd, errF := c.UIDFetch(uidSet, "RFC822")
	if errF != nil {
		err = errF
		return
	}

	for cmd.InProgress() {
		errC := c.Recv(-1)
		if errC != nil {
			return
		}
		for _, rsp := range cmd.Data {

			uid := imap.AsNumber(rsp.MessageInfo().Attrs["UID"])
			mime := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822"])
			msg, errR := mail.ReadMessage(bytes.NewReader(mime))
			if errR != nil {
				continue
			}
			if msg != nil {
				msgdata := GetMessage(msg, uid)
				fetched = append(fetched, msgdata)
			}
		}
		cmd.Data = nil
	}

	return
}
Пример #4
0
// findUnreadEmails will run a find the UIDs of any unread emails in the
// mailbox.
func findUnreadEmails(conn *imap.Client) (*imap.Command, error) {
	// get headers and UID for UnSeen message in src inbox...
	cmd, err := imap.Wait(conn.UIDSearch("UNSEEN"))
	if err != nil {
		return &imap.Command{}, err
	}
	return cmd, nil
}
Пример #5
0
// checkAndStoreMessages will wait for WorkRequests to come acorss the pipe. When it receives a request, it will search
// the given destination inbox for the message. If it is not found, this method will attempt to pull the messages data
// from fetchRequests and then append it to the destination.
func CheckAndAppendMessages(dstConn *imap.Client, storeRequests chan WorkRequest, fetchRequests chan fetchRequest, wg *sync.WaitGroup) {
	defer wg.Done()

	// noop it every few to keep things alive
	timeout := time.NewTicker(NoopMinutes * time.Minute)
	done := false
	for {
		select {
		case request, ok := <-storeRequests:
			if !ok {
				done = true
				break
			}
			// search for in dst
			cmd, err := imap.Wait(dstConn.UIDSearch([]imap.Field{"HEADER", request.Header, request.Value}))
			if err != nil {
				log.Printf("Unable to search for message (%s): %s. skippin!", request.Value, err.Error())
				continue
			}

			results := cmd.Data[0].SearchResults()
			// if not found, PULL from SRC and STORE in DST
			if len(results) == 0 {
				// only fetch if we dont have data already
				if len(request.Msg.Body) == 0 {
					// build and send fetch request
					response := make(chan MessageData)
					fr := fetchRequest{MessageId: request.Value, UID: request.UID, Response: response}
					fetchRequests <- fr

					// grab response from fetchers
					request.Msg = <-response
				}
				if len(request.Msg.Body) == 0 {
					log.Printf("No data found for from fetch request (%s). giving up", request.Value)
					continue
				}

				err = AppendMessage(dstConn, request.Msg)
				if err != nil {
					log.Printf("Problems appending message to dst: %s. quitting.", err.Error())
					return
				}

			}

		case <-timeout.C:
			imap.Wait(dstConn.Noop())
		}

		if done {
			break
		}
	}

	log.Print("storer complete!")
	return
}
Пример #6
0
// FetchEmails will sit and wait for fetchRequests from the destination workers.
func fetchEmails(conn *imap.Client, requests chan fetchRequest, cache *Cache) {

	// noop every few to keep things alive
	timeout := time.NewTicker(NoopMinutes * time.Minute)
	done := false
	for {
		select {
		case request, ok := <-requests:
			if !ok {
				done = true
				break
			}
			found := true
			// check if the message body is in cache
			data, err := cache.Get(request.MessageId)
			if err != nil {
				found = false
				if err != ErrNotFound {
					log.Printf("problems pulling message data from cache: %s. Pulling message from src...", err.Error())
				}
				data = MessageData{}
			}

			if found {
				log.Print("cache success!")
				request.Response <- data
				continue
			}

			msgData, err := FetchMessage(conn, request.UID)
			if err != nil {
				if err == NotFound {
					log.Printf("No data found for UID: %d", request.UID)
				} else {
					log.Printf("Problems fetching message (%s) data: %s. Passing request and quitting.", request.MessageId, err.Error())
					requests <- request
					return
				}
			}
			request.Response <- msgData

			err = cache.Put(request.MessageId, msgData)
			if err != nil {
				log.Printf("Unable to add message (%s) to cache: %s", request.MessageId, err.Error())
			}

		case <-timeout.C:
			imap.Wait(conn.Noop())
		}

		if done {
			break
		}
	}

}
Пример #7
0
func ResetConnection(conn *imap.Client, readOnly bool) error {
	// dont check for error because its possible it's already closed.
	conn.Close(!readOnly)

	_, err := imap.Wait(conn.Select("INBOX", readOnly))
	if err != nil {
		return err
	}

	return nil
}
Пример #8
0
func GetAllMessages(conn *imap.Client) (*imap.Command, error) {
	// get headers and UID for ALL message in src inbox...
	allMsgs, _ := imap.NewSeqSet("")
	allMsgs.Add("1:*")
	cmd, err := imap.Wait(conn.Fetch(allMsgs, "RFC822.HEADER", "UID"))
	if err != nil {
		return &imap.Command{}, err
	}

	return cmd, nil
}
Пример #9
0
func SearchUIDs(c *imap.Client, query string) (uids []uint32, err error) {
	cmd, err := c.UIDSearch("X-GM-RAW", fmt.Sprint("\"", query, "\""))

	for cmd.InProgress() {
		c.Recv(-1)
		for _, rsp := range cmd.Data {
			uids = rsp.SearchResults()
		}
		cmd.Data = nil
	}
	return
}
Пример #10
0
func FetchMessages(c *imap.Client, uidSet *imap.SeqSet) (err error) {
	cmd, err := c.UIDFetch(uidSet, "RFC822")

	for cmd.InProgress() {
		c.Recv(-1)
		for _, rsp := range cmd.Data {
			uid := imap.AsNumber(rsp.MessageInfo().Attrs["UID"])
			mime := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822"])
			if msg, _ := mail.ReadMessage(bytes.NewReader(mime)); msg != nil {
				PrintMessageAsJSON(msg, uid)
			}
		}
		cmd.Data = nil
	}

	return
}
Пример #11
0
func checkMessagesExist(srcConn *imap.Client, checkRequests chan checkExistsRequest, wg *sync.WaitGroup) {
	defer wg.Done()
	// get memcache client
	cache := memcache.New(MemcacheServer)

	timeout := time.NewTicker(NoopMinutes * time.Minute)
	done := false
	for {
		select {
		case request, ok := <-checkRequests:
			if !ok {
				done = true
				break
			}
			// check if it exists in src
			// search for in src
			cmd, err := imap.Wait(srcConn.UIDSearch([]imap.Field{"HEADER", "Message-Id", request.MessageId}))
			if err != nil {
				log.Printf("Unable to search source: %s", err.Error())
				request.Response <- true
				continue
			}

			results := cmd.Data[0].SearchResults()
			// if not found, mark for deletion in DST
			found := (len(results) > 0)

			// response with found bool
			request.Response <- found

			// if it doesnt exist, attempt to remove it from memcached
			if !found {
				cache.Delete(request.MessageId)
			}
		case <-timeout.C:
			imap.Wait(srcConn.Noop())
		}

		if done {
			break
		}
	}

}
Пример #12
0
func FetchMessage(conn *imap.Client, messageUID uint32) (msg MessageData, err error) {
	seq, _ := imap.NewSeqSet("")
	seq.AddNum(messageUID)
	var cmd *imap.Command
	cmd, err = imap.Wait(conn.UIDFetch(seq, "INTERNALDATE", "BODY[]", "UID", "RFC822.HEADER"))
	if err != nil {
		log.Printf("Unable to fetch message (%d): %s", messageUID, err.Error())
		return
	}

	if len(cmd.Data) == 0 {
		log.Printf("Unable to fetch message (%d) from src: NO DATA", messageUID)
		return msg, NotFound
	}

	msgFields := cmd.Data[0].MessageInfo().Attrs
	msg = MessageData{InternalDate: imap.AsDateTime(msgFields["INTERNALDATE"]), Body: imap.AsBytes(msgFields["BODY[]"])}
	return msg, nil
}
Пример #13
0
func checkAndPurgeMessages(conn *imap.Client, requests chan WorkRequest, checkRequests chan checkExistsRequest, wg *sync.WaitGroup) {
	defer wg.Done()

	timeout := time.NewTicker(NoopMinutes * time.Minute)
	done := false
	for {
		select {
		case request, ok := <-requests:
			if !ok {
				done = true
				break
			}
			// check and wait for response
			response := make(chan bool)
			cr := checkExistsRequest{UID: request.UID, MessageId: request.Value, Response: response}
			checkRequests <- cr

			// if response is false (does not exist), flag as Deleted
			if exists := <-response; !exists {
				log.Printf("not found in src. marking for deletion: %s", request.Value)
				err := AddDeletedFlag(conn, request.UID)
				if err != nil {
					log.Printf("Problems removing message from dst: %s", err.Error())
				}
			}
		case <-timeout.C:
			imap.Wait(conn.Noop())
		}

		if done {
			break
		}
	}

	log.Printf("expunging...")
	// expunge at the end
	allMsgs, _ := imap.NewSeqSet("")
	allMsgs.Add("1:*")
	imap.Wait(conn.Expunge(allMsgs))
	log.Printf("expunge complete.")
}
Пример #14
0
func GetUIDs(mbox string, client *imap.Client) ([]uint32, error) {

	uids := make([]uint32, 0)

	cmd, err := client.Select(mbox, true)
	if err != nil {
		return uids, err
	}

	//== Get UIDS of all messages
	cmd, err = imap.Wait(client.UIDSearch("", "ALL"))
	if err != nil {
		return uids, err
	}

	for idx := range cmd.Data {
		for _, uid := range cmd.Data[idx].SearchResults() {
			uids = append(uids, uid)
		}
	}
	return uids, nil

}
Пример #15
0
// getNextUID will grab the next message UID from the inbox. Client.Mailbox.UIDNext is cached so we can't use it.
func getNextUID(conn *imap.Client) (uint32, error) {
	cmd, err := imap.Wait(conn.Status("INBOX", "UIDNEXT"))
	if err != nil {
		return 0, err
	}

	if len(cmd.Data) == 0 {
		return 0, errors.New("no data returned!")
	}

	var status *imap.MailboxStatus
	for _, resp := range cmd.Data {
		switch resp.Type {
		case imap.Data:
			status = resp.MailboxStatus()
			if status != nil {
				break
			}
		}
	}

	return status.UIDNext, nil
}
Пример #16
0
func sensitive(c *imap.Client, action string) imap.LogMask {
	mask := c.SetLogMask(imap.LogConn)
	hide := imap.LogCmd | imap.LogRaw
	if mask&hide != 0 {
		c.Logln(imap.LogConn, "Raw logging disabled during", action)
	}
	c.SetLogMask(mask &^ hide)
	return mask
}
Пример #17
0
//= Return list of IMAP folders
func GetFolders(client *imap.Client) ([]*Folder, error) {

	folders := make([]*Folder, 0)

	cmd, err := imap.Wait(client.List("", "*"))
	if err != nil {
		return folders, err
	}

	for idx := range cmd.Data {
		info := cmd.Data[idx].MailboxInfo()
		fol := new(Folder)
		fol.Name = info.Name
		for flag, boo := range info.Attrs {
			fmt.Println(info.Name, boo, flag)
			if info.Name == "INBOX" && boo {
				fol.Type = "inbox"

			} else if flag == "\\Junk" && boo {
				fol.Type = "junk"

			} else if flag == "\\Trash" && boo {
				fol.Type = "trash"

			} else if flag == "\\Sent" && boo {
				fol.Type = "sent"

			} else if flag == "\\Drafts" && boo {
				fol.Type = "drafts"
			}

		}
		folders = append(folders, fol)
	}

	return folders, nil
}
Пример #18
0
// use whatever imap connection type is specified by s.UseTLS
func (s *Server) Connect() (*imap.Client, error) {
	if s.client != nil {
		s.disconnectTimer.Reset(NoUsageDisconnect)
		return s.client, nil
	}

	var c *imap.Client
	var err error

	// actual dailing happens
	if s.UseTLS {
		c, err = s.dialTLS()
	} else {
		c, err = s.dial()
	}
	if err != nil {
		return nil, err
	}

	// log in
	if c.State() == imap.Login {
		_, err := c.Login(s.Username, s.Password)
		if err != nil {
			s.Close()
			return nil, err
		}
	} else {
		s.Close()
		return nil, fmt.Errorf("expected imap.Login state, instead was %v.", c.State())
	}

	// auto-disconnect after a certain timeout
	s.disconnectTimer = time.AfterFunc(NoUsageDisconnect, func() {
		s.Close()
	})

	return c, nil
}
Пример #19
0
func login(c *imap.Client, user, pass string) (cmd *imap.Command, err error) {
	defer c.SetLogMask(sensitive(c, "LOGIN"))
	return c.Login(user, pass)
}
Пример #20
0
func ExampleClient() {
	//
	// Note: most of error handling code is omitted for brevity
	//
	var (
		c   *imap.Client
		cmd *imap.Command
		rsp *imap.Response
	)

	// Connect to the server
	c, _ = imap.Dial("imap.example.com")

	// Remember to log out and close the connection when finished
	defer c.Logout(30 * time.Second)

	// Print server greeting (first response in the unilateral server data queue)
	fmt.Println("Server says hello:", c.Data[0].Info)
	c.Data = nil

	// Enable encryption, if supported by the server
	if c.Caps["STARTTLS"] {
		c.StartTLS(nil)
	}

	// Authenticate
	if c.State() == imap.Login {
		c.Login("*****@*****.**", "mysupersecretpassword")
	}

	// List all top-level mailboxes, wait for the command to finish
	cmd, _ = imap.Wait(c.List("", "%"))

	// Print mailbox information
	fmt.Println("\nTop-level mailboxes:")
	for _, rsp = range cmd.Data {
		fmt.Println("|--", rsp.MailboxInfo())
	}

	// Check for new unilateral server data responses
	for _, rsp = range c.Data {
		fmt.Println("Server data:", rsp)
	}
	c.Data = nil

	// Open a mailbox (synchronous command - no need for imap.Wait)
	c.Select("INBOX", true)
	fmt.Print("\nMailbox status:\n", c.Mailbox)

	// Fetch the headers of the 10 most recent messages
	set, _ := imap.NewSeqSet("")
	if c.Mailbox.Messages >= 10 {
		set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages)
	} else {
		set.Add("1:*")
	}
	cmd, _ = c.Fetch(set, "RFC822.HEADER")

	// Process responses while the command is running
	fmt.Println("\nMost recent messages:")
	for cmd.InProgress() {
		// Wait for the next response (no timeout)
		c.Recv(-1)

		// Process command data
		for _, rsp = range cmd.Data {
			header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
			if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
				fmt.Println("|--", msg.Header.Get("Subject"))
			}
		}
		cmd.Data = nil

		// Process unilateral server data
		for _, rsp = range c.Data {
			fmt.Println("Server data:", rsp)
		}
		c.Data = nil
	}

	// Check command completion status
	if rsp, err := cmd.Result(imap.OK); err != nil {
		if err == imap.ErrAborted {
			fmt.Println("Fetch command aborted")
		} else {
			fmt.Println("Fetch error:", rsp.Info)
		}
	}
}
Пример #21
0
// Idle setup the processes to wait for notifications from the IMAP source connection.
// If an EXISTS or EXPUNGE command comes across the pipe, the appropriate actions will be
// taken to update the destinations. If the process decides the inboxes are out of sync,
// it will pass a bool to the requestPurge channel. It is expected that the requestPurge
// channel is setup to initiate a purge process when it receives the notificaiton.
func Idle(src *imap.Client, appendRequests []chan WorkRequest, requestPurge chan bool) (err error) {
	var nextUID uint32
	if nextUID, err = getNextUID(src); err != nil {
		log.Printf("Unable to get UIDNext: %s", err.Error())
		return err
	}

	// hold the size so we can determine how to react to commands
	startSize := src.Mailbox.Messages

	// setup interrupt signal channel to terminate the idle
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, os.Kill)

	// setup ticker to reset the idle every 20 minutes (RFC-2177 recommends 29 mins max)
	timeout := time.NewTicker(idleTimeoutMinutes * time.Minute)

	// setup poller signal for checking for data on the idle command
	poll := make(chan bool, 1)
	poll <- true

	log.Print("beginning idle...")
	_, idleErr := src.Idle()
	if (idleErr != nil) && (idleErr != imap.ErrTimeout) {
		log.Printf("Idle error: %s", idleErr.Error())
		return
	}

	for {

		select {
		// if we receive a 'poll' we should check the pipe for new messages
		case <-poll:

			err = src.Recv(0)
			if (idleErr != nil) && (idleErr != imap.ErrTimeout) {
				log.Printf("Idle error: %s", idleErr.Error())
				go sleep(poll)
				continue
			}

			// cache the data so we dont mess it up while start/stopping idle
			var tempData []*imap.Response
			tempData = append(tempData, src.Data...)
			src.Data = nil
			for _, data := range tempData {
				switch data.Type {
				case imap.Data:
					// len of 2 likely means its an EXPUNGE or EXISTS command...
					if len(data.Fields) == 2 {
						msgNum := imap.AsNumber(data.Fields[0])

						switch data.Fields[1] {
						case "EXPUNGE":
							log.Printf("Received an EXPUNGE notification requesting purge - %d", msgNum)
							startSize = msgNum
							requestPurge <- true

						case "EXISTS":
							log.Printf("Received an EXISTS notification - %d", msgNum)
							if startSize > msgNum {
								log.Printf("Mailbox decreased in size %d --> %d. Requesting a purge. MAILBOX MAY NEED TO SYNC", startSize, msgNum)
								requestPurge <- true
								startSize = msgNum
								continue
							}

							// temporarily term the idle so we can fetch the message
							if _, err = src.IdleTerm(); err != nil {
								log.Printf("error while temporarily terminating idle: %s", err.Error())
								return
							}
							log.Printf("terminated idle. appending message.")

							newMessages := msgNum - startSize
							log.Printf("attempting to find/append %d new messages", newMessages)
							for i := uint32(0); i < newMessages; i++ {
								var request WorkRequest
								if request, err = getMessageInfo(src, nextUID); err == nil {

									log.Printf("creating %d append requests for %d", len(appendRequests), nextUID)
									for _, requests := range appendRequests {
										requests <- request
									}
									log.Printf("done creating append requests for %d", nextUID)
									nextUID++
									startSize++
								} else {
									log.Printf("Unable to find message for UID (%d): %s", nextUID, err.Error())
								}
							}

							log.Printf("continuing idle...")
							// turn idle back on
							if _, err = src.Idle(); err != nil {
								log.Printf("Unable to restart idle: %s", err.Error())
								return
							}
						}
					}
				}
			}

			go sleep(poll)

		case <-interrupt:
			log.Printf("Received interrupt. Terminating idle...")
			_, err = src.IdleTerm()
			if err != nil {
				log.Printf("error while terminating idle: %s", err.Error())
			}
			return
		case <-timeout.C:
			log.Printf("resetting idle...")
			_, err = src.IdleTerm()
			if err != nil {
				log.Printf("error while temporarily terminating idle: %s", err.Error())
				return
			}
			log.Printf("terminated idle.")

			// turn idle back on
			_, err = src.Idle()
			if err != nil {
				log.Printf("Unable to restart idle: %s", err.Error())
				return
			}
			log.Printf("idle restarted.")
		}
	}

	return
}
Пример #22
0
func GetMessage(folder, uid string, client *imap.Client) (messag *Message, e error) {

	cmd, err := client.Select(folder, true)
	if err != nil {
		return nil, err
	}

	uidlist, _ := imap.NewSeqSet(uid)
	//uidlist.Add(uid)

	fmt.Println("get_mess", folder, uid)
	mess := new(Message)
	mess.Folder = folder

	cmd, err = imap.Wait(client.UIDFetch(uidlist, "FLAGS", "INTERNALDATE", "RFC822.SIZE", "RFC822")) //  "RFC822.HEADER",  "BODY.PEEK[TEXT]") )
	if err != nil {
		return mess, err
	}
	fmt.Println(len(cmd.Data), cmd.Data)
	rsp := cmd.Data[0]
	minfo := rsp.MessageInfo()

	mess.Uid = minfo.UID

	msg, _ := mail.ReadMessage(bytes.NewReader(imap.AsBytes(minfo.Attrs["RFC822"])))
	mime, mime_err := enmime.ParseMIMEBody(msg)

	for flag, boo := range minfo.Flags {
		if flag == "\\Seen" && boo {
			mess.Seen = true
		}
		if flag == "\\Flagged" && boo {
			mess.Flagged = true
		}
	}
	/*
		bites := imap.AsBytes(minfo.Attrs["RFC822"])
		msg, msg_err := mail.ReadMessage(bytes.NewReader(bites))
		if msg_err != nil {
			return mess, msg_err
		}
	*/

	//fmt.Println(msg.Header.Get("Content-type"))
	//fmt.Println(msg.Header.Get("To"))
	//fmt.Println(msg.Header.Get("Delivered-To"))

	// From
	from, fro_err := mail.ParseAddress(msg.Header.Get("From"))
	if fro_err != nil {
		fmt.Println("address ettot")
	} else {
		mess.FromName = from.Name
		mess.FromEmail = from.Address
	}

	//for i, m := range minfo.Attrs {

	//fmt.Println(i,m)
	//}
	// Date
	dat := imap.AsDateTime(minfo.Attrs["INTERNALDATE"])
	mess.Date = dat.Format("2006-01-02 15:04:05")

	mess.Subject = msg.Header.Get("Subject")
	mess.ContentType = msg.Header.Get("Content-Type")
	//fmt.Println("body=", cmd.Data[0].String)

	//bodyb := imap.AsBytes(minfo.Attrs["BODY[TEXT]"])
	//bb := 	bytes.NewReader(bytes.NewReader(header + bodyb))

	//fmt.Println("bodyb=", string(msg.Body))

	//fmt.Printf("----\n%v\n", mime.Html == nil)
	//mess.Body = mime.Text
	if mime_err != nil {
		fmt.Println("err=", mime_err, mime)
	}
	//*/
	//fmt.Println("body=", body)

	mess.BodyText = mime.Text
	mess.BodyHtml = mime.Html //imap.AsString(minfo.Attrs["RFC822"])

	return mess, nil

}
Пример #23
0
func AddDeletedFlag(conn *imap.Client, uid uint32) error {
	seqSet, _ := imap.NewSeqSet("")
	seqSet.AddNum(uid)
	_, err := conn.UIDStore(seqSet, "+FLAGS", imap.NewFlagSet(`\Deleted`))
	return err
}
Пример #24
0
func AppendMessage(conn *imap.Client, messageData MessageData) error {
	_, err := imap.Wait(conn.Append("INBOX", imap.NewFlagSet("UnSeen"), &messageData.InternalDate, imap.NewLiteral(messageData.Body)))
	return err
}