func fetch(c *imap.Client, user string, thread Thread) ([]*ParsedMail, error) { var set imap.SeqSet for _, uid := range thread { set.AddNum(uid) } cmd, err := imap.Wait(c.UIDFetch(&set, "BODY[]", "X-GM-MSGID", "X-GM-THRID")) if err != nil { return nil, ErrBadConnection } parsed := make([]*ParsedMail, len(cmd.Data)) for i, rsp := range cmd.Data { p, err := parseMail(imap.AsBytes(rsp.MessageInfo().Attrs["BODY[]"]), user) if err != nil { return nil, err } link, err := gmailLink(imap.AsString(rsp.MessageInfo().Attrs["X-GM-MSGID"])) if err != nil { return nil, err } p.GmailLink = link p.Thrid = imap.AsString(rsp.MessageInfo().Attrs["X-GM-THRID"]) parsed[i] = p } return parsed, nil }
func archive(c *imap.Client, thrid string) error { cmd, err := imap.Wait(c.UIDSearch("X-GM-THRID", thrid)) if err != nil { log.Println(err) return ErrBadConnection } if len(cmd.Data) == 0 { return nil } var set imap.SeqSet set.AddNum(cmd.Data[0].SearchResults()...) _, err = imap.Wait(c.UIDStore(&set, "+FLAGS.SILENT", `(\Deleted)`)) return err }
// 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 }
// fetchMessage send UID FETCH command to retrieve message body func fetchMessage(client *imap.Client, messageUID uint32) ([]byte, error) { seq := new(imap.SeqSet) seq.AddNum(messageUID) cmd, err := imap.Wait(client.UIDFetch(seq, "INTERNALDATE", "BODY[]", "UID", "RFC822.HEADER")) if err != nil { logger.Errorf("Unable to fetch message (%d): %s", messageUID, err.Error()) return nil, nil } if len(cmd.Data) == 0 { logger.WithField("uid", messageUID).Info("Unable to fetch message from src: NO DATA") return nil, errors.New("message not found") } msgFields := cmd.Data[0].MessageInfo().Attrs body := imap.AsBytes(msgFields["BODY[]"]) cmd.Data = nil return body, nil }
// loadMessages will search and fetch message body func loadMessages(client *imap.Client, config *Config) error { cmd, err := imap.Wait(client.UIDSearch("FROM", client.Quote(config.From), "UNSEEN")) if err != nil { return err } seq := new(imap.SeqSet) if len(cmd.Data) > 0 { seq.AddNum(cmd.Data[0].SearchResults()...) } if seq.Empty() { return nil } logger.Infof("Fetched UIDs %v", seq) cmd, err = imap.Wait(client.UIDFetch(seq, "FLAGS", "INTERNALDATE", "RFC822.SIZE", "BODY[]")) if err != nil { return err } for _, rsp := range cmd.Data { body, err := fetchMessage(client, rsp.MessageInfo().UID) if err != nil { logger.Fatal(err) return err } err = writeFileFromBody(bytes.NewReader(body), config) if err != nil { logger.Fatal(err) return err } } if !seq.Empty() { _, err = imap.Wait(client.UIDStore(seq, "+FLAGS.SILENT", imap.NewFlagSet(`\Seen`))) } cmd.Data = nil return err }