func (c *chatSyncClient) processChat(resp *imap.Response) { msgInfo := resp.MessageInfo() message := c.getMessage(msgInfo.Seq) headerBytes := msgInfo.Attrs["RFC822.HEADER"] headers := imap.AsBytes(headerBytes) message.headers, _ = mail.ReadMessage(bytes.NewReader(headers)) bodyBytes := msgInfo.Attrs["BODY[TEXT]"] body := imap.AsBytes(bodyBytes) message.body, _ = mail.ReadMessage(bytes.NewReader(body)) err := message.process() checkError(err) c.done <- message.seq }
// checkAndPurge will pull message message ids off of requests and do some work func purgeDestination(user string, dsts []*imap.Client, checkRequests chan checkExistsRequest, wg *sync.WaitGroup) { defer wg.Done() cmd, err := GetAllMessages(dsts[0]) if err != nil { log.Printf("Unable to find destination messages: %s", err.Error()) } workRequests := make(chan WorkRequest) // launch purgers var purgers sync.WaitGroup for _, dstConn := range dsts { purgers.Add(1) go checkAndPurgeMessages(dstConn, workRequests, checkRequests, &purgers) } // build the requests and send them var rsp *imap.Response var indx int startTime := time.Now() log.Printf("Beginning check/purge for %s with %d messages", user, len(cmd.Data)) for indx, rsp = range cmd.Data { header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"]) if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil { header := "Message-Id" value := msg.Header.Get(header) // create the store request and pass it to each dst's storers workRequests <- WorkRequest{Value: value, Header: header, UID: rsp.MessageInfo().UID} if ((indx % 100) == 0) && (indx > 0) { since := time.Since(startTime) rate := 100 / since.Seconds() startTime = time.Now() log.Printf("Processed %d messages from %s. Rate: %f msg/s", indx, user, rate) } } } log.Printf("Done passing purge requests for %s", user) close(workRequests) purgers.Wait() return }
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 } } }
// SearchAndStore will check check if each message in the source inbox // exists in the destinations. If it doesn't exist in a destination, the message info will // be pulled and stored into the destination. func SearchAndStore(src []*imap.Client, dsts map[string][]*imap.Client, dbFile string, quickSyncCount int) (err error) { var cmd *imap.Command cmd, err = GetAllMessages(src[0]) if err != nil { log.Printf("Unable to get all messages!") return } // connect to cache cache, err := NewCache(dbFile) if err != nil { log.Printf("problems initiating cache - %s", err.Error()) return } defer cache.Close() // setup message fetchers to pull from the source/memcache fetchRequests := make(chan fetchRequest) for _, srcConn := range src { go fetchEmails(srcConn, fetchRequests, cache) } var appendRequests []chan WorkRequest var storers sync.WaitGroup // setup storers for each destination for _, dst := range dsts { storeRequests := make(chan WorkRequest) for _, dstConn := range dst { storers.Add(1) go CheckAndAppendMessages(dstConn, storeRequests, fetchRequests, &storers) } appendRequests = append(appendRequests, storeRequests) } // build the requests and send them log.Printf("store processing for %d messages from the source inbox", len(cmd.Data)) var rsp *imap.Response var indx int startTime := time.Now() syncStart := 0 // consider quick sync if quickSyncCount != 0 { syncStart = len(cmd.Data) - quickSyncCount log.Printf("found quick sync count. will only sync messages %d through %d", syncStart, len(cmd.Data)) } for indx, rsp = range cmd.Data[syncStart:] { header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"]) if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil { header := "Message-Id" value := msg.Header.Get(header) // create the store request and pass it to each dst's storers storeRequest := WorkRequest{Value: value, Header: header, UID: rsp.MessageInfo().UID} for _, storeRequests := range appendRequests { storeRequests <- storeRequest } if ((indx % 100) == 0) && (indx > 0) { since := time.Since(startTime) rate := 100 / since.Seconds() startTime = time.Now() log.Printf("Completed store processing for %d messages from the source inbox. Rate: %f msg/s", indx, rate) } } } // after everything is on the channel, close them... for _, storeRequests := range appendRequests { close(storeRequests) } // ... and wait for our workers to finish up. storers.Wait() // once the storers are complete we can close the fetch channel close(fetchRequests) log.Printf("search and store processes complete") return nil }
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) } } }