parent
1a658fc22c
commit
1c5e17472d
5 changed files with 74 additions and 9 deletions
|
@ -23,6 +23,7 @@ type MailboxRenderData struct {
|
|||
Mailboxes []*imap.MailboxInfo
|
||||
Messages []imapMessage
|
||||
PrevPage, NextPage int
|
||||
Query string
|
||||
}
|
||||
|
||||
func handleGetMailbox(ectx echo.Context) error {
|
||||
|
@ -41,6 +42,8 @@ func handleGetMailbox(ectx echo.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
query := ctx.FormValue("query")
|
||||
|
||||
var mailboxes []*imap.MailboxInfo
|
||||
var msgs []imapMessage
|
||||
var mbox *imap.MailboxStatus
|
||||
|
@ -49,7 +52,12 @@ func handleGetMailbox(ectx echo.Context) error {
|
|||
if mailboxes, err = listMailboxes(c); err != nil {
|
||||
return err
|
||||
}
|
||||
if msgs, err = listMessages(c, mboxName, page); err != nil {
|
||||
if query != "" {
|
||||
msgs, err = searchMessages(c, mboxName, query)
|
||||
} else {
|
||||
msgs, err = listMessages(c, mboxName, page)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mbox = c.Mailbox()
|
||||
|
@ -60,12 +68,15 @@ func handleGetMailbox(ectx echo.Context) error {
|
|||
}
|
||||
|
||||
prevPage, nextPage := -1, -1
|
||||
if query == "" {
|
||||
// TODO: paging for search
|
||||
if page > 0 {
|
||||
prevPage = page - 1
|
||||
}
|
||||
if (page+1)*messagesPerPage < int(mbox.Messages) {
|
||||
nextPage = page + 1
|
||||
}
|
||||
}
|
||||
|
||||
return ctx.Render(http.StatusOK, "mailbox.html", &MailboxRenderData{
|
||||
RenderData: *koushin.NewRenderData(ctx),
|
||||
|
@ -74,6 +85,7 @@ func handleGetMailbox(ectx echo.Context) error {
|
|||
Messages: msgs,
|
||||
PrevPage: prevPage,
|
||||
NextPage: nextPage,
|
||||
Query: query,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ func listMessages(conn *imapclient.Client, mboxName string, page int) ([]imapMes
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
seqSet := new(imap.SeqSet)
|
||||
var seqSet imap.SeqSet
|
||||
seqSet.AddRange(uint32(from), uint32(to))
|
||||
|
||||
fetch := []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid, imap.FetchBodyStructure}
|
||||
|
@ -197,7 +197,7 @@ func listMessages(conn *imapclient.Client, mboxName string, page int) ([]imapMes
|
|||
ch := make(chan *imap.Message, 10)
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- conn.Fetch(seqSet, fetch, ch)
|
||||
done <- conn.Fetch(&seqSet, fetch, ch)
|
||||
}()
|
||||
|
||||
msgs := make([]imapMessage, 0, to-from)
|
||||
|
@ -218,6 +218,53 @@ func listMessages(conn *imapclient.Client, mboxName string, page int) ([]imapMes
|
|||
return msgs, nil
|
||||
}
|
||||
|
||||
func searchMessages(conn *imapclient.Client, mboxName, query string) ([]imapMessage, error) {
|
||||
if err := ensureMailboxSelected(conn, mboxName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
criteria := imap.SearchCriteria{Text: []string{query}}
|
||||
nums, err := conn.Search(&criteria)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("UID SEARCH failed: %v", err)
|
||||
}
|
||||
if len(nums) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
indexes := make(map[uint32]int)
|
||||
for i, num := range nums {
|
||||
indexes[num] = i
|
||||
}
|
||||
|
||||
// TODO: paging
|
||||
var seqSet imap.SeqSet
|
||||
seqSet.AddNum(nums...)
|
||||
|
||||
fetch := []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid, imap.FetchBodyStructure}
|
||||
|
||||
ch := make(chan *imap.Message, 10)
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- conn.Fetch(&seqSet, fetch, ch)
|
||||
}()
|
||||
|
||||
msgs := make([]imapMessage, len(nums))
|
||||
for msg := range ch {
|
||||
i, ok := indexes[msg.SeqNum]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
msgs[i] = imapMessage{msg}
|
||||
}
|
||||
|
||||
if err := <-done; err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch message list: %v", err)
|
||||
}
|
||||
|
||||
return msgs, nil
|
||||
}
|
||||
|
||||
func getMessagePart(conn *imapclient.Client, mboxName string, uid uint32, partPath []int) (*imapMessage, *message.Entity, error) {
|
||||
if err := ensureMailboxSelected(conn, mboxName); err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
@ -23,6 +23,7 @@ func init() {
|
|||
})
|
||||
|
||||
p.GET("/mailbox/:mbox", handleGetMailbox)
|
||||
p.POST("/mailbox/:mbox", handleGetMailbox)
|
||||
|
||||
p.GET("/message/:mbox/:uid", func(ectx echo.Context) error {
|
||||
ctx := ectx.(*koushin.Context)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<h1>koushin</h1>
|
||||
|
||||
<form method="post" action="/login">
|
||||
<form method="post" action="">
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" name="username" id="username"/>
|
||||
<br><br>
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
|
||||
<h2>{{.Mailbox.Name}}</h2>
|
||||
|
||||
<form method="post" action="">
|
||||
<input type="search" name="query" value="{{.Query}}">
|
||||
<input type="submit" value="Search">
|
||||
</form>
|
||||
|
||||
<p>Mailboxes:</p>
|
||||
<ul>
|
||||
{{range .Mailboxes}}
|
||||
|
|
Loading…
Reference in a new issue