func (i *ImapSession) imapCleanup(folders []string) error { c := i.client for _, mbox := range folders { cmd, err := imap.Wait(c.Select(mbox, false)) if err != nil { fmt.Println("unable to select", mbox, "=>", err, i.client.State()) continue } fmt.Println("cleaning up", mbox) yesterday := time.Now().Add(-1 * 24 * time.Hour) cmd = imapMust(imap.Wait(c.UIDSearch("SEEN BEFORE " + yesterday.Format("02-Jan-2006") + " NOT FLAGGED"))) toDelete, _ := imap.NewSeqSet("") toDelete.AddNum(cmd.Data[0].SearchResults()...) if !toDelete.Empty() { fmt.Println("deleting...", toDelete) if i.isGmail { imapMust(imap.Wait(c.UIDStore(toDelete, "X-GM-LABELS", imap.NewFlagSet(`\Trash`)))) } else { imapMust(imap.Wait(c.UIDStore(toDelete, "+FLAGS.SILENT", imap.NewFlagSet(`\Deleted`)))) } imapMust(imap.Wait(c.Expunge(nil))) } } return nil }
func (i *ImapSession) Append(folder string, extraCopies []string, msg io.Reader) error { c := i.client mbox := folder buf := new(bytes.Buffer) buf.ReadFrom(msg) now := time.Now() cmd, err := imap.Wait(c.Append(mbox, nil, &now, imap.NewLiteral(buf.Bytes()))) if err != nil { fmt.Println(err) return err } rsp, err := cmd.Result(imap.OK) if err != nil { fmt.Println(err) return err } uid := imap.AsNumber(rsp.Fields[len(rsp.Fields)-1]) set, _ := imap.NewSeqSet("") set.AddNum(uid) imapMust(imap.Wait(c.Select(mbox, false))) for _, mb := range extraCopies { if i.isGmail { imapMust(imap.Wait(c.UIDStore(set, "X-GM-LABELS", imap.NewFlagSet(mb)))) } else { imapMust(c.UIDCopy(set, mb)) } } return nil }
//UnmarkEmails unmarks/resets flags of mails having uids from src with IMAP flag specified in imapFlag. //See RFC 3501 section 2.3.2 for a list of all valid flags. func UnMarkEmails(acct *IMAPAccount, src string, imapFlag string, uids []uint32, jobSize int, skipCerti bool) (err error) { imap.DefaultLogger = log.New(os.Stdout, "", 0) // imap.DefaultLogMask = imap.LogConn | imap.LogRaw log.Printf("Starting UnMarking for user '%s' on IMAP server '%s:%d'", acct.Username, acct.Server.Host, acct.Server.Port) if jobSize <= 0 { jobSize = 10 } c, errD := Dial(acct.Server, skipCerti) if errD != nil { err = errD return } _, err = login(c, acct.Username, acct.Password) if err != nil { return } defer c.Logout(-1) if src == "" { err = errors.New("No source provided") return } err = WaitResp(c.Select(src, false)) if err != nil { return } timestarted := time.Now() var jobs []*imap.SeqSet var jUids []uint32 for i := 0; i < len(uids); i++ { if i%(jobSize) == 0 && i != 0 { //Append the new job to jobs set, _ := imap.NewSeqSet("") set.AddNum(jUids[:]...) jobs = append(jobs, set) jUids = nil } jUids = append(jUids, uids[i]) if i == len(uids)-1 { //Last Element Encountered Add to jobs set, _ := imap.NewSeqSet("") set.AddNum(jUids[:]...) jobs = append(jobs, set) jUids = nil } } log.Printf("UnMarking: %d UIDs with %s total, %d jobs of size <= %d from %s\n", len(uids), imapFlag, len(jobs), jobSize, src) for _, jobUIDs := range jobs { log.Println("UnMarking ", jobUIDs) err = WaitResp(c.UIDStore(jobUIDs, "-FLAGS.SILENT", imap.NewFlagSet(imapFlag))) if err != nil { log.Println(err) continue } } err = WaitResp(c.Close(false)) if err != nil { log.Println("Error While Closing ", err) return } timeelapsed := time.Since(timestarted) msecpermessage := timeelapsed.Seconds() / float64(len(uids)) * 1000 messagespersec := float64(len(uids)) / timeelapsed.Seconds() log.Printf("Finished UnMarking %d messages in %.2fs (%.1fms per message; %.1f messages per second)\n", len(uids), timeelapsed.Seconds(), msecpermessage, messagespersec) return }
func AddDeletedFlag(conn *imap.Client, uid uint32) error { seqSet, _ := imap.NewSeqSet("") seqSet.AddNum(uid) _, err := conn.UIDStore(seqSet, "+FLAGS", imap.NewFlagSet(`\Deleted`)) return err }
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 }
func TestLiteral(T *testing.T) { t := mock.Server(T, `S: * PREAUTH [CAPABILITY IMAP4rev1] Server ready`, ) c, err := t.Dial() t.Join(err) flags := imap.NewFlagSet(`\Seen`) lines := []string{ "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)", "From: Fred Foobar <*****@*****.**>", "Subject: afternoon meeting", "To: [email protected]", "Message-Id: <*****@*****.**>", "MIME-Version: 1.0", "Content-Type: TEXT/PLAIN; CHARSET=US-ASCII", "", "Hello Joe, do you think we can meet at 3:30 tomorrow?", "", } msg := []byte(strings.Join(lines, "\r\n")) lit := imap.NewLiteral(msg) // Embedded literal t.Script( `C: A1 APPEND "saved-messages" (\Seen) {310}`, `S: + Ready for literal data`, `C: `+lines[0], `C: `+lines[1], `C: `+lines[2], `C: `+lines[3], `C: `+lines[4], `C: `+lines[5], `C: `+lines[6], `C: `+lines[7], `C: `+lines[8], `C: `+lines[9], `S: A1 OK APPEND completed`, ) _, err = imap.Wait(c.Append("saved-messages", flags, nil, lit)) t.Join(err) // Recv action literal t.Script( `C: A2 APPEND "saved-messages" (\Seen) {310}`, `S: + Ready for literal data`, mock.Recv(msg), `C: `, `S: A2 OK APPEND completed`, ) _, err = imap.Wait(c.Append("saved-messages", flags, nil, lit)) t.Join(err) // Embedded and Send action literals from the server t.Script( `C: A3 LIST "" "*"`, `S: * LIST (\Noselect) "/" {3}`, `S: foo`, `S: * LIST () "/" {7}`, mock.Send("foo/bar"), `S: `, `S: A3 OK LIST completed`, ) _, err = imap.Wait(c.List("", "*")) t.Join(err) }
func main() { imap.DefaultLogger = log.New(os.Stdout, "", 0) imap.DefaultLogMask = imap.LogConn | imap.LogRaw c := Dial(Addr) defer func() { ReportOK(c.Logout(30 * time.Second)) }() if c.Caps["STARTTLS"] { ReportOK(c.StartTLS(nil)) } if c.Caps["ID"] { ReportOK(c.ID("name", "goimap")) } ReportOK(c.Noop()) ReportOK(Login(c, User, Pass)) if c.Caps["QUOTA"] { ReportOK(c.GetQuotaRoot("INBOX")) } cmd := ReportOK(c.List("", "")) delim := cmd.Data[0].MailboxInfo().Delim mbox := MBox + delim + "Demo1" if cmd, err := imap.Wait(c.Create(mbox)); err != nil { if rsp, ok := err.(imap.ResponseError); ok && rsp.Status == imap.NO { ReportOK(c.Delete(mbox)) } ReportOK(c.Create(mbox)) } else { ReportOK(cmd, err) } ReportOK(c.List("", MBox)) ReportOK(c.List("", mbox)) ReportOK(c.Rename(mbox, mbox+"2")) ReportOK(c.Rename(mbox+"2", mbox)) ReportOK(c.Subscribe(mbox)) ReportOK(c.Unsubscribe(mbox)) ReportOK(c.Status(mbox)) ReportOK(c.Delete(mbox)) ReportOK(c.Create(mbox)) ReportOK(c.Select(mbox, true)) ReportOK(c.Close(false)) msg := []byte(strings.Replace(Msg[1:], "\n", "\r\n", -1)) ReportOK(c.Append(mbox, nil, nil, imap.NewLiteral(msg))) ReportOK(c.Select(mbox, false)) ReportOK(c.Check()) fmt.Println(c.Mailbox) cmd = ReportOK(c.UIDSearch("SUBJECT", c.Quote("GoIMAP"))) set, _ := imap.NewSeqSet("") set.AddNum(cmd.Data[0].SearchResults()...) ReportOK(c.Fetch(set, "FLAGS", "INTERNALDATE", "RFC822.SIZE", "BODY[]")) ReportOK(c.UIDStore(set, "+FLAGS.SILENT", imap.NewFlagSet(`\Deleted`))) ReportOK(c.Expunge(nil)) ReportOK(c.UIDSearch("SUBJECT", c.Quote("GoIMAP"))) fmt.Println(c.Mailbox) ReportOK(c.Close(true)) ReportOK(c.Delete(mbox)) }