diff --git a/imap.go b/imap.go index e7e7710..869d457 100644 --- a/imap.go +++ b/imap.go @@ -1,6 +1,8 @@ package koushin import ( + "sort" + "github.com/emersion/go-imap" imapclient "github.com/emersion/go-imap/client" ) @@ -45,5 +47,51 @@ func listMailboxes(conn *imapclient.Client) ([]*imap.MailboxInfo, error) { return nil, err } + sort.Slice(mailboxes, func(i, j int) bool { + return mailboxes[i].Name < mailboxes[j].Name + }) return mailboxes, nil } + +func listMessages(conn *imapclient.Client, mboxName string) ([]*imap.Message, error) { + mbox := conn.Mailbox() + if mbox == nil || mbox.Name != mboxName { + var err error + mbox, err = conn.Select(mboxName, false) + if err != nil { + return nil, err + } + } + + n := uint32(10) + from := uint32(1) + to := mbox.Messages + if mbox.Messages > n { + from = mbox.Messages - n + } + seqSet := new(imap.SeqSet) + seqSet.AddRange(from, to) + + ch := make(chan *imap.Message, 10) + done := make(chan error, 1) + go func() { + done <- conn.Fetch(seqSet, []imap.FetchItem{imap.FetchEnvelope}, ch) + }() + + msgs := make([]*imap.Message, 0, n) + for msg := range ch { + msgs = append(msgs, msg) + } + + if err := <-done; err != nil { + return nil, err + } + + // Reverse list of messages + for i := len(msgs)/2-1; i >= 0; i-- { + opp := len(msgs)-1-i + msgs[i], msgs[opp] = msgs[opp], msgs[i] + } + + return msgs, nil +} diff --git a/public/index.html b/public/mailbox.html similarity index 60% rename from public/index.html rename to public/mailbox.html index 4a9566a..2f5cdb6 100644 --- a/public/index.html +++ b/public/mailbox.html @@ -9,4 +9,11 @@ {{end}} +

Messages:

+ + {{template "foot"}} diff --git a/server.go b/server.go index f573756..8245e08 100644 --- a/server.go +++ b/server.go @@ -88,7 +88,7 @@ func handleLogin(ectx echo.Context) error { } ctx.setToken(token) - return ctx.Redirect(http.StatusFound, "/") + return ctx.Redirect(http.StatusFound, "/mailbox/INBOX") } return ctx.Render(http.StatusOK, "login.html", nil) @@ -135,7 +135,7 @@ func New(imapURL string) *echo.Echo { e.Logger.Fatal("Failed to load templates:", err) } - e.GET("/", func(ectx echo.Context) error { + e.GET("/mailbox/:mbox", func(ectx echo.Context) error { ctx := ectx.(*context) mailboxes, err := listMailboxes(ctx.conn) @@ -143,8 +143,14 @@ func New(imapURL string) *echo.Echo { return err } - return ctx.Render(http.StatusOK, "index.html", map[string]interface{}{ + msgs, err := listMessages(ctx.conn, ctx.Param("mbox")) + if err != nil { + return err + } + + return ctx.Render(http.StatusOK, "mailbox.html", map[string]interface{}{ "Mailboxes": mailboxes, + "Messages": msgs, }) })