// 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 }
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 }
// 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 }
// 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 }
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 } } }
// 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 } } }
func readMessage(message *imap.MessageInfo) { set := new(imap.SeqSet) set.AddNum(message.Seq) cmd, err := imap.Wait(c.Fetch(set, BODY_PART_NAME)) panicMaybe(err) reader, err := messageReader(cmd.Data[0].MessageInfo()) panicMaybe(err) scanner := bufio.NewScanner(reader) var lines []string for scanner.Scan() { lines = append(lines, scanner.Text()) } messageBodyStr := strings.Join(lines[:min(len(lines), ui.TermHeight()-2)], "\n") if len(messageBodyStr) <= 0 { LOG.Printf("Message body was empty or could not be retrieved: +%v\n", err) return } msgBox := ui.NewPar(messageBodyStr) msgBox.Border.Label = "Reading Message" msgBox.Height = ui.TermHeight() msgBox.Width = ui.TermWidth() msgBox.Y = 0 ui.Render(msgBox) topLineIndex := 0 redraw := make(chan bool) for { select { case e := <-ui.EventCh(): switch e.Key { case ui.KeyArrowDown: topLineIndex = max(0, min( len(lines)-msgBox.Height/2, topLineIndex+1)) go func() { redraw <- true }() case ui.KeyArrowUp: topLineIndex = max(0, topLineIndex-1) go func() { redraw <- true }() case ui.KeyEsc: // back to "list messages" return } case <-redraw: messageBodyStr = strings.Join(lines[topLineIndex+1:], "\n") msgBox.Text = messageBodyStr ui.Render(msgBox) } } }
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 }
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 }
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 (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 }
func (i *ImapSession) CreateFolder(folder string) error { c := i.client mbox := folder if _, err := imap.Wait(c.Create(mbox)); err != nil { if rsp, ok := err.(imap.ResponseError); ok && rsp.Status == imap.NO { return nil } else { return err } } return nil }
// newIMAPClient will initiate a new IMAP connection with the given creds. func newIMAPClient(host, username, password, mailbox string) (*imap.Client, error) { client, err := imap.DialTLS(host, new(tls.Config)) if err != nil { return client, err } _, err = client.Login(username, password) if err != nil { return client, err } _, err = imap.Wait(client.Select(mailbox, false)) if err != nil { return client, err } return client, nil }
func GetConnection(info InboxInfo, readOnly bool) (*imap.Client, error) { conn, err := imap.DialTLS(info.Host, new(tls.Config)) if err != nil { return nil, err } _, err = conn.Login(info.User, info.Pw) if err != nil { return nil, err } _, err = imap.Wait(conn.Select("INBOX", readOnly)) if err != nil { return nil, err } return conn, nil }
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 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 }
// 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 }
// geet all the top-level mailboxes in the server, and return them func (s *Server) GetMailboxes() (boxes []*Mailbox, err error) { c, err := s.Connect() if err != nil { return } // fetch data synchronously cmd, err := imap.Wait(c.List("", "%")) if err != nil { return } boxes = make([]*Mailbox, len(cmd.Data)) for i, rsp := range cmd.Data { info := rsp.MailboxInfo() mbox := NewMailbox(info.Name, s) boxes[i] = mbox s.Mailboxes[mbox.Name] = mbox } return boxes, nil }
//= 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 }
// messages are usually created with just header information // this method downloads the actual body of the message from the server, // optionally marking the message as '\Seen', in IMAP terms. func (m *Email) Body(setRead bool) (body []byte, err error) { // cache if m.bodyData != nil { return m.bodyData, nil } // what will our FETCH request? var requestType string if setRead { requestType = "BODY[TEXT]" } else { requestType = "BODY.PEEK[TEXT]" } cmd, err := m.RetrieveRaw(requestType) cmd, err = imap.Wait(cmd, err) if err != nil { return } info := cmd.Data[0].MessageInfo() m.bodyData = imap.AsBytes(info.Attrs["BODY[TEXT]"]) return m.bodyData, nil }
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() { // 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 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 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)) }
func (c CustomClient) XYZZY() (cmd *imap.Command, err error) { if !c.Caps["XYZZY"] { return nil, imap.NotAvailableError("XYZZY") } return imap.Wait(c.Send("XYZZY")) }
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() { flag.Parse() email, password := getCredentials() quit := make(chan os.Signal) signal.Notify(quit, os.Interrupt, os.Kill) go func() { <-quit os.Exit(0) }() connect := func(server string) (c *imap.Client, err error) { c, err = imap.DialTLS(server, &tls.Config{}) if err != nil { return } _, err = c.Auth(imap.PlainAuth(email, password, "")) if err != nil { return } log.Println("Successfully authed") cmd, err := c.Select(*mailbox, true) if err != nil { log.Println("Error selecting mailbox: ", err) return } _, err = cmd.Result(imap.OK) if err != nil { return } log.Println("Successfully selected ", *mailbox) _, err = c.Idle() if err != nil { return } log.Println("Starting idle...") c.Data = nil return } loop: for { if err := cmd(); err != nil { log.Printf("Error running sync on new loop: %s\n", err) continue } c, err := connect("imap.gmail.com") if err != nil { continue } wait := true for wait { err = c.Recv(15 * time.Minute) switch err { case nil: fallthrough case io.EOF: // We received content from server -- sync mails wait = false case imap.ErrTimeout: // after the timeout, wakeup the connection if _, err := c.IdleTerm(); err != nil { log.Println("Error finishing idle:: ", err) continue loop } if _, err := imap.Wait(c.Noop()); err != nil { log.Println("Error nooping: ", err) continue loop } log.Println("Keeping it alive !") if _, err := c.Idle(); err != nil { log.Println("Error re-idling: ", err) continue loop } default: log.Println("Error while receiving content: ", err) continue loop } } for _, rsp := range c.Data { if rsp.Label == "EXISTS" { log.Println("New message, running sync...") if err := cmd(); err != nil { log.Printf("Error running sync: %s\n", err) } log.Println("Ran sync") } } c.Data = nil } }
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 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 }