func TestImap(t *testing.T) { var user, pw string if mock { testDial = fakeDial user = "******" pw = "password" } else { acct := google.Acct("*****@*****.**") user = acct.Email pw = acct.Password } c, err := NewClient(TLS, "imap.gmail.com", user, pw, "") if err != nil { t.Fatal(err) } inbox := c.Inbox() msgs := inbox.Msgs() for _, m := range msgs { if m.UID == 611764547<<32|57046 { // c.io.lock() // c.cmd(c.boxByName[`[Gmail]/All Mail`], `UID SEARCH X-GM-RAW "label:[email protected] in:inbox in:unread -in:muted"`) // c.cmd(c.inbox, `UID SEARCH X-GM-RAW "label:[email protected] in:inbox in:unread -in:muted"`) // c.cmd(c.boxByName[`To Read`], `UID SEARCH X-GM-RAW "label:[email protected] in:inbox in:unread -in:muted"`) // c.cmd(c.boxByName[`[Gmail]/All Mail`], `UID SEARCH X-GM-RAW "label:[email protected] in:inbox in:unread -in:muted"`) // c.fetch(m.Root.Child[0], "") // c.io.unlock() fmt.Println("--") fmt.Println("From:", m.Hdr.From) fmt.Println("To:", m.Hdr.To) fmt.Println("Subject:", m.Hdr.Subject) fmt.Println("M-Date:", m.Date) fmt.Println("Date:", m.Hdr.Date) fmt.Println() fmt.Println(string(m.Root.Child[0].Text())) fmt.Println("--") } } c.Close() }
func main() { flag.BoolVar(&imap.Debug, "imapdebug", false, "imap debugging trace") flag.Parse() acct = google.Acct(*acctName) if args := flag.Args(); len(args) > 0 { for i := range args { args[i] = "-to=" + args[i] } cmd := exec.Command("gmailsend", append([]string{"-a", acct.Email, "-i"}, args...)...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { fmt.Fprintf(os.Stderr, "!%s\n", err) os.Exit(1) } return } c, err := imap.NewClient(imap.TLS, "imap.gmail.com", acct.Email, acct.Password, "") if err != nil { log.Fatal(err) } isGmail = c.IsGmail() threaded = isGmail if *search != "" { b, err := c.GmailSearch(*search) if err != nil { log.Fatal(err) } inbox = b } else { inbox = c.Inbox() if err := inbox.Check(); err != nil { log.Fatal(err) } } msgs = inbox.Msgs() maxfrom = 12 for i, m := range msgs { msgNum[m] = i if n := len(from(m.Hdr)); n > maxfrom { maxfrom = n } } if maxfrom > 20 { maxfrom = 20 } subjlen = 80 - maxfrom rethread() interrupts := make(chan os.Signal, 1) signal.Notify(interrupts, syscall.SIGINT) go func() { for _ = range interrupts { fmt.Fprintf(os.Stderr, "!interrupt\n") interrupted = true } }() for { if dot != nil { fmt.Fprintf(bout, "%d", msgNum[dot.Msg]+1) if dot != &dot.Msg.Root { fmt.Fprintf(bout, ".%s", dot.ID) } } fmt.Fprintf(bout, ": ") bout.Flush() line, err := bin.ReadString('\n') if err != nil { break } cmd, err := parsecmd(line) if err != nil { fmt.Fprintf(bout, "!%s\n", err) continue } if cmd.Targ != nil || cmd.Targs == nil && cmd.A2 == 0 { x := cmd.F(cmd, cmd.Targ) if x != nil { dot = x } } else { targs := cmd.Targs if targs == nil { delta := +1 if cmd.A1 > cmd.A2 { delta = -1 } for i := cmd.A1; i <= cmd.A2; i += delta { if i < 1 || i > len(msgs) { continue } targs = append(targs, msgs[i-1]) } } if cmd.Thread { if !isGmail { fmt.Fprintf(bout, "!need gmail for threaded command\n") continue } byThread := make(map[uint64][]*imap.Msg) for _, m := range msgs { t := m.GmailThread byThread[t] = append(byThread[t], m) } for _, m := range targs { t := m.GmailThread if byThread[t] != nil { if cmd.TF != nil { if x := cmd.TF(cmd, byThread[t]); x != nil { dot = x } } else { for _, mm := range byThread[t] { x := cmd.F(cmd, &mm.Root) if x != nil { dot = x } } } } delete(byThread, t) } continue } for _, m := range targs { if cmd.Delete { dcmd(cmd, &m.Root) if cmd.Name == "p" { // dp is a special case: it advances to the next message before the p. next := nextMsg(m) if next == nil { fmt.Fprintf(bout, "!address\n") dot = &m.Root break } m = next } } x := cmd.F(cmd, &m.Root) if x != nil { dot = x } // TODO: Break loop on interrupt. } } } qcmd(nil, nil) }
func main() { flag.Usage = usage flag.Parse() acct = google.Acct(*acctName) aw, err := acme.New() if err != nil { log.Fatal(err) } aw.Name("Chat/" + acct.Nick + "/") client, err = xmpp.NewClient("talk.google.com:443", acct.Email, acct.Password) if err != nil { log.Fatal(err) } w := &Window{Win: aw, typ: "main", name: "Chat/" + acct.Nick + "/"} data, err := ioutil.ReadFile(google.Dir() + "/chat." + acct.Nick) if err != nil { log.Fatal(err) } if err == nil { w.Write("body", data) } mainWin = w active[w.name] = w go w.readAcme() client.Roster() setStatus(status) go w.readChat() lastActivity = time.Now() tick := time.Tick(0.5e9) Loop: for len(active) > 0 { select { case w := <-acmeChan: if w == nil { // Sync with reader. continue } if w.err != nil { if active[w.name] == nil { continue } log.Fatal(w.err) } if *acmeDebug { fmt.Fprintf(os.Stderr, "%s %c%c %d,%d %q\n", w.name, w.C1, w.C2, w.Q0, w.Q1, w.Text) } if w.C1 == 'M' || w.C1 == 'K' { lastActivity = time.Now() if status != xmpp.Available { setStatus(xmpp.Available) } } if (w.C2 == 'x' || w.C2 == 'X') && string(w.Text) == "Del" { // TODO: Hangup connection for w.typ == "acct"? delete(active, w.name) w.Del(true) continue Loop } switch w.typ { case "main": switch w.C2 { case 'L': // Button 3 in body: load chat window for contact. w.expand() fallthrough case 'l': // Button 3 in tag arg := string(w.Text) showContact(arg) continue Loop } case "chat": if w.C1 == 'F' && w.C2 == 'I' { continue Loop } if w.C1 != 'M' && w.C1 != 'K' { break } if w.blinky { w.blinky = false w.Fprintf("ctl", "dirty\n") } switch w.C2 { case 'X', 'x': if string(w.Text) == "Ack" { w.Fprintf("ctl", "clean\n") } case 'I': w.sendMsg() continue Loop } } w.WriteEvent(w.Event) case msg := <-msgChan: w := msg.w if msg.err != nil { w.Fprintf("body", "ERROR: %s\n", msg.err) continue Loop } you := msg.Remote if i := strings.Index(you, "/"); i >= 0 { you = you[:i] } switch msg.Type { case "chat": w := showContact(you) text := strings.TrimSpace(msg.Text) if text == "" { // Probably a composing notification. continue } w.message("> %s\n", text) w.blinky = true w.dirty = true case "presence": pr := msg.Presence pr, new := savePresence(pr, you) if !new { continue } w := lookContact(you) if w != nil { w.status(pr) } mainStatus(pr, you) } case t := <-tick: switch status { case xmpp.Available: if t.Sub(lastActivity) > awayTime { setStatus(xmpp.Away) } case xmpp.Away: if t.Sub(lastActivity) > extendedAwayTime { setStatus(xmpp.ExtendedAway) } } for _, w := range active { if w.blinky { w.dirty = !w.dirty if w.dirty { w.Fprintf("ctl", "dirty\n") } else { w.Fprintf("ctl", "clean\n") } } } } } }