func getThreads(c *imap.Client) ([]Thread, error) { set, err := imap.NewSeqSet("1:*") cmd, err := imap.Wait(c.Fetch(set, "X-GM-THRID", "UID")) if err != nil { fmt.Println(err) return nil, ErrBadConnection } var result []Thread seen := make(map[string]int) for _, rsp := range cmd.Data { thrid := imap.AsString(rsp.MessageInfo().Attrs["X-GM-THRID"]) uid := imap.AsNumber(rsp.MessageInfo().Attrs["UID"]) if i, ok := seen[thrid]; ok { result[i] = append(result[i], uid) } else { result = append(result, Thread{uid}) seen[thrid] = len(result) - 1 } } return result, nil }
/** * This method moves the mail associated with the given 'UID', from the folder where it currently * resides, into the "toFolder" folder and sets its "Deleted" flag. * After this operation, the following post condition holds, if a mail with the given UID existed * in the original folder: * - The mail in the original folder has its "Deleted" flag set * - The folder 'newFolder' now contains a new mail with the Header and Content of the original * mail (but with a new UID) * * ATTENTION: * The original mail is NOT deleted from the folder where it resided (only its deleted flag is set). * The deletion operation will happen when the IMAP connection is closed, or the EXPUNGE operation * is called. * * @param uid The UID of the mail to be moved * @param folder The folder in which the current mail resides (its source location) * @param toFolder The folder the mail should be moved to (the target folder) * @return Returns the UID of the newly created mail in the target folder or an error, if something * went wrong. */ func (mc *MailCon) moveMail_internal(uid, folder, toFolder string) (uint32, error) { var targetMbox string = mc.mailbox // 1) First check if we need to select a specific folder in the mailbox or if it is root if err := mc.selectFolder(folder, true); err != nil { return 0, err } // 2) Assign necessary variables and initiate IMAP Copy process set, _ := imap.NewSeqSet(uid) if len(toFolder) > 0 && toFolder != "/" { targetMbox = fmt.Sprintf("%s%s%s", mc.mailbox, mc.delim, toFolder) } cmd, err := mc.client.UIDCopy(set, targetMbox) var resp *imap.Response if resp, err = cmd.Result(imap.OK); err != nil { return 0, fmt.Errorf("[watney] ERROR waiting for result of copy command\n\t%s\n", err.Error()) } // 3) Execute the copy process to copy the mail internally to the new folder if _, err := mc.waitFor(mc.client.UIDStore(set, "+FLAGS", SerializeFlags(&Flags{Deleted: true}))); err != nil { return 0, fmt.Errorf("[watney] ERROR waiting for result of update flags command\n\t%s\n", err.Error()) } // 4) Check if the copy worked, and if so, return the new UID and no error // The Response is an 'COPYUID' with the fields: // [0] COPYUID:string | [1] internaldate:long64 | [2] Orig-UID:uint32 | [3] New-UID:uint32 // The Orig-UID resambles the given UID for the original mail // The New-UID is the UID of the new mail stored in the 'toFolder' if len(resp.Fields) == 4 { return imap.AsNumber(resp.Fields[3]), nil } else { return 0, errors.New("[watney] WARNING: Copy completed without doing anyting\n") } }
// fetchIDs downloads the messages with the given IDs and invokes the callback for // each message. func (w *IMAPSource) fetchIDs(ids []uint32) error { set, _ := imap.NewSeqSet("") set.AddNum(ids...) w.deletionSet, _ = imap.NewSeqSet("") cmd, err := w.conn.Fetch(set, "RFC822", "UID", "FLAGS", "INTERNALDATE") if err != nil { logger.Errorf("FETCH failed: %s", err) return err } for cmd.InProgress() { w.conn.Recv(-1) for _, rsp := range cmd.Data { _ = w.handleMessage(rsp) } cmd.Data = nil // Consume other server data for _ = range w.conn.Data { } w.conn.Data = nil } if rsp, err := cmd.Result(imap.OK); err != nil { if err == imap.ErrAborted { logger.Errorf("FETCH command aborted") } else { logger.Errorf("FETCH error: %s", rsp.Info) } } else { logger.Debugf("FETCH completed without errors") } if !w.deletePlainCopies { return nil } if w.deletionSet.Empty() { return nil } logger.Debugf("marking mails as deleted") _, err = imap.Wait(w.conn.UIDStore(w.deletionSet, "+FLAGS", "(\\Deleted)")) if err != nil { logger.Errorf("failed to mark set=%v for deletion: %s", w.deletionSet.String(), err) } return err }
/** * Loads the header and the content of the mail for the given UIDs. */ func (mc *MailCon) LoadNMailsFromFolderWithSeqNbrs(folder string, seqNbrs []uint32) ([]Mail, error) { mc.mutex.Lock() defer mc.mutex.Unlock() // TODO: Check if UIDs are below 1 and react accordingly var seqNbrStrings []string = make([]string, len(seqNbrs)) for index, seqNbr := range seqNbrs { // FIXME: This is a potential unsafe cast if the sequence number would be bigger than // 2^31-1 seqNbrStrings[index] = strconv.Itoa(int(seqNbr)) } set, _ := imap.NewSeqSet(strings.Join(seqNbrStrings, ",")) return mc.loadMails(set, folder, true, mc.client.Fetch) }
/** @param folder The folder to retrieve mails from @param n > 0 The number of mails to retrieve from the folder in the mailbox n <= 0 All mails that are saved within the folder @param withContent True - Also loads the content of all mails False - Only loads the headers of all mails */ func (mc *MailCon) LoadNMailsFromFolder(folder string, n int, withContent bool) ([]Mail, error) { mc.mutex.Lock() defer mc.mutex.Unlock() // 1) Define the number of mails that should be loaded var nbrMailsExp string if n > 0 { nbrMailsExp = fmt.Sprintf("1:%d", n) } else { nbrMailsExp = "1:*" } set, _ := imap.NewSeqSet(nbrMailsExp) return mc.loadMails(set, folder, withContent, mc.client.Fetch) }
/** * * ATTENTION: * If the mail for the given UID can't be found in the given folder, no flags will be changed. * * @param folder The folder, this mail resides in, e.g., "/", "Sent", ... * @param uid The unique server ID of this message * @param add True - Sets the flag(s) as activated * False - Removes the flag(s) (sets them as deactivated) */ func (mc *MailCon) UpdateMailFlags(folder, uid string, f *Flags, add bool) error { mc.mutex.Lock() defer mc.mutex.Unlock() var task string // 1) Select the folder in which the mail resides whose flags should be updated if err := mc.selectFolder(folder, false); err != nil { return err } // 2) Prepare parameters for update request and perform the request if add { task = "+" } else { task = "-" } set, _ := imap.NewSeqSet(uid) _, err := mc.waitFor(mc.client.UIDStore(set, strings.Replace("*FLAGS", "*", task, 1), SerializeFlags(f))) return err }
func notifyNewEmail(c *imap.Client, mId uint32) { set, _ := imap.NewSeqSet("") set.AddNum(mId) cmd := ReportOK(c.Fetch(set, "FLAGS", "RFC822.HEADER")) for _, rsp := range cmd.Data { header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"]) if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil { subj := msg.Header.Get("Subject") from := msg.Header.Get("From") formattedFrom := strings.Split(from, " ")[0] exec.Command( "terminal-notifier", "-message", subj, "-title", "Mail From: "+formattedFrom+"", "-sender", "com.apple.Mail", ).Output() } } }
/** * Loads the header and the content of the mail for the given UID. */ func (mc *MailCon) LoadMailFromFolderWithUID(folder string, uid uint32) (Mail, error) { mc.mutex.Lock() defer mc.mutex.Unlock() if uid < 1 { return Mail{}, errors.New(fmt.Sprintf("Couldn't retrieve mail, because mail UID (%d) needs to "+ "be greater than 0", uid)) } var ( mails MailSlice err error ) set, _ := imap.NewSeqSet(fmt.Sprintf("%d", uid)) if mails, err = mc.loadMails(set, folder, true, mc.client.UIDFetch); err != nil { return Mail{}, errors.New(fmt.Sprintf("No mail could be retrieved for the given ID: %d; due to "+ "the error:\n%s\n", uid, err.Error())) } if len(mails) == 0 { return Mail{}, errors.New(fmt.Sprintf("No mail found for the given ID: %d\n", uid)) } return mails[0], err }
//use imap to delete a mail func (email *Email) DeleteEmail(w rest.ResponseWriter, r *rest.Request) { log.Printf("delete email...") addr := r.FormValue("imapAddr") //port := r.FormValue("smtpPort") user := r.FormValue("user") pwd := r.FormValue("pwd") id := r.FormValue("id") //check params, return error //create imap client var ( c *imap.Client cmd *imap.Command rsp *imap.Response ) // Connect to the server c, _ = imap.Dial(addr) // 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) log.Printf("Server says hello:%s", 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(user, pwd) } // List all top-level mailboxes, wait for the command to finish cmd, _ = imap.Wait(c.List("", "%")) // Print mailbox information log.Printf("\nTop-level mailboxes:") for _, rsp = range cmd.Data { log.Printf("|--%s", rsp.MailboxInfo()) } // Check for new unilateral server data responses for _, rsp = range c.Data { log.Printf("Server data:%s", rsp) } c.Data = nil // Open a mailbox (synchronous command - no need for imap.Wait) c.Select("INBOX", true) log.Printf("\nMailbox status:%s\n", c.Mailbox) if c.Mailbox == nil { resp := EmailJsonResponse{Success: true} w.WriteJson(&resp) return } //use Expunge to delete a mail set, _ := imap.NewSeqSet("") mid, _ := strconv.Atoi(id) set.AddNum(uint32(mid)) //delete mail cmd, err := c.Expunge(set) if err != nil { log.Printf("%v ", cmd) } else { log.Printf("delete mail ok") } }
func (emaill *Email) getEmailContentUseIMAP(w rest.ResponseWriter, r *rest.Request) { addr := r.FormValue("imapAddr") port := r.FormValue("imapPort") user := r.FormValue("user") pwd := r.FormValue("pwd") id := r.FormValue("id") address := addr + ":" + port log.Printf("get email content use imap %s\n", address) var ( c *imap.Client cmd *imap.Command rsp *imap.Response ) // Connect to the server c, err := imap.Dial(addr) if err != nil { log.Printf("dial %s error\n", address) return } // 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) log.Printf("Server says hello:%s", 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(user, pwd) } // List all top-level mailboxes, wait for the command to finish cmd, _ = imap.Wait(c.List("", "%")) // Print mailbox information log.Printf("\nTop-level mailboxes:") for _, rsp = range cmd.Data { log.Printf("|--%s", rsp.MailboxInfo()) } // Check for new unilateral server data responses for _, rsp = range c.Data { log.Printf("Server data:%s", rsp) } c.Data = nil // Open a mailbox (synchronous command - no need for imap.Wait) c.Select("INBOX", true) log.Printf("\nMailbox status:%s\n", c.Mailbox) if c.Mailbox == nil { resp := EmailJsonResponse{Success: true} w.WriteJson(&resp) return } // Fetch the headers of the 10 most recent messages set, _ := imap.NewSeqSet("") set.Add(id) // if c.Mailbox.Messages >= 10 { // set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages) //测试只取最新一封邮件 // } else { // set.Add("1:*") // } cmd, _ = c.Fetch(set, "RFC822.HEADER", "RFC822.TEXT") //指定要获取的内容 // Process responses while the command is running log.Printf("\nget mail [%s] messages:", id) 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 { subject := msg.Header.Get("Subject") log.Printf("|--%s", subject) realSubject := GetRealSubject(subject) log.Printf("in rest_email.go: get real subject") log.Printf(realSubject) senderAddr := msg.Header.Get("From") recverAddrList := msg.Header.Get("To") realSenderAddr := GetRealSubject(senderAddr) realRecverAddrList := GetRealSubject(recverAddrList) body := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.TEXT"]) //log.Printf("email body: %s", body) //realBody := GetRealBody(string(body)) headerAndBody := make([]byte, len(header)+len(body)) copy(headerAndBody, header) copy(headerAndBody[len(header):], body) msg, _ := mail.ReadMessage(bytes.NewReader(headerAndBody)) mime, _ := enmime.ParseMIMEBody(msg) realBody := mime.Text //如果原始内容为html,会去掉html元素标签 log.Printf("real body: %s", realBody) //获取MIMEPart所有节点内容 // log.Printf("root ======================") // root := mime.Root // if root != nil { // log.Printf(string(root.Content())) // log.Printf("child==========") // if child := root.FirstChild(); child != nil { // log.Printf(string(child.Content())) // } // } attachments := mime.Attachments log.Printf("attachments len=%d", len(attachments)) count := len(attachments) var attachmentList []Attachment = nil var data EmailContent if count > 0 { attachmentList = make([]Attachment, count) for i := 0; i < len(attachments); i++ { name := attachments[i].FileName() content := attachments[i].Content() //todo encode by base64 log.Printf("name===%s", name) attachmentList[i] = Attachment{Name: name, Body: string(content)} } } data = EmailContent{Subject: realSubject, SenderAddr: realSenderAddr, RecverAddrList: realRecverAddrList, Content: realBody, Attachments: attachmentList} resp := EmailJsonResponse{Success: true, Data: data} w.WriteJson(resp) } } cmd.Data = nil // Process unilateral server data for _, rsp = range c.Data { log.Printf("Server data:%s", rsp) } c.Data = nil } // Check command completion status if rsp, err := cmd.Result(imap.OK); err != nil { if err == imap.ErrAborted { log.Printf("Fetch command aborted\n") } else { log.Printf("Fetch error:%s\n", rsp.Info) } } }
// updateTray is called whenever a client detects that the number of unseen // messages *may* have changed. It will search the selected folder for unseen // messages, count them and store the result. Then it will use the notify // channel to let our main process update the status icon. func UpdateTray(c *imap.Client, notify chan bool, name string) { // Send > Search since Search adds CHARSET UTF-8 which might not be supported cmd, err := c.Send("SEARCH", "UNSEEN") if err != nil { fmt.Printf("%s failed to look for new messages\n", name) fmt.Println(" ", err) return } if _, ok := Unseen[name]; !ok { Unseen[name] = []uint32{} } unseenMessages := []uint32{} for cmd.InProgress() { // Wait for the next response (no timeout) err = c.Recv(-1) // Process command data for _, rsp := range cmd.Data { result := rsp.SearchResults() unseenMessages = append(unseenMessages, result...) } // Reset for next run cmd.Data = nil 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) } return } fmt.Printf("%d unseen\n", len(unseenMessages)) // Find messages that the user hasn't been notified of // TODO: Make this optional/configurable newUnseen, _ := imap.NewSeqSet("") numNewUnseen := 0 for _, uid := range unseenMessages { seen := false for _, olduid := range Unseen[name] { if olduid == uid { seen = true break } } if !seen { newUnseen.AddNum(uid) numNewUnseen++ } } // If we do have new unseen messages, fetch and display them if numNewUnseen > 0 { messages := make([]string, numNewUnseen) i := 0 // Fetch headers... cmd, _ = c.Fetch(newUnseen, "RFC822.HEADER") for cmd.InProgress() { c.Recv(-1) for _, rsp := range cmd.Data { header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"]) if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil { subject := msg.Header.Get("Subject") messages[i], err = new(mime.WordDecoder).DecodeHeader(subject) if err != nil { messages[i] = subject } i++ } } cmd.Data = nil c.Data = nil } // Print them in reverse order to get newest first notification := "" for ; i > 0; i-- { notification += "> " + messages[i-1] + "\n" } notification = strings.TrimRight(notification, "\n") fmt.Println(notification) // And send them with notify-send! title := fmt.Sprintf("%s has new mail (%d unseen)", name, len(unseenMessages)) sh := exec.Command("/usr/bin/notify-send", "-i", "notification-message-email", "-c", "email", title, notification) err := sh.Start() if err != nil { fmt.Println("Failed to notify user...") fmt.Println(err) } go func() { // collect exit code to avoid zombies sh.Wait() }() } Unseen[name] = unseenMessages // Let main process know something has changed notify <- true }
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 main() { token := flag.String("token", "", "The Telegram bot token") to := flag.String("to", "", "The mail recipient") from := flag.String("from", "", "The mail sender") server := flag.String("server", "", "The mail server") port := flag.Int("port", 587, "The mail server port") user := flag.String("user", "", "") pass := flag.String("pass", "", "") subject := flag.String("subject", "", "") flag.Parse() bot, err := telebot.NewBot(*token) if err != nil { return } // Fetching Mails and send as Telegram messages var ( c *imap.Client cmd *imap.Command rsp *imap.Response ) c, _ = imap.Dial(*server) defer c.Logout(30 * time.Second) c.Data = nil if c.Caps["STARTTLS"] { c.StartTLS(nil) } if c.State() == imap.Login { c.Login(*user, *pass) } cmd, _ = imap.Wait(c.List("", "%")) c.Data = nil c.Select("INBOX", true) set, _ := imap.NewSeqSet("") set.Add("1:*") cmd, _ = c.Fetch(set, "RFC822.HEADER") for cmd.InProgress() { c.Recv(-1) 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("FROM")) } } cmd.Data = nil c.Data = nil } 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) } } /* * Listen to Telegram messages and send as mail */ messages := make(chan telebot.Message) bot.Listen(messages, 1*time.Second) for message := range messages { m := gomail.NewMessage() m.SetHeader("From", *from) m.SetHeader("To", *to) m.SetHeader("Subject", *subject) m.SetBody("text/html", message.Text) d := gomail.NewPlainDialer(*server, *port, *user, *pass) d.TLSConfig = &tls.Config{InsecureSkipVerify: true} if err := d.DialAndSend(m); err != nil { panic(err) } } }
// Fetch email for the specified user and host. func Fetch(host, user, pass string) { c, err := imap.Dial(host) if err != nil { log.Print(err) return } defer c.Logout(30 * time.Second) log.Println("Server says hello:", c.Data[0].Info) c.Data = nil if c.Caps["STARTTLS"] { c.StartTLS(nil) } if c.State() == imap.Login { c.Login(user, pass) } cmd, err := imap.Wait(c.List("", "%")) if err != nil { log.Print(err) return } log.Println("\nTop-level mailboxes:") for _, rsp := range cmd.Data { log.Println("|--", rsp.MailboxInfo()) } for _, rsp := range c.Data { log.Println("Server data:", rsp) } c.Data = nil c.Select("INBOX", true) log.Print("\nMailbox status:\n", c.Mailbox) 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") log.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 { log.Println("|--", msg.Header.Get("Subject")) } } cmd.Data = nil // Process unilateral server data for _, rsp := range c.Data { log.Println("Server data:", rsp) } c.Data = nil } if rsp, err := cmd.Result(imap.OK); err != nil { if err == imap.ErrAborted { log.Println("Fetch command aborted") } else { log.Println("Fetch error:", rsp.Info) } } }
func transferMbox(c *cli.Context) { source := c.Args().Get(0) target := c.Args().Get(1) if source == "" || target == "" { log.Fatal("Bitte Quell- und Zielordner angeben, z.B.: mailporter transfer INBOX INBOX") } n := imapConnect(notes) defer n.Logout(30 * time.Second) _, err := n.Select(source, true) if err != nil { log.Fatal("Kein Zugriff auf %s/%s. Fehler: %s", notes, source, err.Error()) } e := imapConnect(exchange) defer e.Logout(30 * time.Second) fmt.Println("Ermittle zu übertragende Mails...") criteria := []string{"ALL"} if c.String("before") != "" { criteria = append(criteria, "BEFORE "+c.String("before")) } nc, err := imap.Wait(n.UIDSearch(strings.Join(criteria, " "))) var mails []uint32 for _, r := range nc.Data { mails = r.SearchResults() } reader := bufio.NewReader(os.Stdin) fmt.Printf("%d Mails sind zu übertragen. Fortfahren (j oder n)? ", len(mails)) cont, _ := reader.ReadString('\n') if strings.TrimSpace(cont) != "j" { return } fmt.Printf("Übertrage Mails.\n") bar := pb.StartNew(len(mails)) set, _ := imap.NewSeqSet("") for _, mid := range mails { set.AddNum(mid) } fetch, err := n.UIDFetch(set, "BODY.PEEK[]") if err != nil { log.Fatalf("Konnte Mails nicht laden: ", err) } flags := map[string]bool{ "\\Seen": true, } for fetch.InProgress() { n.Recv(-1) for _, r := range fetch.Data { i := r.MessageInfo() if i.Size >= maxSize { m, err := mail.ReadMessage(bytes.NewReader(imap.AsBytes(i.Attrs["BODY[]"]))) if err != nil { log.Fatal(err) } date, _ := m.Header.Date() datestring := date.Format(time.RFC822) fmt.Printf("WARNUNG: Mail '%s' (%s, von %s) ist zu groß für Exchange. Überspringe.\n", m.Header.Get("Subject"), datestring, m.Header.Get("From")) fetch.Data = nil n.Data = nil continue } _, err := imap.Wait(e.Append(target, flags, nil, imap.NewLiteral(imap.AsBytes(i.Attrs["BODY[]"])))) if err != nil { fmt.Printf("WARNUNG: Konnte Mail nicht auf Exchange speichern.\nFehler: %s\n", err.Error()) m, err := mail.ReadMessage(bytes.NewReader(imap.AsBytes(i.Attrs["BODY[]"]))) if err != nil { log.Fatal(err) } date, _ := m.Header.Date() datestring := date.Format(time.RFC822) fmt.Println("Von: ", m.Header.Get("From")) fmt.Println("Betreff: ", m.Header.Get("Subject")) fmt.Println("Datum: ", datestring) e.Logout(0) e = imapConnect(exchange) defer e.Logout(30 * time.Second) fetch.Data = nil n.Data = nil continue } bar.Increment() } fetch.Data = nil n.Data = 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) } } }