mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-18 18:17:03 +00:00
Reorganize packages, closes #79
- All packages go into either cmd or pkg directories - Most packages renamed - Server packages moved into pkg/server - sanitize moved into webui, as that's the only place it's used - filestore moved into pkg/storage/file - Makefile updated, and PKG variable use fixed
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -26,8 +26,12 @@ _testmain.go
|
|||||||
*.swo
|
*.swo
|
||||||
|
|
||||||
# our binaries
|
# our binaries
|
||||||
|
/client
|
||||||
|
/client.exe
|
||||||
/inbucket
|
/inbucket
|
||||||
/inbucket.exe
|
/inbucket.exe
|
||||||
/dist/**
|
/dist/**
|
||||||
/cmd/client/client
|
/cmd/client/client
|
||||||
/cmd/client/client.exe
|
/cmd/client/client.exe
|
||||||
|
/cmd/inbucket/inbucket
|
||||||
|
/cmd/inbucket/inbucket.exe
|
||||||
|
|||||||
31
Makefile
31
Makefile
@@ -1,26 +1,27 @@
|
|||||||
PKG := inbucket
|
SHELL = /bin/sh
|
||||||
SHELL := /bin/sh
|
|
||||||
|
|
||||||
SRC := $(shell find . -type f -name '*.go' -not -path "./vendor/*")
|
SRC ::= $(shell find . -type f -name '*.go' -not -path "./vendor/*")
|
||||||
PKGS := $$(go list ./... | grep -v /vendor/)
|
PKGS ::= $(shell go list ./... | grep -v /vendor/)
|
||||||
|
|
||||||
.PHONY: all build clean fmt install lint simplify test
|
.PHONY: all build clean fmt lint simplify test
|
||||||
|
|
||||||
all: test lint build
|
commands ::= client inbucket
|
||||||
|
|
||||||
|
all: clean test lint build
|
||||||
|
|
||||||
|
$(commands): %: cmd/%
|
||||||
|
go build ./$<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
go clean
|
go clean $(PKGS)
|
||||||
|
rm -f $(commands)
|
||||||
|
|
||||||
deps:
|
deps:
|
||||||
go get -t ./...
|
go get -t ./...
|
||||||
|
|
||||||
build: clean deps
|
build: deps $(commands)
|
||||||
go build
|
|
||||||
|
|
||||||
install: build
|
test: deps
|
||||||
go install
|
|
||||||
|
|
||||||
test: clean deps
|
|
||||||
go test -race ./...
|
go test -race ./...
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
@@ -31,5 +32,5 @@ simplify:
|
|||||||
|
|
||||||
lint:
|
lint:
|
||||||
@test -z "$(shell gofmt -l . | tee /dev/stderr)" || echo "[WARN] Fix formatting issues with 'make fmt'"
|
@test -z "$(shell gofmt -l . | tee /dev/stderr)" || echo "[WARN] Fix formatting issues with 'make fmt'"
|
||||||
@golint -set_exit_status $${PKGS}
|
@golint -set_exit_status $(PKGS)
|
||||||
@go vet $${PKGS}
|
@go vet $(PKGS)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
"github.com/jhillyerd/inbucket/rest/client"
|
"github.com/jhillyerd/inbucket/pkg/rest/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type listCmd struct {
|
type listCmd struct {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
"github.com/jhillyerd/inbucket/rest/client"
|
"github.com/jhillyerd/inbucket/pkg/rest/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type matchCmd struct {
|
type matchCmd struct {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
"github.com/jhillyerd/inbucket/rest/client"
|
"github.com/jhillyerd/inbucket/pkg/rest/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mboxCmd struct {
|
type mboxCmd struct {
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/filestore"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
"github.com/jhillyerd/inbucket/pkg/msghub"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/rest"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/pkg/server/pop3"
|
||||||
"github.com/jhillyerd/inbucket/pop3d"
|
"github.com/jhillyerd/inbucket/pkg/server/smtp"
|
||||||
"github.com/jhillyerd/inbucket/rest"
|
"github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
"github.com/jhillyerd/inbucket/smtpd"
|
"github.com/jhillyerd/inbucket/pkg/storage/file"
|
||||||
"github.com/jhillyerd/inbucket/webui"
|
"github.com/jhillyerd/inbucket/pkg/webui"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -39,8 +39,8 @@ var (
|
|||||||
shutdownChan = make(chan bool)
|
shutdownChan = make(chan bool)
|
||||||
|
|
||||||
// Server instances
|
// Server instances
|
||||||
smtpServer *smtpd.Server
|
smtpServer *smtp.Server
|
||||||
pop3Server *pop3d.Server
|
pop3Server *pop3.Server
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -119,17 +119,17 @@ func main() {
|
|||||||
ds := filestore.DefaultFileDataStore()
|
ds := filestore.DefaultFileDataStore()
|
||||||
|
|
||||||
// Start HTTP server
|
// Start HTTP server
|
||||||
httpd.Initialize(config.GetWebConfig(), shutdownChan, ds, msgHub)
|
web.Initialize(config.GetWebConfig(), shutdownChan, ds, msgHub)
|
||||||
webui.SetupRoutes(httpd.Router)
|
webui.SetupRoutes(web.Router)
|
||||||
rest.SetupRoutes(httpd.Router)
|
rest.SetupRoutes(web.Router)
|
||||||
go httpd.Start(rootCtx)
|
go web.Start(rootCtx)
|
||||||
|
|
||||||
// Start POP3 server
|
// Start POP3 server
|
||||||
pop3Server = pop3d.New(config.GetPOP3Config(), shutdownChan, ds)
|
pop3Server = pop3.New(config.GetPOP3Config(), shutdownChan, ds)
|
||||||
go pop3Server.Start(rootCtx)
|
go pop3Server.Start(rootCtx)
|
||||||
|
|
||||||
// Startup SMTP server
|
// Startup SMTP server
|
||||||
smtpServer = smtpd.NewServer(config.GetSMTPConfig(), shutdownChan, ds, msgHub)
|
smtpServer = smtp.NewServer(config.GetSMTPConfig(), shutdownChan, ds, msgHub)
|
||||||
go smtpServer.Start(rootCtx)
|
go smtpServer.Start(rootCtx)
|
||||||
|
|
||||||
// Loop forever waiting for signals or shutdown channel
|
// Loop forever waiting for signals or shutdown channel
|
||||||
@@ -10,15 +10,15 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
"github.com/jhillyerd/inbucket/pkg/rest/model"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
"github.com/jhillyerd/inbucket/rest/model"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
"github.com/jhillyerd/inbucket/stringutil"
|
"github.com/jhillyerd/inbucket/pkg/stringutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MailboxListV1 renders a list of messages in a mailbox
|
// MailboxListV1 renders a list of messages in a mailbox
|
||||||
func MailboxListV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxListV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -48,11 +48,11 @@ func MailboxListV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context)
|
|||||||
Size: msg.Size(),
|
Size: msg.Size(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return httpd.RenderJSON(w, jmessages)
|
return web.RenderJSON(w, jmessages)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MailboxShowV1 renders a particular message from a mailbox
|
// MailboxShowV1 renders a particular message from a mailbox
|
||||||
func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
@@ -96,7 +96,7 @@ func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return httpd.RenderJSON(w,
|
return web.RenderJSON(w,
|
||||||
&model.JSONMessageV1{
|
&model.JSONMessageV1{
|
||||||
Mailbox: name,
|
Mailbox: name,
|
||||||
ID: msg.ID(),
|
ID: msg.ID(),
|
||||||
@@ -115,7 +115,7 @@ func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MailboxPurgeV1 deletes all messages from a mailbox
|
// MailboxPurgeV1 deletes all messages from a mailbox
|
||||||
func MailboxPurgeV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxPurgeV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -133,11 +133,11 @@ func MailboxPurgeV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context
|
|||||||
}
|
}
|
||||||
log.Tracef("HTTP purged mailbox for %q", name)
|
log.Tracef("HTTP purged mailbox for %q", name)
|
||||||
|
|
||||||
return httpd.RenderJSON(w, "OK")
|
return web.RenderJSON(w, "OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
// MailboxSourceV1 displays the raw source of a message, including headers. Renders text/plain
|
// MailboxSourceV1 displays the raw source of a message, including headers. Renders text/plain
|
||||||
func MailboxSourceV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxSourceV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
@@ -171,7 +171,7 @@ func MailboxSourceV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MailboxDeleteV1 removes a particular message from a mailbox
|
// MailboxDeleteV1 removes a particular message from a mailbox
|
||||||
func MailboxDeleteV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxDeleteV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
@@ -197,5 +197,5 @@ func MailboxDeleteV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Contex
|
|||||||
return fmt.Errorf("Delete(%q) failed: %v", id, err)
|
return fmt.Errorf("Delete(%q) failed: %v", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return httpd.RenderJSON(w, "OK")
|
return web.RenderJSON(w, "OK")
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/rest/model"
|
"github.com/jhillyerd/inbucket/pkg/rest/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client accesses the Inbucket REST API v1
|
// Client accesses the Inbucket REST API v1
|
||||||
23
pkg/rest/routes.go
Normal file
23
pkg/rest/routes.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package rest
|
||||||
|
|
||||||
|
import "github.com/gorilla/mux"
|
||||||
|
import "github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
|
|
||||||
|
// SetupRoutes populates the routes for the REST interface
|
||||||
|
func SetupRoutes(r *mux.Router) {
|
||||||
|
// API v1
|
||||||
|
r.Path("/api/v1/mailbox/{name}").Handler(
|
||||||
|
web.Handler(MailboxListV1)).Name("MailboxListV1").Methods("GET")
|
||||||
|
r.Path("/api/v1/mailbox/{name}").Handler(
|
||||||
|
web.Handler(MailboxPurgeV1)).Name("MailboxPurgeV1").Methods("DELETE")
|
||||||
|
r.Path("/api/v1/mailbox/{name}/{id}").Handler(
|
||||||
|
web.Handler(MailboxShowV1)).Name("MailboxShowV1").Methods("GET")
|
||||||
|
r.Path("/api/v1/mailbox/{name}/{id}").Handler(
|
||||||
|
web.Handler(MailboxDeleteV1)).Name("MailboxDeleteV1").Methods("DELETE")
|
||||||
|
r.Path("/api/v1/mailbox/{name}/{id}/source").Handler(
|
||||||
|
web.Handler(MailboxSourceV1)).Name("MailboxSourceV1").Methods("GET")
|
||||||
|
r.Path("/api/v1/monitor/messages").Handler(
|
||||||
|
web.Handler(MonitorAllMessagesV1)).Name("MonitorAllMessagesV1").Methods("GET")
|
||||||
|
r.Path("/api/v1/monitor/messages/{name}").Handler(
|
||||||
|
web.Handler(MonitorMailboxMessagesV1)).Name("MonitorMailboxMessagesV1").Methods("GET")
|
||||||
|
}
|
||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/msghub"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/pkg/rest/model"
|
||||||
"github.com/jhillyerd/inbucket/rest/model"
|
"github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
"github.com/jhillyerd/inbucket/stringutil"
|
"github.com/jhillyerd/inbucket/pkg/stringutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -145,16 +145,16 @@ func (ml *msgListener) Close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MonitorAllMessagesV1(
|
func MonitorAllMessagesV1(
|
||||||
w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Upgrade to Websocket
|
// Upgrade to Websocket
|
||||||
conn, err := upgrader.Upgrade(w, req, nil)
|
conn, err := upgrader.Upgrade(w, req, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
httpd.ExpWebSocketConnectsCurrent.Add(1)
|
web.ExpWebSocketConnectsCurrent.Add(1)
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
httpd.ExpWebSocketConnectsCurrent.Add(-1)
|
web.ExpWebSocketConnectsCurrent.Add(-1)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.Tracef("HTTP[%v] Upgraded to websocket", req.RemoteAddr)
|
log.Tracef("HTTP[%v] Upgraded to websocket", req.RemoteAddr)
|
||||||
@@ -168,7 +168,7 @@ func MonitorAllMessagesV1(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MonitorMailboxMessagesV1(
|
func MonitorMailboxMessagesV1(
|
||||||
w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -178,10 +178,10 @@ func MonitorMailboxMessagesV1(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
httpd.ExpWebSocketConnectsCurrent.Add(1)
|
web.ExpWebSocketConnectsCurrent.Add(1)
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
httpd.ExpWebSocketConnectsCurrent.Add(-1)
|
web.ExpWebSocketConnectsCurrent.Add(-1)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.Tracef("HTTP[%v] Upgraded to websocket", req.RemoteAddr)
|
log.Tracef("HTTP[%v] Upgraded to websocket", req.RemoteAddr)
|
||||||
@@ -10,10 +10,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/enmime"
|
"github.com/jhillyerd/enmime"
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/msghub"
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
"github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InputMessageData struct {
|
type InputMessageData struct {
|
||||||
@@ -184,7 +184,7 @@ func testRestGet(url string) (*httptest.ResponseRecorder, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
httpd.Router.ServeHTTP(w, req)
|
web.Router.ServeHTTP(w, req)
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,8 +200,8 @@ func setupWebServer(ds datastore.DataStore) *bytes.Buffer {
|
|||||||
PublicDir: "../themes/bootstrap/public",
|
PublicDir: "../themes/bootstrap/public",
|
||||||
}
|
}
|
||||||
shutdownChan := make(chan bool)
|
shutdownChan := make(chan bool)
|
||||||
httpd.Initialize(cfg, shutdownChan, ds, &msghub.Hub{})
|
web.Initialize(cfg, shutdownChan, ds, &msghub.Hub{})
|
||||||
SetupRoutes(httpd.Router)
|
SetupRoutes(web.Router)
|
||||||
|
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package pop3d
|
package pop3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// State tracks the current mode of our POP3 state machine
|
// State tracks the current mode of our POP3 state machine
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package pop3d
|
package pop3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server defines an instance of our POP3 server
|
// Server defines an instance of our POP3 server
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package smtpd
|
package smtp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@@ -12,10 +12,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/msghub"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
"github.com/jhillyerd/inbucket/stringutil"
|
"github.com/jhillyerd/inbucket/pkg/stringutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// State tracks the current mode of our SMTP state machine
|
// State tracks the current mode of our SMTP state machine
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package smtpd
|
package smtp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -13,9 +13,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/msghub"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
type scriptStep struct {
|
type scriptStep struct {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package smtpd
|
package smtp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
@@ -10,10 +10,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/msghub"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package httpd
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/msghub"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Context is passed into every request handler function
|
// Context is passed into every request handler function
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package httpd
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TemplateFuncs declares functions made available to all templates (including partials)
|
// TemplateFuncs declares functions made available to all templates (including partials)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package httpd
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package httpd
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Package httpd provides the plumbing for Inbucket's web GUI and RESTful API
|
// Package web provides the plumbing for Inbucket's web GUI and RESTful API
|
||||||
package httpd
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -12,10 +12,10 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gorilla/securecookie"
|
"github.com/gorilla/securecookie"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/msghub"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is a function type that handles an HTTP request in Inbucket
|
// Handler is a function type that handles an HTTP request in Inbucket
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package httpd
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cachedMutex sync.Mutex
|
var cachedMutex sync.Mutex
|
||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/enmime"
|
"github.com/jhillyerd/enmime"
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileMessage implements Message and contains a little bit of data about a
|
// FileMessage implements Message and contains a little bit of data about a
|
||||||
@@ -11,10 +11,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/stringutil"
|
"github.com/jhillyerd/inbucket/pkg/stringutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Name of index file in each mailbox
|
// Name of index file in each mailbox
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@ package datastore_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHashLock(t *testing.T) {
|
func TestHashLock(t *testing.T) {
|
||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -7,29 +7,29 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/datastore"
|
"github.com/jhillyerd/inbucket/pkg/log"
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
"github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
"github.com/jhillyerd/inbucket/sanitize"
|
"github.com/jhillyerd/inbucket/pkg/stringutil"
|
||||||
"github.com/jhillyerd/inbucket/stringutil"
|
"github.com/jhillyerd/inbucket/pkg/webui/sanitize"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MailboxIndex renders the index page for a particular mailbox
|
// MailboxIndex renders the index page for a particular mailbox
|
||||||
func MailboxIndex(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxIndex(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Form values must be validated manually
|
// Form values must be validated manually
|
||||||
name := req.FormValue("name")
|
name := req.FormValue("name")
|
||||||
selected := req.FormValue("id")
|
selected := req.FormValue("id")
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
ctx.Session.AddFlash("Account name is required", "errors")
|
ctx.Session.AddFlash("Account name is required", "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
name, err = stringutil.ParseMailboxName(name)
|
name, err = stringutil.ParseMailboxName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Session.AddFlash(err.Error(), "errors")
|
ctx.Session.AddFlash(err.Error(), "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Remember this mailbox was visited
|
// Remember this mailbox was visited
|
||||||
@@ -40,7 +40,7 @@ func MailboxIndex(w http.ResponseWriter, req *http.Request, ctx *httpd.Context)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Render template
|
// Render template
|
||||||
return httpd.RenderTemplate("mailbox/index.html", w, map[string]interface{}{
|
return web.RenderTemplate("mailbox/index.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
"errorFlash": errorFlash,
|
"errorFlash": errorFlash,
|
||||||
"name": name,
|
"name": name,
|
||||||
@@ -49,24 +49,24 @@ func MailboxIndex(w http.ResponseWriter, req *http.Request, ctx *httpd.Context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MailboxLink handles pretty links to a particular message. Renders a redirect
|
// MailboxLink handles pretty links to a particular message. Renders a redirect
|
||||||
func MailboxLink(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxLink(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Session.AddFlash(err.Error(), "errors")
|
ctx.Session.AddFlash(err.Error(), "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Build redirect
|
// Build redirect
|
||||||
uri := fmt.Sprintf("%s?name=%s&id=%s", httpd.Reverse("MailboxIndex"), name, id)
|
uri := fmt.Sprintf("%s?name=%s&id=%s", web.Reverse("MailboxIndex"), name, id)
|
||||||
http.Redirect(w, req, uri, http.StatusSeeOther)
|
http.Redirect(w, req, uri, http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MailboxList renders a list of messages in a mailbox. Renders a partial
|
// MailboxList renders a list of messages in a mailbox. Renders a partial
|
||||||
func MailboxList(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxList(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -84,7 +84,7 @@ func MailboxList(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
}
|
}
|
||||||
log.Tracef("Got %v messsages", len(messages))
|
log.Tracef("Got %v messsages", len(messages))
|
||||||
// Render partial template
|
// Render partial template
|
||||||
return httpd.RenderPartial("mailbox/_list.html", w, map[string]interface{}{
|
return web.RenderPartial("mailbox/_list.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
"name": name,
|
"name": name,
|
||||||
"messages": messages,
|
"messages": messages,
|
||||||
@@ -92,7 +92,7 @@ func MailboxList(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MailboxShow renders a particular message from a mailbox. Renders an HTML partial
|
// MailboxShow renders a particular message from a mailbox. Renders an HTML partial
|
||||||
func MailboxShow(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxShow(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
@@ -117,7 +117,7 @@ func MailboxShow(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ReadBody(%q) failed: %v", id, err)
|
return fmt.Errorf("ReadBody(%q) failed: %v", id, err)
|
||||||
}
|
}
|
||||||
body := template.HTML(httpd.TextToHTML(mime.Text))
|
body := template.HTML(web.TextToHTML(mime.Text))
|
||||||
htmlAvailable := mime.HTML != ""
|
htmlAvailable := mime.HTML != ""
|
||||||
var htmlBody template.HTML
|
var htmlBody template.HTML
|
||||||
if htmlAvailable {
|
if htmlAvailable {
|
||||||
@@ -128,7 +128,7 @@ func MailboxShow(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Render partial template
|
// Render partial template
|
||||||
return httpd.RenderPartial("mailbox/_show.html", w, map[string]interface{}{
|
return web.RenderPartial("mailbox/_show.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
"name": name,
|
"name": name,
|
||||||
"message": msg,
|
"message": msg,
|
||||||
@@ -141,7 +141,7 @@ func MailboxShow(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MailboxHTML displays the HTML content of a message. Renders a partial
|
// MailboxHTML displays the HTML content of a message. Renders a partial
|
||||||
func MailboxHTML(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxHTML(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
@@ -168,7 +168,7 @@ func MailboxHTML(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
}
|
}
|
||||||
// Render partial template
|
// Render partial template
|
||||||
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
|
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
|
||||||
return httpd.RenderPartial("mailbox/_html.html", w, map[string]interface{}{
|
return web.RenderPartial("mailbox/_html.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
"name": name,
|
"name": name,
|
||||||
"message": message,
|
"message": message,
|
||||||
@@ -178,7 +178,7 @@ func MailboxHTML(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MailboxSource displays the raw source of a message, including headers. Renders text/plain
|
// MailboxSource displays the raw source of a message, including headers. Renders text/plain
|
||||||
func MailboxSource(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxSource(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
@@ -213,14 +213,14 @@ func MailboxSource(w http.ResponseWriter, req *http.Request, ctx *httpd.Context)
|
|||||||
|
|
||||||
// MailboxDownloadAttach sends the attachment to the client; disposition:
|
// MailboxDownloadAttach sends the attachment to the client; disposition:
|
||||||
// attachment, type: application/octet-stream
|
// attachment, type: application/octet-stream
|
||||||
func MailboxDownloadAttach(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxDownloadAttach(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Session.AddFlash(err.Error(), "errors")
|
ctx.Session.AddFlash(err.Error(), "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
numStr := ctx.Vars["num"]
|
numStr := ctx.Vars["num"]
|
||||||
@@ -228,7 +228,7 @@ func MailboxDownloadAttach(w http.ResponseWriter, req *http.Request, ctx *httpd.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Session.AddFlash("Attachment number must be unsigned numeric", "errors")
|
ctx.Session.AddFlash("Attachment number must be unsigned numeric", "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
mb, err := ctx.DataStore.MailboxFor(name)
|
mb, err := ctx.DataStore.MailboxFor(name)
|
||||||
@@ -252,7 +252,7 @@ func MailboxDownloadAttach(w http.ResponseWriter, req *http.Request, ctx *httpd.
|
|||||||
if int(num) >= len(body.Attachments) {
|
if int(num) >= len(body.Attachments) {
|
||||||
ctx.Session.AddFlash("Attachment number too high", "errors")
|
ctx.Session.AddFlash("Attachment number too high", "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
part := body.Attachments[num]
|
part := body.Attachments[num]
|
||||||
@@ -266,13 +266,13 @@ func MailboxDownloadAttach(w http.ResponseWriter, req *http.Request, ctx *httpd.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MailboxViewAttach sends the attachment to the client for online viewing
|
// MailboxViewAttach sends the attachment to the client for online viewing
|
||||||
func MailboxViewAttach(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func MailboxViewAttach(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
// Don't have to validate these aren't empty, Gorilla returns 404
|
// Don't have to validate these aren't empty, Gorilla returns 404
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Session.AddFlash(err.Error(), "errors")
|
ctx.Session.AddFlash(err.Error(), "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
id := ctx.Vars["id"]
|
id := ctx.Vars["id"]
|
||||||
@@ -281,7 +281,7 @@ func MailboxViewAttach(w http.ResponseWriter, req *http.Request, ctx *httpd.Cont
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Session.AddFlash("Attachment number must be unsigned numeric", "errors")
|
ctx.Session.AddFlash("Attachment number must be unsigned numeric", "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
mb, err := ctx.DataStore.MailboxFor(name)
|
mb, err := ctx.DataStore.MailboxFor(name)
|
||||||
@@ -305,7 +305,7 @@ func MailboxViewAttach(w http.ResponseWriter, req *http.Request, ctx *httpd.Cont
|
|||||||
if int(num) >= len(body.Attachments) {
|
if int(num) >= len(body.Attachments) {
|
||||||
ctx.Session.AddFlash("Attachment number too high", "errors")
|
ctx.Session.AddFlash("Attachment number too high", "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
part := body.Attachments[num]
|
part := body.Attachments[num]
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package webui
|
package webui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
"github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -12,7 +12,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// RememberMailbox manages the list of recently accessed mailboxes stored in the session
|
// RememberMailbox manages the list of recently accessed mailboxes stored in the session
|
||||||
func RememberMailbox(ctx *httpd.Context, mailbox string) {
|
func RememberMailbox(ctx *web.Context, mailbox string) {
|
||||||
recent := RecentMailboxes(ctx)
|
recent := RecentMailboxes(ctx)
|
||||||
newRecent := make([]string, 1, maxRemembered)
|
newRecent := make([]string, 1, maxRemembered)
|
||||||
newRecent[0] = mailbox
|
newRecent[0] = mailbox
|
||||||
@@ -28,7 +28,7 @@ func RememberMailbox(ctx *httpd.Context, mailbox string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RecentMailboxes returns a slice of the most recently accessed mailboxes
|
// RecentMailboxes returns a slice of the most recently accessed mailboxes
|
||||||
func RecentMailboxes(ctx *httpd.Context) []string {
|
func RecentMailboxes(ctx *web.Context) []string {
|
||||||
val := ctx.Session.Values[mailboxKey]
|
val := ctx.Session.Values[mailboxKey]
|
||||||
recent, _ := val.([]string)
|
recent, _ := val.([]string)
|
||||||
return recent
|
return recent
|
||||||
@@ -6,13 +6,13 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/pkg/config"
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
"github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
"github.com/jhillyerd/inbucket/stringutil"
|
"github.com/jhillyerd/inbucket/pkg/stringutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RootIndex serves the Inbucket landing page
|
// RootIndex serves the Inbucket landing page
|
||||||
func RootIndex(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func RootIndex(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
greeting, err := ioutil.ReadFile(config.GetWebConfig().GreetingFile)
|
greeting, err := ioutil.ReadFile(config.GetWebConfig().GreetingFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to load greeting: %v", err)
|
return fmt.Errorf("Failed to load greeting: %v", err)
|
||||||
@@ -23,7 +23,7 @@ func RootIndex(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Render template
|
// Render template
|
||||||
return httpd.RenderTemplate("root/index.html", w, map[string]interface{}{
|
return web.RenderTemplate("root/index.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
"errorFlash": errorFlash,
|
"errorFlash": errorFlash,
|
||||||
"greeting": template.HTML(string(greeting)),
|
"greeting": template.HTML(string(greeting)),
|
||||||
@@ -31,11 +31,11 @@ func RootIndex(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RootMonitor serves the Inbucket monitor page
|
// RootMonitor serves the Inbucket monitor page
|
||||||
func RootMonitor(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func RootMonitor(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
if !config.GetWebConfig().MonitorVisible {
|
if !config.GetWebConfig().MonitorVisible {
|
||||||
ctx.Session.AddFlash("Monitor is disabled in configuration", "errors")
|
ctx.Session.AddFlash("Monitor is disabled in configuration", "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Get flash messages, save session
|
// Get flash messages, save session
|
||||||
@@ -44,25 +44,25 @@ func RootMonitor(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Render template
|
// Render template
|
||||||
return httpd.RenderTemplate("root/monitor.html", w, map[string]interface{}{
|
return web.RenderTemplate("root/monitor.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
"errorFlash": errorFlash,
|
"errorFlash": errorFlash,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RootMonitorMailbox serves the Inbucket monitor page for a particular mailbox
|
// RootMonitorMailbox serves the Inbucket monitor page for a particular mailbox
|
||||||
func RootMonitorMailbox(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func RootMonitorMailbox(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
if !config.GetWebConfig().MonitorVisible {
|
if !config.GetWebConfig().MonitorVisible {
|
||||||
ctx.Session.AddFlash("Monitor is disabled in configuration", "errors")
|
ctx.Session.AddFlash("Monitor is disabled in configuration", "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
name, err := stringutil.ParseMailboxName(ctx.Vars["name"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Session.AddFlash(err.Error(), "errors")
|
ctx.Session.AddFlash(err.Error(), "errors")
|
||||||
_ = ctx.Session.Save(req, w)
|
_ = ctx.Session.Save(req, w)
|
||||||
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Get flash messages, save session
|
// Get flash messages, save session
|
||||||
@@ -71,7 +71,7 @@ func RootMonitorMailbox(w http.ResponseWriter, req *http.Request, ctx *httpd.Con
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Render template
|
// Render template
|
||||||
return httpd.RenderTemplate("root/monitor.html", w, map[string]interface{}{
|
return web.RenderTemplate("root/monitor.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
"errorFlash": errorFlash,
|
"errorFlash": errorFlash,
|
||||||
"name": name,
|
"name": name,
|
||||||
@@ -79,7 +79,7 @@ func RootMonitorMailbox(w http.ResponseWriter, req *http.Request, ctx *httpd.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RootStatus serves the Inbucket status page
|
// RootStatus serves the Inbucket status page
|
||||||
func RootStatus(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func RootStatus(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
|
||||||
smtpListener := fmt.Sprintf("%s:%d", config.GetSMTPConfig().IP4address.String(),
|
smtpListener := fmt.Sprintf("%s:%d", config.GetSMTPConfig().IP4address.String(),
|
||||||
config.GetSMTPConfig().IP4port)
|
config.GetSMTPConfig().IP4port)
|
||||||
pop3Listener := fmt.Sprintf("%s:%d", config.GetPOP3Config().IP4address.String(),
|
pop3Listener := fmt.Sprintf("%s:%d", config.GetPOP3Config().IP4address.String(),
|
||||||
@@ -92,7 +92,7 @@ func RootStatus(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Render template
|
// Render template
|
||||||
return httpd.RenderTemplate("root/status.html", w, map[string]interface{}{
|
return web.RenderTemplate("root/status.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
"errorFlash": errorFlash,
|
"errorFlash": errorFlash,
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
35
pkg/webui/routes.go
Normal file
35
pkg/webui/routes.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// Package webui powers Inbucket's web GUI
|
||||||
|
package webui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/jhillyerd/inbucket/pkg/server/web"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetupRoutes populates routes for the webui into the provided Router
|
||||||
|
func SetupRoutes(r *mux.Router) {
|
||||||
|
r.Path("/").Handler(
|
||||||
|
web.Handler(RootIndex)).Name("RootIndex").Methods("GET")
|
||||||
|
r.Path("/monitor").Handler(
|
||||||
|
web.Handler(RootMonitor)).Name("RootMonitor").Methods("GET")
|
||||||
|
r.Path("/monitor/{name}").Handler(
|
||||||
|
web.Handler(RootMonitorMailbox)).Name("RootMonitorMailbox").Methods("GET")
|
||||||
|
r.Path("/status").Handler(
|
||||||
|
web.Handler(RootStatus)).Name("RootStatus").Methods("GET")
|
||||||
|
r.Path("/link/{name}/{id}").Handler(
|
||||||
|
web.Handler(MailboxLink)).Name("MailboxLink").Methods("GET")
|
||||||
|
r.Path("/mailbox").Handler(
|
||||||
|
web.Handler(MailboxIndex)).Name("MailboxIndex").Methods("GET")
|
||||||
|
r.Path("/mailbox/{name}").Handler(
|
||||||
|
web.Handler(MailboxList)).Name("MailboxList").Methods("GET")
|
||||||
|
r.Path("/mailbox/{name}/{id}").Handler(
|
||||||
|
web.Handler(MailboxShow)).Name("MailboxShow").Methods("GET")
|
||||||
|
r.Path("/mailbox/{name}/{id}/html").Handler(
|
||||||
|
web.Handler(MailboxHTML)).Name("MailboxHtml").Methods("GET")
|
||||||
|
r.Path("/mailbox/{name}/{id}/source").Handler(
|
||||||
|
web.Handler(MailboxSource)).Name("MailboxSource").Methods("GET")
|
||||||
|
r.Path("/mailbox/dattach/{name}/{id}/{num}/{file}").Handler(
|
||||||
|
web.Handler(MailboxDownloadAttach)).Name("MailboxDownloadAttach").Methods("GET")
|
||||||
|
r.Path("/mailbox/vattach/{name}/{id}/{num}/{file}").Handler(
|
||||||
|
web.Handler(MailboxViewAttach)).Name("MailboxViewAttach").Methods("GET")
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ package sanitize_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jhillyerd/inbucket/sanitize"
|
"github.com/jhillyerd/inbucket/pkg/webui/sanitize"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestHTMLPlainStrings test plain text passthrough
|
// TestHTMLPlainStrings test plain text passthrough
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package rest
|
|
||||||
|
|
||||||
import "github.com/gorilla/mux"
|
|
||||||
import "github.com/jhillyerd/inbucket/httpd"
|
|
||||||
|
|
||||||
// SetupRoutes populates the routes for the REST interface
|
|
||||||
func SetupRoutes(r *mux.Router) {
|
|
||||||
// API v1
|
|
||||||
r.Path("/api/v1/mailbox/{name}").Handler(
|
|
||||||
httpd.Handler(MailboxListV1)).Name("MailboxListV1").Methods("GET")
|
|
||||||
r.Path("/api/v1/mailbox/{name}").Handler(
|
|
||||||
httpd.Handler(MailboxPurgeV1)).Name("MailboxPurgeV1").Methods("DELETE")
|
|
||||||
r.Path("/api/v1/mailbox/{name}/{id}").Handler(
|
|
||||||
httpd.Handler(MailboxShowV1)).Name("MailboxShowV1").Methods("GET")
|
|
||||||
r.Path("/api/v1/mailbox/{name}/{id}").Handler(
|
|
||||||
httpd.Handler(MailboxDeleteV1)).Name("MailboxDeleteV1").Methods("DELETE")
|
|
||||||
r.Path("/api/v1/mailbox/{name}/{id}/source").Handler(
|
|
||||||
httpd.Handler(MailboxSourceV1)).Name("MailboxSourceV1").Methods("GET")
|
|
||||||
r.Path("/api/v1/monitor/messages").Handler(
|
|
||||||
httpd.Handler(MonitorAllMessagesV1)).Name("MonitorAllMessagesV1").Methods("GET")
|
|
||||||
r.Path("/api/v1/monitor/messages/{name}").Handler(
|
|
||||||
httpd.Handler(MonitorMailboxMessagesV1)).Name("MonitorMailboxMessagesV1").Methods("GET")
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
// Package webui powers Inbucket's web GUI
|
|
||||||
package webui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SetupRoutes populates routes for the webui into the provided Router
|
|
||||||
func SetupRoutes(r *mux.Router) {
|
|
||||||
r.Path("/").Handler(
|
|
||||||
httpd.Handler(RootIndex)).Name("RootIndex").Methods("GET")
|
|
||||||
r.Path("/monitor").Handler(
|
|
||||||
httpd.Handler(RootMonitor)).Name("RootMonitor").Methods("GET")
|
|
||||||
r.Path("/monitor/{name}").Handler(
|
|
||||||
httpd.Handler(RootMonitorMailbox)).Name("RootMonitorMailbox").Methods("GET")
|
|
||||||
r.Path("/status").Handler(
|
|
||||||
httpd.Handler(RootStatus)).Name("RootStatus").Methods("GET")
|
|
||||||
r.Path("/link/{name}/{id}").Handler(
|
|
||||||
httpd.Handler(MailboxLink)).Name("MailboxLink").Methods("GET")
|
|
||||||
r.Path("/mailbox").Handler(
|
|
||||||
httpd.Handler(MailboxIndex)).Name("MailboxIndex").Methods("GET")
|
|
||||||
r.Path("/mailbox/{name}").Handler(
|
|
||||||
httpd.Handler(MailboxList)).Name("MailboxList").Methods("GET")
|
|
||||||
r.Path("/mailbox/{name}/{id}").Handler(
|
|
||||||
httpd.Handler(MailboxShow)).Name("MailboxShow").Methods("GET")
|
|
||||||
r.Path("/mailbox/{name}/{id}/html").Handler(
|
|
||||||
httpd.Handler(MailboxHTML)).Name("MailboxHtml").Methods("GET")
|
|
||||||
r.Path("/mailbox/{name}/{id}/source").Handler(
|
|
||||||
httpd.Handler(MailboxSource)).Name("MailboxSource").Methods("GET")
|
|
||||||
r.Path("/mailbox/dattach/{name}/{id}/{num}/{file}").Handler(
|
|
||||||
httpd.Handler(MailboxDownloadAttach)).Name("MailboxDownloadAttach").Methods("GET")
|
|
||||||
r.Path("/mailbox/vattach/{name}/{id}/{num}/{file}").Handler(
|
|
||||||
httpd.Handler(MailboxViewAttach)).Name("MailboxViewAttach").Methods("GET")
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user