diff --git a/go.mod b/go.mod index 9cd983b..5b738dc 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.13 require ( github.com/emersion/go-imap v1.0.3-0.20191213134403-f1c945935a36 + github.com/emersion/go-imap-move v0.0.0-20190710073258-6e5a51a5b342 github.com/emersion/go-message v0.10.8 github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b github.com/emersion/go-smtp v0.12.1 diff --git a/go.sum b/go.sum index b3e2bbe..585c322 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/emersion/go-imap v1.0.3-0.20191213134403-f1c945935a36 h1:CrPKMqbfsFwzOFqqXd43j40NfCKJUgm6niLJhklQkrA= github.com/emersion/go-imap v1.0.3-0.20191213134403-f1c945935a36/go.mod h1:TjT+1ncDso8j/VXeUHcZeQknho5hjyQLqEIybJJjjDI= +github.com/emersion/go-imap-move v0.0.0-20190710073258-6e5a51a5b342 h1:5p1t3e1PomYgLWwEwhwEU5kVBwcyAcVrOpexv8AeZx0= +github.com/emersion/go-imap-move v0.0.0-20190710073258-6e5a51a5b342/go.mod h1:QuMaZcKFDVI0yCrnAbPLfbwllz1wtOrZH8/vZ5yzp4w= github.com/emersion/go-message v0.10.8 h1:1l1Vb+0By9U1ITTH3FgKfJQWQ9sTI3N1smPe6SS3QXY= github.com/emersion/go-message v0.10.8/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY= github.com/emersion/go-sasl v0.0.0-20190817083125-240c8404624e h1:ba7YsgX5OV8FjGi5ZWml8Jng6oBrJAb3ahqWMJ5Ce8Q= diff --git a/plugins/base/handlers.go b/plugins/base/handlers.go index 8e9971a..d77cd4a 100644 --- a/plugins/base/handlers.go +++ b/plugins/base/handlers.go @@ -12,6 +12,7 @@ import ( "git.sr.ht/~emersion/koushin" "github.com/emersion/go-imap" imapclient "github.com/emersion/go-imap/client" + imapmove "github.com/emersion/go-imap-move" "github.com/emersion/go-message" "github.com/emersion/go-smtp" "github.com/labstack/echo/v4" @@ -120,6 +121,7 @@ func handleLogout(ectx echo.Context) error { type MessageRenderData struct { koushin.RenderData + Mailboxes []*imap.MailboxInfo Mailbox *imap.MailboxStatus Message *IMAPMessage Body string @@ -138,14 +140,20 @@ func handleGetPart(ctx *koushin.Context, raw bool) error { return echo.NewHTTPError(http.StatusBadRequest, err) } + var mailboxes []*imap.MailboxInfo var msg *IMAPMessage var part *message.Entity var mbox *imap.MailboxStatus err = ctx.Session.DoIMAP(func(c *imapclient.Client) error { var err error - msg, part, err = getMessagePart(c, mboxName, uid, partPath) + if mailboxes, err = listMailboxes(c); err != nil { + return err + } + if msg, part, err = getMessagePart(c, mboxName, uid, partPath); err != nil { + return err + } mbox = c.Mailbox() - return err + return nil }) if err != nil { return err @@ -187,6 +195,7 @@ func handleGetPart(ctx *koushin.Context, raw bool) error { return ctx.Render(http.StatusOK, "message.html", &MessageRenderData{ RenderData: *koushin.NewRenderData(ctx), + Mailboxes: mailboxes, Mailbox: mbox, Message: msg, Body: body, @@ -296,3 +305,36 @@ func handleCompose(ectx echo.Context) error { Message: &msg, }) } + +func handleMove(ectx echo.Context) error { + ctx := ectx.(*koushin.Context) + + mboxName, uid, err := parseMboxAndUid(ctx.Param("mbox"), ctx.Param("uid")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, err) + } + + to := ctx.FormValue("to") + + err = ctx.Session.DoIMAP(func(c *imapclient.Client) error { + mc := imapmove.NewClient(c) + + if err := ensureMailboxSelected(c, mboxName); err != nil { + return err + } + + var seqSet imap.SeqSet + seqSet.AddNum(uid) + if err := mc.UidMoveWithFallback(&seqSet, to); err != nil { + return fmt.Errorf("failed to move message: %v", err) + } + + // TODO: get the UID of the message in the destination mailbox with UIDPLUS + return nil + }) + if err != nil { + return err + } + + return ctx.Redirect(http.StatusFound, fmt.Sprintf("/mailbox/%v", to)) +} diff --git a/plugins/base/plugin.go b/plugins/base/plugin.go index 7c2aeaf..7eaf00c 100644 --- a/plugins/base/plugin.go +++ b/plugins/base/plugin.go @@ -45,5 +45,7 @@ func init() { p.GET("/message/:mbox/:uid/reply", handleCompose) p.POST("/message/:mbox/:uid/reply", handleCompose) + p.POST("/message/:mbox/:uid/move", handleMove) + koushin.RegisterPlugin(p.Plugin()) } diff --git a/plugins/base/public/message.html b/plugins/base/public/message.html index 729937d..2a0ab71 100644 --- a/plugins/base/public/message.html +++ b/plugins/base/public/message.html @@ -16,6 +16,16 @@ {{end}} +
+ + + +
+ {{define "message-part-tree"}} {{/* nested templates can't access the parent's context */}} {{$ = index . 0}}