aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conn_pool.go2
-rw-r--r--imap.go20
-rw-r--r--public/mailbox.html15
-rw-r--r--public/message.html8
-rw-r--r--server.go23
-rw-r--r--smtp.go10
-rw-r--r--strconv.go2
7 files changed, 60 insertions, 20 deletions
diff --git a/conn_pool.go b/conn_pool.go
index 69281af..34c51bb 100644
--- a/conn_pool.go
+++ b/conn_pool.go
@@ -21,7 +21,7 @@ func generateToken() (string, error) {
var ErrSessionExpired = errors.New("session expired")
type Session struct {
- locker sync.Mutex
+ locker sync.Mutex
imapConn *imapclient.Client
username, password string
}
diff --git a/imap.go b/imap.go
index 748d5cb..9c83fc7 100644
--- a/imap.go
+++ b/imap.go
@@ -206,23 +206,23 @@ func (msg *imapMessage) PartTree() *IMAPPartNode {
return imapPartTree(msg.BodyStructure, nil)
}
-func listMessages(conn *imapclient.Client, mboxName string) ([]imapMessage, error) {
+func listMessages(conn *imapclient.Client, mboxName string, page int) ([]imapMessage, error) {
if err := ensureMailboxSelected(conn, mboxName); err != nil {
return nil, err
}
- n := uint32(50)
-
mbox := conn.Mailbox()
- from := uint32(1)
- to := mbox.Messages
- if mbox.Messages == 0 {
+ to := int(mbox.Messages) - page*messagesPerPage
+ from := to - messagesPerPage
+ if from <= 0 {
+ from = 1
+ }
+ if to <= 0 {
return nil, nil
- } else if mbox.Messages > n {
- from = mbox.Messages - n
}
+
seqSet := new(imap.SeqSet)
- seqSet.AddRange(from, to)
+ seqSet.AddRange(uint32(from), uint32(to))
fetch := []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid, imap.FetchBodyStructure}
@@ -232,7 +232,7 @@ func listMessages(conn *imapclient.Client, mboxName string) ([]imapMessage, erro
done <- conn.Fetch(seqSet, fetch, ch)
}()
- msgs := make([]imapMessage, 0, n)
+ msgs := make([]imapMessage, 0, to-from)
for msg := range ch {
msgs = append(msgs, imapMessage{msg})
}
diff --git a/public/mailbox.html b/public/mailbox.html
index e56efcb..435998c 100644
--- a/public/mailbox.html
+++ b/public/mailbox.html
@@ -20,10 +20,23 @@
<ul>
{{range .Messages}}
<li><a href="/message/{{$.Mailbox.Name | pathescape}}/{{.Uid}}?part={{.TextPartName}}">
- {{.Envelope.Subject}}
+ {{if .Envelope.Subject}}
+ {{.Envelope.Subject}}
+ {{else}}
+ (No subject)
+ {{end}}
</a></li>
{{end}}
</ul>
+
+ <p>
+ {{if ge .PrevPage 0}}
+ <a href="?page={{.PrevPage}}">Prev</a>
+ {{end}}
+ {{if ge .NextPage 0}}
+ <a href="?page={{.NextPage}}">Next</a>
+ {{end}}
+ </p>
{{else}}
<p>Mailbox is empty.</p>
{{end}}
diff --git a/public/message.html b/public/message.html
index 2e1a308..5c18bd0 100644
--- a/public/message.html
+++ b/public/message.html
@@ -6,7 +6,13 @@
<a href="/mailbox/{{.Mailbox.Name | pathescape}}">Back</a>
</p>
-<h2>{{.Message.Envelope.Subject}}</h2>
+<h2>
+ {{if .Message.Envelope.Subject}}
+ {{.Message.Envelope.Subject}}
+ {{else}}
+ (No subject)
+ {{end}}
+</h2>
{{define "message-part-tree"}}
{{/* nested templates can't access the parent's context */}}
diff --git a/server.go b/server.go
index bcdcfcc..93da487 100644
--- a/server.go
+++ b/server.go
@@ -6,6 +6,7 @@ import (
"mime"
"net/http"
"net/url"
+ "strconv"
"strings"
"time"
@@ -18,6 +19,8 @@ import (
const cookieName = "koushin_session"
+const messagesPerPage = 50
+
type Server struct {
imap struct {
host string
@@ -366,6 +369,14 @@ func New(imapURL, smtpURL string) *echo.Echo {
return echo.NewHTTPError(http.StatusBadRequest, err)
}
+ page := 0
+ if pageStr := ctx.QueryParam("page"); pageStr != "" {
+ var err error
+ if page, err = strconv.Atoi(pageStr); err != nil || page < 0 {
+ return echo.NewHTTPError(http.StatusBadRequest, "invalid page index")
+ }
+ }
+
var mailboxes []*imap.MailboxInfo
var msgs []imapMessage
var mbox *imap.MailboxStatus
@@ -374,7 +385,7 @@ func New(imapURL, smtpURL string) *echo.Echo {
if mailboxes, err = listMailboxes(c); err != nil {
return err
}
- if msgs, err = listMessages(c, mboxName); err != nil {
+ if msgs, err = listMessages(c, mboxName, page); err != nil {
return err
}
mbox = c.Mailbox()
@@ -384,10 +395,20 @@ func New(imapURL, smtpURL string) *echo.Echo {
return err
}
+ prevPage, nextPage := -1, -1
+ if page > 0 {
+ prevPage = page - 1
+ }
+ if (page+1)*messagesPerPage < int(mbox.Messages) {
+ nextPage = page + 1
+ }
+
return ctx.Render(http.StatusOK, "mailbox.html", map[string]interface{}{
"Mailbox": mbox,
"Mailboxes": mailboxes,
"Messages": msgs,
+ "PrevPage": prevPage,
+ "NextPage": nextPage,
})
})
diff --git a/smtp.go b/smtp.go
index 288f332..b9d77b2 100644
--- a/smtp.go
+++ b/smtp.go
@@ -3,9 +3,9 @@ package koushin
import (
"bufio"
"fmt"
- "time"
"io"
"strings"
+ "time"
"github.com/emersion/go-message/mail"
"github.com/emersion/go-smtp"
@@ -50,11 +50,11 @@ func (s *Server) connectSMTP() (*smtp.Client, error) {
}
type OutgoingMessage struct {
- From string
- To []string
- Subject string
+ From string
+ To []string
+ Subject string
InReplyTo string
- Text string
+ Text string
}
func (msg *OutgoingMessage) ToString() string {
diff --git a/strconv.go b/strconv.go
index 14c0c27..63cbffc 100644
--- a/strconv.go
+++ b/strconv.go
@@ -2,9 +2,9 @@ package koushin
import (
"fmt"
+ "net/url"
"strconv"
"strings"
- "net/url"
)
func parseUid(s string) (uint32, error) {