Example #1
0
// 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
}
Example #2
0
/**
 * 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
}
Example #3
0
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)
}
Example #4
0
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))
}
Example #5
0
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
	}
}