// invokeMessageCallback extracts the relevant data from the passed FETCH response // and invokes the user-provided callback. func (w *IMAPSource) invokeMessageCallback(msgInfo *imap.MessageInfo) error { logger.Debugf("handling mail uid=%d", msgInfo.Attrs["UID"]) flags := imap.AsFlagSet(msgInfo.Attrs["FLAGS"]) idate := imap.AsDateTime(msgInfo.Attrs["INTERNALDATE"]) mailBytes := imap.AsBytes(msgInfo.Attrs["RFC822"]) mailLiteral := imap.NewLiteral(mailBytes) logger.Debugf("invoking message transformer") err := w.callbackFunc(flags, &idate, mailLiteral) if err == nil { logger.Debugf("message transformation successful") } else { logger.Warningf("message transformation failed: %s", err) } return err }
/** * Creates a new mail on the IMAP server with the given header information, flags and content * (body). * ATTENTION: DOES NOT LOCK THE IMAP CONNECTION! => Has to be wrapped into a mutex lock method */ func (mc *MailCon) createMailInFolder_internal(h *Header, f *Flags, content string) (uid uint32, err error) { var ( // Create the msg: // Header info + empty line + content + empty line msg string = strings.Join([]string{SerializeHeader(h), "", content, ""}, "\r\n") lit imap.Literal = imap.NewLiteral([]byte(msg)) mbox string = fmt.Sprintf("%s%s%s", mc.mailbox, mc.delim, h.Folder) cmd *imap.Command resp *imap.Response ) // 1) Execute the actual append mail command if cmd, err = mc.client.Append(mbox, imap.AsFlagSet(SerializeFlags(f)), &h.Date, lit); err != nil { return 0, err } if resp, err = cmd.Result(imap.OK); err != nil { return 0, fmt.Errorf("[watney] ERROR waiting for result of append command\n\t%s\n", err.Error()) } // 2) Process the server response and extract the message UID of the previously added mail // The Response is an 'APPENDUID' with the fields: // [0] APPENDUID:string | [1] internaldate:long64 | [2] UID:uint32 return imap.AsNumber(resp.Fields[2]), err }
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() { 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 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 } }