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 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 }
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 }
// Retrieve metadata for all messages in a given mailbox. func (conn *Connection) Messages(box string, count uint32) ([]*MessageMeta, error) { conn.client.Select(box, true) // Create a range set that selects the most recent `count` messages (or // all messages if the mailbox contains fewer than that). Also, allocate a // slice for the results. set, _ := imap.NewSeqSet("") var messages []*MessageMeta totalCount := conn.client.Mailbox.Messages if totalCount >= count { set.AddRange(totalCount-(count-1), totalCount) messages = make([]*MessageMeta, count) } else { set.Add("1:*") messages = make([]*MessageMeta, totalCount) } // Fetch messages. cmd, err := conn.client.Fetch(set, "RFC822.HEADER RFC822.SIZE UID") if err != nil { return nil, err } // Parse each message. i := 0 for cmd.InProgress() { err = conn.client.Recv(time.Second * 5) if err != nil { return nil, err } // Process the message data received so far. for _, rsp := range cmd.Data { msgInfo := rsp.MessageInfo() header := imap.AsBytes(msgInfo.Attrs["RFC822.HEADER"]) msg, err := mail.ReadMessage(bytes.NewReader(header)) if err != nil { return nil, err } messages[i] = &MessageMeta{ UID: msgInfo.UID, Size: msgInfo.Size, Subject: msg.Header.Get("Subject"), } i++ } cmd.Data = nil } return messages, nil }
// Issue a FETCH request for this message // TODO make private, this is an abstraction-breaker func (m *Email) RetrieveRaw(requestType string) (cmd *imap.Command, err error) { c, err := m.server.Connect() if err != nil { return } // fetch message by UID set, err := imap.NewSeqSet(fmt.Sprintf("%d", m.UID)) if err != nil { return } cmd, err = c.UIDFetch(set, requestType) return cmd, err }
func GetLastUIDs(alluids []uint32) *imap.SeqSet { //payload.Uids, err = GetUIDs("INBOX", client) //= Calc last few messages lenny := len(alluids) last := lenny - 50 // ################ if last < 0 { last = 0 } //= Make List of messages uids uidlist, _ := imap.NewSeqSet("") for _, uid := range alluids[last:lenny] { uidlist.AddNum(uid) } return uidlist }
func PrintMail(acct *IMAPAccount, query string) { imap.DefaultLogger = log.New(os.Stdout, "", 0) // imap.DefaultLogMask = imap.LogConn | imap.LogRaw log.Printf("Running for user '%s' on IMAP server '%s:%d'", acct.Username, acct.Server.Host, acct.Server.Port) jobsize := 250 // Fetch UIDs. c := Dial(acct.Server) login(c, acct.Username, acct.Password) c.Select(mbox, true) uids, _ := SearchUIDs(c, query) timestarted := time.Now() nparts := (len(uids) + jobsize - 1) / jobsize jobs := make([]*imap.SeqSet, nparts) for i := 0; i < nparts; i++ { lo := i * jobsize hi_exclusive := (i + 1) * jobsize if hi_exclusive >= len(uids) { hi_exclusive = len(uids) - 1 for uids[hi_exclusive] == 0 { // hacky hi_exclusive-- } } set, _ := imap.NewSeqSet("") set.AddNum(uids[lo:hi_exclusive]...) jobs[i] = set } log.Printf("%d UIDs total, %d jobs of size <= %d\n", len(uids), len(jobs), jobsize) for _, jobUIDs := range jobs { FetchMessages(c, jobUIDs) } timeelapsed := time.Since(timestarted) msecpermessage := timeelapsed.Seconds() / float64(len(uids)) * 1000 messagespersec := float64(len(uids)) / timeelapsed.Seconds() log.Printf("Finished fetching %d messages in %.2fs (%.1fms per message; %.1f messages per second)\n", len(uids), timeelapsed.Seconds(), msecpermessage, messagespersec) c.Close(false) c.Logout(-1) }
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 }
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.") }
func (c *chatSyncClient) syncChats() error { log.Print("Starting sync...") // Create SeqSet specifying all messages set, err := imap.NewSeqSet("10:20") checkError(err) // Fetch all messages cmd, err := c.client.Fetch(set, "RFC822.HEADER", "BODY[TEXT]") checkError(err) for cmd.InProgress() { c.client.Recv(-1) for _, resp := range cmd.Data { go c.processChat(resp) } cmd.Data = nil } for { completed := <-c.done delete(c.messages, completed) allDone := true for k, _ := range c.messages { if !c.messages[k].done { allDone = false break } } if allDone { break } } log.Print("Processed all chats!") 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 }
//GetEmails gets Emails from mailbox mbox in Struct of Type MsgData. //It searches the mailbox for messages that match the given searching criteria mentioned in query string. //See RFC 3501 section 6.4.4 for a list of all valid search keys. //It is the caller's responsibility to quote strings when necessary. //All strings must use UTF-8 encoding. func GetEMails(acct *IMAPAccount, query string, mbox string, jobSize int, skipCerti bool) (mails []MsgData, err error) { imap.DefaultLogger = log.New(os.Stdout, "", 0) // imap.DefaultLogMask = imap.LogConn | imap.LogRaw log.Printf("Running for user '%s' on IMAP server '%s:%d'", acct.Username, acct.Server.Host, acct.Server.Port) if jobSize <= 0 { jobSize = 10 } // Fetch UIDs. 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 mbox == "" { mbox = "inbox" } err = WaitResp(c.Select(mbox, true)) if err != nil { return } uids, err1 := SearchUIDs(c, query) if err1 != nil { err = err1 return } timestarted := time.Now() var jobs []*imap.SeqSet var jUids []uint32 for i := 0; i < len(uids); i++ { /*Logic 1.If we are at last index len(uids)-1 and still have not reached jobSize limit then append that to jobs (In other words if set size is smaller then jobsize) 2.if we go over index of size greater then jobsize then add all elemetns up to that index in to jobs 3.0 mod n returns 0 hence i!=0 is checked */ 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("%d UIDs total, %d jobs of size <= %d\n", len(uids), len(jobs), jobSize) for _, jobUIDs := range jobs { fetched, errF := FetchMessages(c, jobUIDs) if errF != nil { log.Println("error while fetching ", jobUIDs, " ", err) continue } for _, msg := range fetched { mails = append(mails, msg) } } timeelapsed := time.Since(timestarted) msecpermessage := timeelapsed.Seconds() / float64(len(uids)) * 1000 messagespersec := float64(len(uids)) / timeelapsed.Seconds() log.Printf("Finished fetching %d messages in %.2fs (%.1fms per message; %.1f messages per second)\n", len(uids), timeelapsed.Seconds(), msecpermessage, messagespersec) err = WaitResp(c.Close(false)) return }
//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 }
//CopyEmails copies Emails having unique identifiers uids (NOT sequence numbers) of mailbox src //to mailbox dst by making bunches of jobsize. //If dst mbox doesnt exist then it will create it. //IF skipCerti is true then it will not check for the validity of the Certificate of the IMAP server, //good only if IMAP server is using self signed certi. //e.g. if jobsize =10 and total emails =100 then it will create 10 bunches of size 10 and then copy them. func CopyEmails(acct *IMAPAccount, src string, dst 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 Copying for user '%s' on IMAP server '%s:%d'", acct.Username, acct.Server.Host, acct.Server.Port) if jobSize <= 0 { jobSize = 10 } // Fetch UIDs. 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 } if dst == "" { err = errors.New("No Dst provided") return } //PRC Dest MBOX CHeck Start err = WaitResp(c.Select(dst, false)) if err != nil { //Doesnt Exist->Create err = WaitResp(c.Create(dst)) if err != nil { return } err = WaitResp(c.Select(dst, false)) } err = WaitResp(c.Close(false)) if err != nil { return } //PRC Dest MBOX Check End err = WaitResp(c.Select(src, true)) if err != nil { return } timestarted := time.Now() var jobs []*imap.SeqSet var jUids []uint32 for i := 0; i < len(uids); i++ { /*Logic 1.If we are at last index len(uids)-1 and still have not reached jobSize limit then append that to jobs (In other words if set size is smaller then jobsize) 2.if we go over index of size greater then jobsize then add all elemetns up to that index in to jobs 3.0 mod n returns 0 hence i!=0 is checked */ 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("Copying: %d UIDs total, %d jobs of size <= %d to %s\n", len(uids), len(jobs), jobSize, dst) for _, jobUIDs := range jobs { log.Println("Copying ", jobUIDs) err1 := WaitResp(c.UIDCopy(jobUIDs, dst)) if err1 != nil { log.Println(err) continue } } err = WaitResp(c.Close(false)) timeelapsed := time.Since(timestarted) msecpermessage := timeelapsed.Seconds() / float64(len(uids)) * 1000 messagespersec := float64(len(uids)) / timeelapsed.Seconds() log.Printf("Finished copying %d messages in %.2fs (%.1fms per message; %.1f messages per second)\n", len(uids), timeelapsed.Seconds(), msecpermessage, messagespersec) return }
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) } } }
func connectNet(user string) { netTimeout := time.Second * 30 cl, err := imap.DialTLS("imap.gmail.com", nil) if err != nil { log.Println(err) time.Sleep(netTimeout) return } defer cl.Logout(-1) log.Println("server says hello:", cl.Data[0].Info) cl.Data = nil log.Println("logging in") if cl.State() == imap.Login { _, err = cl.Login(user+"@gmail.com", "PASSHERE") if err != nil { log.Println(err) time.Sleep(netTimeout) return } } log.Println("logged in") log.Println("selecting INBOX") _, err = cl.Select("INBOX", false) if err != nil { log.Println(err) time.Sleep(netTimeout) return } log.Println("selected INBOX") set, _ := imap.NewSeqSet("") searchLoop: for { var successCounter int conTimeout := 5 log.Println("searching INBOX") cmd, err := imap.Wait(cl.Search("SUBJECT \"Confirm your email\"")) if err != nil { log.Println(err) break searchLoop } searchResults := cmd.Data[0].SearchResults() if searchResults == nil { log.Println("no email[s] found") time.Sleep(time.Second * 5) break searchLoop } else { log.Println("found", len(searchResults), "emails to spoof, results:", searchResults) set.AddNum(searchResults...) } var rsp *imap.Response link := regexp.MustCompile(`https:=\r\n\/\/invites.oneplus.net\/confirm\/[0-9A-Z]*.`) var UIDCounter int log.Println("beginning spoof confirmation loop") cmd, err = cl.Fetch(set, "RFC822") if err != nil { log.Println(err) break searchLoop } setDone, _ := imap.NewSeqSet("") getMailLoop: for cmd.InProgress() { cl.Recv(-1) for _, rsp = range cmd.Data { message := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822"]) if msg, err := mail.ReadMessage(bytes.NewReader(message)); msg != nil { log.Println("current conTimeout", conTimeout) body, err := ioutil.ReadAll(msg.Body) if err != nil { log.Println(err) break searchLoop } linkRawM := link.FindSubmatch(body) var linkRaw []byte if len(linkRawM) > 0 { linkRaw = linkRawM[0] } else { log.Println("found nolink mail") continue getMailLoop } log.Println(string(linkRaw)) url, err := url.Parse(string(linkRaw[:6]) + string(linkRaw[9:])) if err != nil { log.Println(err) break searchLoop } log.Println(url) req := confirmURL.ReplaceAll(reqTemplate, []byte(url.Path)[:len(url.Path)-1]) for { log.Println("attempting to spoof confirmation for", searchResults[UIDCounter]) c, err := tls.Dial("tcp", url.Host+":443", nil) if err != nil { log.Println(err) break searchLoop } _, err = c.Write(req) if err != nil { log.Println(err) break searchLoop } resp, err := http.ReadResponse(bufio.NewReader(c), nil) if err != nil { log.Println(err) break searchLoop } if resp.StatusCode == 302 { redirectReg := regexp.MustCompile(`https:\/\/oneplus\.net\/invites\?kid=[0-9A-Z]*`) redirectURL, err := resp.Location() if err != nil { log.Println(err) break searchLoop } log.Println(resp.Location()) if redirectReg.MatchString(redirectURL.String()) { log.Println("successfully spoofed confirmation for", searchResults[UIDCounter]) setDone.AddNum(searchResults[UIDCounter]) UIDCounter++ if successCounter == 10 { conTimeout-- successCounter = 0 } break } else { log.Println("server trying to migitate spoofing") conTimeout++ successCounter = 0 } } else { log.Println("gg rip hamsters") conTimeout++ successCounter = 0 } time.Sleep(time.Second * time.Duration(conTimeout)) } } else { log.Println(err) } } time.Sleep(time.Second * time.Duration(conTimeout)) cmd.Data = nil } log.Println("deleting mail", setDone) _, err = imap.Wait(cl.Store(setDone, "+FLAGS", "\\DELETED")) if err != nil { log.Println(err) break searchLoop } _, err = imap.Wait(cl.Expunge(nil)) if err != nil { log.Println(err) break searchLoop } } }
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)) }
// gets all the messages on the server since the last message in the list func (m *Mailbox) Update() (newMail []*Email, err error) { c, err := m.server.Connect() if err != nil { return nil, err } // sync imap command to select the mailbox for actions c.Select(m.Name, true) lastHad := m.latestMessage // retrieve items wanted := fmt.Sprintf("%d:*", lastHad) set, err := imap.NewSeqSet(wanted) if err != nil { return nil, err } cmd, err := c.UIDFetch(set, "RFC822.HEADER UID") if err != nil { return nil, err } // result newMail = make([]*Email, 0, 5) for cmd.InProgress() { // Wait for the next response (no timeout) c.Recv(-1) // Process command data // retrieve message UID // construct local Message structure from given header // store message in map // append UID to newMessages list for _, rsp := range cmd.Data { info := rsp.MessageInfo() if info.Attrs["UID"] != nil { // construct message header := imap.AsBytes(info.Attrs["RFC822.HEADER"]) // TODO: catch this error if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil { // we could read the message and retrieve the UID // so this is valid to push into our storage system m.latestMessage = info.UID my_msg := &MessageNode{ Header: msg.Header, ContentType: msg.Header.Get(ContentType), } email := &Email{ server: m.server, mailbox: m, UID: info.UID, Message: my_msg, } // store newMail = append(newMail, email) m.Mail[info.UID] = email } else { fmt.Printf("mail.ReadMessage failed on UID %d\n", info.UID) } } else { fmt.Printf("Message %v had no UID. Skipped.\n", info) } } // clear data cmd.Data = nil } return newMail, nil }
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 main() { // Source: https://godoc.org/code.google.com/p/go-imap/go1/imap#example-Client // Note: most of error handling code is omitted for brevity // // Connect to the server c, _ = imap.DialTLS(IMAP_SERVER, nil) // 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(USERNAME, PASSWORD) } // 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-19, c.Mailbox.Messages) } else { set.Add("1:*") } cmd, _ = imap.Wait(c.Fetch(set, HEADER_PART_NAME)) messages := make([]*imap.MessageInfo, 0, 0) for _, rsp = range cmd.Data { // May not be necessary to check for nil here. if msg := rsp.MessageInfo(); msg != nil { messages = append(messages, msg) } } listMessages(messages) // // 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[HEADER_PART_NAME]) // 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) // } // } // render() }
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 }