mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 09:37:02 +00:00
- storage: rename DataStore to Store - file: rename types to appease linter
This commit is contained in:
@@ -116,7 +116,7 @@ func main() {
|
|||||||
msgHub := msghub.New(rootCtx, config.GetWebConfig().MonitorHistory)
|
msgHub := msghub.New(rootCtx, config.GetWebConfig().MonitorHistory)
|
||||||
|
|
||||||
// Grab our datastore
|
// Grab our datastore
|
||||||
ds := filestore.DefaultFileDataStore()
|
ds := file.DefaultStore()
|
||||||
|
|
||||||
// Start HTTP server
|
// Start HTTP server
|
||||||
web.Initialize(config.GetWebConfig(), shutdownChan, ds, msgHub)
|
web.Initialize(config.GetWebConfig(), shutdownChan, ds, msgHub)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (
|
|||||||
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
msg, err := mb.GetMessage(id)
|
msg, err := mb.GetMessage(id)
|
||||||
if err == datastore.ErrNotExist {
|
if err == storage.ErrNotExist {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ func MailboxSourceV1(w http.ResponseWriter, req *http.Request, ctx *web.Context)
|
|||||||
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
message, err := mb.GetMessage(id)
|
message, err := mb.GetMessage(id)
|
||||||
if err == datastore.ErrNotExist {
|
if err == storage.ErrNotExist {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ func MailboxDeleteV1(w http.ResponseWriter, req *http.Request, ctx *web.Context)
|
|||||||
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
message, err := mb.GetMessage(id)
|
message, err := mb.GetMessage(id)
|
||||||
if err == datastore.ErrNotExist {
|
if err == storage.ErrNotExist {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const (
|
|||||||
|
|
||||||
func TestRestMailboxList(t *testing.T) {
|
func TestRestMailboxList(t *testing.T) {
|
||||||
// Setup
|
// Setup
|
||||||
ds := &datastore.MockDataStore{}
|
ds := &storage.MockDataStore{}
|
||||||
logbuf := setupWebServer(ds)
|
logbuf := setupWebServer(ds)
|
||||||
|
|
||||||
// Test invalid mailbox name
|
// Test invalid mailbox name
|
||||||
@@ -45,9 +45,9 @@ func TestRestMailboxList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test empty mailbox
|
// Test empty mailbox
|
||||||
emptybox := &datastore.MockMailbox{}
|
emptybox := &storage.MockMailbox{}
|
||||||
ds.On("MailboxFor", "empty").Return(emptybox, nil)
|
ds.On("MailboxFor", "empty").Return(emptybox, nil)
|
||||||
emptybox.On("GetMessages").Return([]datastore.Message{}, nil)
|
emptybox.On("GetMessages").Return([]storage.Message{}, nil)
|
||||||
|
|
||||||
w, err = testRestGet(baseURL + "/mailbox/empty")
|
w, err = testRestGet(baseURL + "/mailbox/empty")
|
||||||
expectCode = 200
|
expectCode = 200
|
||||||
@@ -59,7 +59,7 @@ func TestRestMailboxList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test MailboxFor error
|
// Test MailboxFor error
|
||||||
ds.On("MailboxFor", "error").Return(&datastore.MockMailbox{}, fmt.Errorf("Internal error"))
|
ds.On("MailboxFor", "error").Return(&storage.MockMailbox{}, fmt.Errorf("Internal error"))
|
||||||
w, err = testRestGet(baseURL + "/mailbox/error")
|
w, err = testRestGet(baseURL + "/mailbox/error")
|
||||||
expectCode = 500
|
expectCode = 500
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -77,9 +77,9 @@ func TestRestMailboxList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test MailboxFor error
|
// Test MailboxFor error
|
||||||
error2box := &datastore.MockMailbox{}
|
error2box := &storage.MockMailbox{}
|
||||||
ds.On("MailboxFor", "error2").Return(error2box, nil)
|
ds.On("MailboxFor", "error2").Return(error2box, nil)
|
||||||
error2box.On("GetMessages").Return([]datastore.Message{}, fmt.Errorf("Internal error 2"))
|
error2box.On("GetMessages").Return([]storage.Message{}, fmt.Errorf("Internal error 2"))
|
||||||
|
|
||||||
w, err = testRestGet(baseURL + "/mailbox/error2")
|
w, err = testRestGet(baseURL + "/mailbox/error2")
|
||||||
expectCode = 500
|
expectCode = 500
|
||||||
@@ -107,11 +107,11 @@ func TestRestMailboxList(t *testing.T) {
|
|||||||
Subject: "subject 2",
|
Subject: "subject 2",
|
||||||
Date: time.Date(2012, 7, 1, 10, 11, 12, 253, time.FixedZone("PDT", -700)),
|
Date: time.Date(2012, 7, 1, 10, 11, 12, 253, time.FixedZone("PDT", -700)),
|
||||||
}
|
}
|
||||||
goodbox := &datastore.MockMailbox{}
|
goodbox := &storage.MockMailbox{}
|
||||||
ds.On("MailboxFor", "good").Return(goodbox, nil)
|
ds.On("MailboxFor", "good").Return(goodbox, nil)
|
||||||
msg1 := data1.MockMessage()
|
msg1 := data1.MockMessage()
|
||||||
msg2 := data2.MockMessage()
|
msg2 := data2.MockMessage()
|
||||||
goodbox.On("GetMessages").Return([]datastore.Message{msg1, msg2}, nil)
|
goodbox.On("GetMessages").Return([]storage.Message{msg1, msg2}, nil)
|
||||||
|
|
||||||
// Check return code
|
// Check return code
|
||||||
w, err = testRestGet(baseURL + "/mailbox/good")
|
w, err = testRestGet(baseURL + "/mailbox/good")
|
||||||
@@ -155,7 +155,7 @@ func TestRestMailboxList(t *testing.T) {
|
|||||||
|
|
||||||
func TestRestMessage(t *testing.T) {
|
func TestRestMessage(t *testing.T) {
|
||||||
// Setup
|
// Setup
|
||||||
ds := &datastore.MockDataStore{}
|
ds := &storage.MockDataStore{}
|
||||||
logbuf := setupWebServer(ds)
|
logbuf := setupWebServer(ds)
|
||||||
|
|
||||||
// Test invalid mailbox name
|
// Test invalid mailbox name
|
||||||
@@ -169,9 +169,9 @@ func TestRestMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test requesting a message that does not exist
|
// Test requesting a message that does not exist
|
||||||
emptybox := &datastore.MockMailbox{}
|
emptybox := &storage.MockMailbox{}
|
||||||
ds.On("MailboxFor", "empty").Return(emptybox, nil)
|
ds.On("MailboxFor", "empty").Return(emptybox, nil)
|
||||||
emptybox.On("GetMessage", "0001").Return(&datastore.MockMessage{}, datastore.ErrNotExist)
|
emptybox.On("GetMessage", "0001").Return(&storage.MockMessage{}, storage.ErrNotExist)
|
||||||
|
|
||||||
w, err = testRestGet(baseURL + "/mailbox/empty/0001")
|
w, err = testRestGet(baseURL + "/mailbox/empty/0001")
|
||||||
expectCode = 404
|
expectCode = 404
|
||||||
@@ -183,7 +183,7 @@ func TestRestMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test MailboxFor error
|
// Test MailboxFor error
|
||||||
ds.On("MailboxFor", "error").Return(&datastore.MockMailbox{}, fmt.Errorf("Internal error"))
|
ds.On("MailboxFor", "error").Return(&storage.MockMailbox{}, fmt.Errorf("Internal error"))
|
||||||
w, err = testRestGet(baseURL + "/mailbox/error/0001")
|
w, err = testRestGet(baseURL + "/mailbox/error/0001")
|
||||||
expectCode = 500
|
expectCode = 500
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -201,9 +201,9 @@ func TestRestMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test GetMessage error
|
// Test GetMessage error
|
||||||
error2box := &datastore.MockMailbox{}
|
error2box := &storage.MockMailbox{}
|
||||||
ds.On("MailboxFor", "error2").Return(error2box, nil)
|
ds.On("MailboxFor", "error2").Return(error2box, nil)
|
||||||
error2box.On("GetMessage", "0001").Return(&datastore.MockMessage{}, fmt.Errorf("Internal error 2"))
|
error2box.On("GetMessage", "0001").Return(&storage.MockMessage{}, fmt.Errorf("Internal error 2"))
|
||||||
|
|
||||||
w, err = testRestGet(baseURL + "/mailbox/error2/0001")
|
w, err = testRestGet(baseURL + "/mailbox/error2/0001")
|
||||||
expectCode = 500
|
expectCode = 500
|
||||||
@@ -228,7 +228,7 @@ func TestRestMessage(t *testing.T) {
|
|||||||
Text: "This is some text",
|
Text: "This is some text",
|
||||||
HTML: "This is some HTML",
|
HTML: "This is some HTML",
|
||||||
}
|
}
|
||||||
goodbox := &datastore.MockMailbox{}
|
goodbox := &storage.MockMailbox{}
|
||||||
ds.On("MailboxFor", "good").Return(goodbox, nil)
|
ds.On("MailboxFor", "good").Return(goodbox, nil)
|
||||||
msg1 := data1.MockMessage()
|
msg1 := data1.MockMessage()
|
||||||
goodbox.On("GetMessage", "0001").Return(msg1, nil)
|
goodbox.On("GetMessage", "0001").Return(msg1, nil)
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ type InputMessageData struct {
|
|||||||
HTML, Text string
|
HTML, Text string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *InputMessageData) MockMessage() *datastore.MockMessage {
|
func (d *InputMessageData) MockMessage() *storage.MockMessage {
|
||||||
msg := &datastore.MockMessage{}
|
msg := &storage.MockMessage{}
|
||||||
msg.On("ID").Return(d.ID)
|
msg.On("ID").Return(d.ID)
|
||||||
msg.On("From").Return(d.From)
|
msg.On("From").Return(d.From)
|
||||||
msg.On("To").Return(d.To)
|
msg.On("To").Return(d.To)
|
||||||
@@ -188,7 +188,7 @@ func testRestGet(url string) (*httptest.ResponseRecorder, error) {
|
|||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupWebServer(ds datastore.DataStore) *bytes.Buffer {
|
func setupWebServer(ds storage.Store) *bytes.Buffer {
|
||||||
// Capture log output
|
// Capture log output
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
log.SetOutput(buf)
|
log.SetOutput(buf)
|
||||||
|
|||||||
@@ -57,18 +57,18 @@ var commands = map[string]bool{
|
|||||||
|
|
||||||
// Session defines an active POP3 session
|
// Session defines an active POP3 session
|
||||||
type Session struct {
|
type Session struct {
|
||||||
server *Server // Reference to the server we belong to
|
server *Server // Reference to the server we belong to
|
||||||
id int // Session ID number
|
id int // Session ID number
|
||||||
conn net.Conn // Our network connection
|
conn net.Conn // Our network connection
|
||||||
remoteHost string // IP address of client
|
remoteHost string // IP address of client
|
||||||
sendError error // Used to bail out of read loop on send error
|
sendError error // Used to bail out of read loop on send error
|
||||||
state State // Current session state
|
state State // Current session state
|
||||||
reader *bufio.Reader // Buffered reader for our net conn
|
reader *bufio.Reader // Buffered reader for our net conn
|
||||||
user string // Mailbox name
|
user string // Mailbox name
|
||||||
mailbox datastore.Mailbox // Mailbox instance
|
mailbox storage.Mailbox // Mailbox instance
|
||||||
messages []datastore.Message // Slice of messages in mailbox
|
messages []storage.Message // Slice of messages in mailbox
|
||||||
retain []bool // Messages to retain upon UPDATE (true=retain)
|
retain []bool // Messages to retain upon UPDATE (true=retain)
|
||||||
msgCount int // Number of undeleted messages
|
msgCount int // Number of undeleted messages
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSession creates a new POP3 session
|
// NewSession creates a new POP3 session
|
||||||
@@ -432,7 +432,7 @@ func (ses *Session) transactionHandler(cmd string, args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send the contents of the message to the client
|
// Send the contents of the message to the client
|
||||||
func (ses *Session) sendMessage(msg datastore.Message) {
|
func (ses *Session) sendMessage(msg storage.Message) {
|
||||||
reader, err := msg.RawReader()
|
reader, err := msg.RawReader()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ses.logError("Failed to read message for RETR command")
|
ses.logError("Failed to read message for RETR command")
|
||||||
@@ -465,7 +465,7 @@ func (ses *Session) sendMessage(msg datastore.Message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send the headers plus the top N lines to the client
|
// Send the headers plus the top N lines to the client
|
||||||
func (ses *Session) sendMessageTop(msg datastore.Message, lineCount int) {
|
func (ses *Session) sendMessageTop(msg storage.Message, lineCount int) {
|
||||||
reader, err := msg.RawReader()
|
reader, err := msg.RawReader()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ses.logError("Failed to read message for RETR command")
|
ses.logError("Failed to read message for RETR command")
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ type Server struct {
|
|||||||
host string
|
host string
|
||||||
domain string
|
domain string
|
||||||
maxIdleSeconds int
|
maxIdleSeconds int
|
||||||
dataStore datastore.DataStore
|
dataStore storage.Store
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
globalShutdown chan bool
|
globalShutdown chan bool
|
||||||
waitgroup *sync.WaitGroup
|
waitgroup *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Server struct
|
// New creates a new Server struct
|
||||||
func New(cfg config.POP3Config, shutdownChan chan bool, ds datastore.DataStore) *Server {
|
func New(cfg config.POP3Config, shutdownChan chan bool, ds storage.Store) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
host: fmt.Sprintf("%v:%v", cfg.IP4address, cfg.IP4port),
|
host: fmt.Sprintf("%v:%v", cfg.IP4address, cfg.IP4port),
|
||||||
domain: cfg.Domain,
|
domain: cfg.Domain,
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ var commands = map[string]bool{
|
|||||||
// recipientDetails for message delivery
|
// recipientDetails for message delivery
|
||||||
type recipientDetails struct {
|
type recipientDetails struct {
|
||||||
address, localPart, domainPart string
|
address, localPart, domainPart string
|
||||||
mailbox datastore.Mailbox
|
mailbox storage.Mailbox
|
||||||
}
|
}
|
||||||
|
|
||||||
// Session holds the state of an SMTP session
|
// Session holds the state of an SMTP session
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type scriptStep struct {
|
|||||||
// Test commands in GREET state
|
// Test commands in GREET state
|
||||||
func TestGreetState(t *testing.T) {
|
func TestGreetState(t *testing.T) {
|
||||||
// Setup mock objects
|
// Setup mock objects
|
||||||
mds := &datastore.MockDataStore{}
|
mds := &storage.MockDataStore{}
|
||||||
|
|
||||||
server, logbuf, teardown := setupSMTPServer(mds)
|
server, logbuf, teardown := setupSMTPServer(mds)
|
||||||
defer teardown()
|
defer teardown()
|
||||||
@@ -83,7 +83,7 @@ func TestGreetState(t *testing.T) {
|
|||||||
// Test commands in READY state
|
// Test commands in READY state
|
||||||
func TestReadyState(t *testing.T) {
|
func TestReadyState(t *testing.T) {
|
||||||
// Setup mock objects
|
// Setup mock objects
|
||||||
mds := &datastore.MockDataStore{}
|
mds := &storage.MockDataStore{}
|
||||||
|
|
||||||
server, logbuf, teardown := setupSMTPServer(mds)
|
server, logbuf, teardown := setupSMTPServer(mds)
|
||||||
defer teardown()
|
defer teardown()
|
||||||
@@ -144,9 +144,9 @@ func TestReadyState(t *testing.T) {
|
|||||||
// Test commands in MAIL state
|
// Test commands in MAIL state
|
||||||
func TestMailState(t *testing.T) {
|
func TestMailState(t *testing.T) {
|
||||||
// Setup mock objects
|
// Setup mock objects
|
||||||
mds := &datastore.MockDataStore{}
|
mds := &storage.MockDataStore{}
|
||||||
mb1 := &datastore.MockMailbox{}
|
mb1 := &storage.MockMailbox{}
|
||||||
msg1 := &datastore.MockMessage{}
|
msg1 := &storage.MockMessage{}
|
||||||
mds.On("MailboxFor", "u1").Return(mb1, nil)
|
mds.On("MailboxFor", "u1").Return(mb1, nil)
|
||||||
mb1.On("NewMessage").Return(msg1, nil)
|
mb1.On("NewMessage").Return(msg1, nil)
|
||||||
mb1.On("Name").Return("u1")
|
mb1.On("Name").Return("u1")
|
||||||
@@ -259,9 +259,9 @@ func TestMailState(t *testing.T) {
|
|||||||
// Test commands in DATA state
|
// Test commands in DATA state
|
||||||
func TestDataState(t *testing.T) {
|
func TestDataState(t *testing.T) {
|
||||||
// Setup mock objects
|
// Setup mock objects
|
||||||
mds := &datastore.MockDataStore{}
|
mds := &storage.MockDataStore{}
|
||||||
mb1 := &datastore.MockMailbox{}
|
mb1 := &storage.MockMailbox{}
|
||||||
msg1 := &datastore.MockMessage{}
|
msg1 := &storage.MockMessage{}
|
||||||
mds.On("MailboxFor", "u1").Return(mb1, nil)
|
mds.On("MailboxFor", "u1").Return(mb1, nil)
|
||||||
mb1.On("NewMessage").Return(msg1, nil)
|
mb1.On("NewMessage").Return(msg1, nil)
|
||||||
mb1.On("Name").Return("u1")
|
mb1.On("Name").Return("u1")
|
||||||
@@ -367,7 +367,7 @@ func (m *mockConn) SetDeadline(t time.Time) error { return nil }
|
|||||||
func (m *mockConn) SetReadDeadline(t time.Time) error { return nil }
|
func (m *mockConn) SetReadDeadline(t time.Time) error { return nil }
|
||||||
func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil }
|
func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil }
|
||||||
|
|
||||||
func setupSMTPServer(ds datastore.DataStore) (s *Server, buf *bytes.Buffer, teardown func()) {
|
func setupSMTPServer(ds storage.Store) (s *Server, buf *bytes.Buffer, teardown func()) {
|
||||||
// Test Server Config
|
// Test Server Config
|
||||||
cfg := config.SMTPConfig{
|
cfg := config.SMTPConfig{
|
||||||
IP4address: net.IPv4(127, 0, 0, 1),
|
IP4address: net.IPv4(127, 0, 0, 1),
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ type Server struct {
|
|||||||
storeMessages bool
|
storeMessages bool
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
dataStore datastore.DataStore // Mailbox/message store
|
dataStore storage.Store // Mailbox/message store
|
||||||
globalShutdown chan bool // Shuts down Inbucket
|
globalShutdown chan bool // Shuts down Inbucket
|
||||||
msgHub *msghub.Hub // Pub/sub for message info
|
msgHub *msghub.Hub // Pub/sub for message info
|
||||||
retentionScanner *datastore.RetentionScanner // Deletes expired messages
|
retentionScanner *storage.RetentionScanner // Deletes expired messages
|
||||||
|
|
||||||
// State
|
// State
|
||||||
listener net.Listener // Incoming network connections
|
listener net.Listener // Incoming network connections
|
||||||
@@ -83,7 +83,7 @@ var (
|
|||||||
func NewServer(
|
func NewServer(
|
||||||
cfg config.SMTPConfig,
|
cfg config.SMTPConfig,
|
||||||
globalShutdown chan bool,
|
globalShutdown chan bool,
|
||||||
ds datastore.DataStore,
|
ds storage.Store,
|
||||||
msgHub *msghub.Hub) *Server {
|
msgHub *msghub.Hub) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
host: fmt.Sprintf("%v:%v", cfg.IP4address, cfg.IP4port),
|
host: fmt.Sprintf("%v:%v", cfg.IP4address, cfg.IP4port),
|
||||||
@@ -96,7 +96,7 @@ func NewServer(
|
|||||||
globalShutdown: globalShutdown,
|
globalShutdown: globalShutdown,
|
||||||
dataStore: ds,
|
dataStore: ds,
|
||||||
msgHub: msgHub,
|
msgHub: msgHub,
|
||||||
retentionScanner: datastore.NewRetentionScanner(ds, globalShutdown),
|
retentionScanner: storage.NewRetentionScanner(ds, globalShutdown),
|
||||||
waitgroup: new(sync.WaitGroup),
|
waitgroup: new(sync.WaitGroup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
type Context struct {
|
type Context struct {
|
||||||
Vars map[string]string
|
Vars map[string]string
|
||||||
Session *sessions.Session
|
Session *sessions.Session
|
||||||
DataStore datastore.DataStore
|
DataStore storage.Store
|
||||||
MsgHub *msghub.Hub
|
MsgHub *msghub.Hub
|
||||||
WebConfig config.WebConfig
|
WebConfig config.WebConfig
|
||||||
IsJSON bool
|
IsJSON bool
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type Handler func(http.ResponseWriter, *http.Request, *Context) error
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// DataStore is where all the mailboxes and messages live
|
// DataStore is where all the mailboxes and messages live
|
||||||
DataStore datastore.DataStore
|
DataStore storage.Store
|
||||||
|
|
||||||
// msgHub holds a reference to the message pub/sub system
|
// msgHub holds a reference to the message pub/sub system
|
||||||
msgHub *msghub.Hub
|
msgHub *msghub.Hub
|
||||||
@@ -51,7 +51,7 @@ func init() {
|
|||||||
func Initialize(
|
func Initialize(
|
||||||
cfg config.WebConfig,
|
cfg config.WebConfig,
|
||||||
shutdownChan chan bool,
|
shutdownChan chan bool,
|
||||||
ds datastore.DataStore,
|
ds storage.Store,
|
||||||
mh *msghub.Hub) {
|
mh *msghub.Hub) {
|
||||||
|
|
||||||
webConfig = cfg
|
webConfig = cfg
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package filestore
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@@ -15,10 +15,10 @@ import (
|
|||||||
"github.com/jhillyerd/inbucket/pkg/storage"
|
"github.com/jhillyerd/inbucket/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileMessage implements Message and contains a little bit of data about a
|
// Message implements Message and contains a little bit of data about a
|
||||||
// particular email message, and methods to retrieve the rest of it from disk.
|
// particular email message, and methods to retrieve the rest of it from disk.
|
||||||
type FileMessage struct {
|
type Message struct {
|
||||||
mailbox *FileMailbox
|
mailbox *Mailbox
|
||||||
// Stored in GOB
|
// Stored in GOB
|
||||||
Fid string
|
Fid string
|
||||||
Fdate time.Time
|
Fdate time.Time
|
||||||
@@ -34,7 +34,7 @@ type FileMessage struct {
|
|||||||
|
|
||||||
// NewMessage creates a new FileMessage object and sets the Date and Id fields.
|
// NewMessage creates a new FileMessage object and sets the Date and Id fields.
|
||||||
// It will also delete messages over messageCap if configured.
|
// It will also delete messages over messageCap if configured.
|
||||||
func (mb *FileMailbox) NewMessage() (datastore.Message, error) {
|
func (mb *Mailbox) NewMessage() (storage.Message, error) {
|
||||||
// Load index
|
// Load index
|
||||||
if !mb.indexLoaded {
|
if !mb.indexLoaded {
|
||||||
if err := mb.readIndex(); err != nil {
|
if err := mb.readIndex(); err != nil {
|
||||||
@@ -54,50 +54,50 @@ func (mb *FileMailbox) NewMessage() (datastore.Message, error) {
|
|||||||
|
|
||||||
date := time.Now()
|
date := time.Now()
|
||||||
id := generateID(date)
|
id := generateID(date)
|
||||||
return &FileMessage{mailbox: mb, Fid: id, Fdate: date, writable: true}, nil
|
return &Message{mailbox: mb, Fid: id, Fdate: date, writable: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID gets the ID of the Message
|
// ID gets the ID of the Message
|
||||||
func (m *FileMessage) ID() string {
|
func (m *Message) ID() string {
|
||||||
return m.Fid
|
return m.Fid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Date returns the date/time this Message was received by Inbucket
|
// Date returns the date/time this Message was received by Inbucket
|
||||||
func (m *FileMessage) Date() time.Time {
|
func (m *Message) Date() time.Time {
|
||||||
return m.Fdate
|
return m.Fdate
|
||||||
}
|
}
|
||||||
|
|
||||||
// From returns the value of the Message From header
|
// From returns the value of the Message From header
|
||||||
func (m *FileMessage) From() string {
|
func (m *Message) From() string {
|
||||||
return m.Ffrom
|
return m.Ffrom
|
||||||
}
|
}
|
||||||
|
|
||||||
// To returns the value of the Message To header
|
// To returns the value of the Message To header
|
||||||
func (m *FileMessage) To() []string {
|
func (m *Message) To() []string {
|
||||||
return m.Fto
|
return m.Fto
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subject returns the value of the Message Subject header
|
// Subject returns the value of the Message Subject header
|
||||||
func (m *FileMessage) Subject() string {
|
func (m *Message) Subject() string {
|
||||||
return m.Fsubject
|
return m.Fsubject
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a string in the form: "Subject()" from From()
|
// String returns a string in the form: "Subject()" from From()
|
||||||
func (m *FileMessage) String() string {
|
func (m *Message) String() string {
|
||||||
return fmt.Sprintf("\"%v\" from %v", m.Fsubject, m.Ffrom)
|
return fmt.Sprintf("\"%v\" from %v", m.Fsubject, m.Ffrom)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the size of the Message on disk in bytes
|
// Size returns the size of the Message on disk in bytes
|
||||||
func (m *FileMessage) Size() int64 {
|
func (m *Message) Size() int64 {
|
||||||
return m.Fsize
|
return m.Fsize
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *FileMessage) rawPath() string {
|
func (m *Message) rawPath() string {
|
||||||
return filepath.Join(m.mailbox.path, m.Fid+".raw")
|
return filepath.Join(m.mailbox.path, m.Fid+".raw")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadHeader opens the .raw portion of a Message and returns a standard Go mail.Message object
|
// ReadHeader opens the .raw portion of a Message and returns a standard Go mail.Message object
|
||||||
func (m *FileMessage) ReadHeader() (msg *mail.Message, err error) {
|
func (m *Message) ReadHeader() (msg *mail.Message, err error) {
|
||||||
file, err := os.Open(m.rawPath())
|
file, err := os.Open(m.rawPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -113,7 +113,7 @@ func (m *FileMessage) ReadHeader() (msg *mail.Message, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadBody opens the .raw portion of a Message and returns a MIMEBody object
|
// ReadBody opens the .raw portion of a Message and returns a MIMEBody object
|
||||||
func (m *FileMessage) ReadBody() (body *enmime.Envelope, err error) {
|
func (m *Message) ReadBody() (body *enmime.Envelope, err error) {
|
||||||
file, err := os.Open(m.rawPath())
|
file, err := os.Open(m.rawPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -133,7 +133,7 @@ func (m *FileMessage) ReadBody() (body *enmime.Envelope, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RawReader opens the .raw portion of a Message as an io.ReadCloser
|
// RawReader opens the .raw portion of a Message as an io.ReadCloser
|
||||||
func (m *FileMessage) RawReader() (reader io.ReadCloser, err error) {
|
func (m *Message) RawReader() (reader io.ReadCloser, err error) {
|
||||||
file, err := os.Open(m.rawPath())
|
file, err := os.Open(m.rawPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -142,7 +142,7 @@ func (m *FileMessage) RawReader() (reader io.ReadCloser, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadRaw opens the .raw portion of a Message and returns it as a string
|
// ReadRaw opens the .raw portion of a Message and returns it as a string
|
||||||
func (m *FileMessage) ReadRaw() (raw *string, err error) {
|
func (m *Message) ReadRaw() (raw *string, err error) {
|
||||||
reader, err := m.RawReader()
|
reader, err := m.RawReader()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -163,10 +163,10 @@ func (m *FileMessage) ReadRaw() (raw *string, err error) {
|
|||||||
|
|
||||||
// Append data to a newly opened Message, this will fail on a pre-existing Message and
|
// Append data to a newly opened Message, this will fail on a pre-existing Message and
|
||||||
// after Close() is called.
|
// after Close() is called.
|
||||||
func (m *FileMessage) Append(data []byte) error {
|
func (m *Message) Append(data []byte) error {
|
||||||
// Prevent Appending to a pre-existing Message
|
// Prevent Appending to a pre-existing Message
|
||||||
if !m.writable {
|
if !m.writable {
|
||||||
return datastore.ErrNotWritable
|
return storage.ErrNotWritable
|
||||||
}
|
}
|
||||||
// Open file for writing if we haven't yet
|
// Open file for writing if we haven't yet
|
||||||
if m.writer == nil {
|
if m.writer == nil {
|
||||||
@@ -190,7 +190,7 @@ func (m *FileMessage) Append(data []byte) error {
|
|||||||
|
|
||||||
// Close this Message for writing - no more data may be Appended. Close() will also
|
// Close this Message for writing - no more data may be Appended. Close() will also
|
||||||
// trigger the creation of the .gob file.
|
// trigger the creation of the .gob file.
|
||||||
func (m *FileMessage) Close() error {
|
func (m *Message) Close() error {
|
||||||
// nil out the writer fields so they can't be used
|
// nil out the writer fields so they can't be used
|
||||||
writer := m.writer
|
writer := m.writer
|
||||||
writerFile := m.writerFile
|
writerFile := m.writerFile
|
||||||
@@ -245,7 +245,7 @@ func (m *FileMessage) Close() error {
|
|||||||
|
|
||||||
// Delete this Message from disk by removing it from the index and deleting the
|
// Delete this Message from disk by removing it from the index and deleting the
|
||||||
// raw files.
|
// raw files.
|
||||||
func (m *FileMessage) Delete() error {
|
func (m *Message) Delete() error {
|
||||||
messages := m.mailbox.messages
|
messages := m.mailbox.messages
|
||||||
for i, mm := range messages {
|
for i, mm := range messages {
|
||||||
if m == mm {
|
if m == mm {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package filestore
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@@ -48,17 +48,17 @@ func countGenerator(c chan int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileDataStore implements DataStore aand is the root of the mail storage
|
// Store implements DataStore aand is the root of the mail storage
|
||||||
// hiearchy. It provides access to Mailbox objects
|
// hiearchy. It provides access to Mailbox objects
|
||||||
type FileDataStore struct {
|
type Store struct {
|
||||||
hashLock datastore.HashLock
|
hashLock storage.HashLock
|
||||||
path string
|
path string
|
||||||
mailPath string
|
mailPath string
|
||||||
messageCap int
|
messageCap int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFileDataStore creates a new DataStore object using the specified path
|
// New creates a new DataStore object using the specified path
|
||||||
func NewFileDataStore(cfg config.DataStoreConfig) datastore.DataStore {
|
func New(cfg config.DataStoreConfig) storage.Store {
|
||||||
path := cfg.Path
|
path := cfg.Path
|
||||||
if path == "" {
|
if path == "" {
|
||||||
log.Errorf("No value configured for datastore path")
|
log.Errorf("No value configured for datastore path")
|
||||||
@@ -71,19 +71,19 @@ func NewFileDataStore(cfg config.DataStoreConfig) datastore.DataStore {
|
|||||||
log.Errorf("Error creating dir %q: %v", mailPath, err)
|
log.Errorf("Error creating dir %q: %v", mailPath, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &FileDataStore{path: path, mailPath: mailPath, messageCap: cfg.MailboxMsgCap}
|
return &Store{path: path, mailPath: mailPath, messageCap: cfg.MailboxMsgCap}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultFileDataStore creates a new DataStore object. It uses the inbucket.Config object to
|
// DefaultStore creates a new DataStore object. It uses the inbucket.Config object to
|
||||||
// construct it's path.
|
// construct it's path.
|
||||||
func DefaultFileDataStore() datastore.DataStore {
|
func DefaultStore() storage.Store {
|
||||||
cfg := config.GetDataStoreConfig()
|
cfg := config.GetDataStoreConfig()
|
||||||
return NewFileDataStore(cfg)
|
return New(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MailboxFor retrieves the Mailbox object for a specified email address, if the mailbox
|
// MailboxFor retrieves the Mailbox object for a specified email address, if the mailbox
|
||||||
// does not exist, it will attempt to create it.
|
// does not exist, it will attempt to create it.
|
||||||
func (ds *FileDataStore) MailboxFor(emailAddress string) (datastore.Mailbox, error) {
|
func (ds *Store) MailboxFor(emailAddress string) (storage.Mailbox, error) {
|
||||||
name, err := stringutil.ParseMailboxName(emailAddress)
|
name, err := stringutil.ParseMailboxName(emailAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -94,13 +94,13 @@ func (ds *FileDataStore) MailboxFor(emailAddress string) (datastore.Mailbox, err
|
|||||||
path := filepath.Join(ds.mailPath, s1, s2, dir)
|
path := filepath.Join(ds.mailPath, s1, s2, dir)
|
||||||
indexPath := filepath.Join(path, indexFileName)
|
indexPath := filepath.Join(path, indexFileName)
|
||||||
|
|
||||||
return &FileMailbox{store: ds, name: name, dirName: dir, path: path,
|
return &Mailbox{store: ds, name: name, dirName: dir, path: path,
|
||||||
indexPath: indexPath}, nil
|
indexPath: indexPath}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllMailboxes returns a slice with all Mailboxes
|
// AllMailboxes returns a slice with all Mailboxes
|
||||||
func (ds *FileDataStore) AllMailboxes() ([]datastore.Mailbox, error) {
|
func (ds *Store) AllMailboxes() ([]storage.Mailbox, error) {
|
||||||
mailboxes := make([]datastore.Mailbox, 0, 100)
|
mailboxes := make([]storage.Mailbox, 0, 100)
|
||||||
infos1, err := ioutil.ReadDir(ds.mailPath)
|
infos1, err := ioutil.ReadDir(ds.mailPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -127,7 +127,7 @@ func (ds *FileDataStore) AllMailboxes() ([]datastore.Mailbox, error) {
|
|||||||
mbdir := inf3.Name()
|
mbdir := inf3.Name()
|
||||||
mbpath := filepath.Join(ds.mailPath, l1, l2, mbdir)
|
mbpath := filepath.Join(ds.mailPath, l1, l2, mbdir)
|
||||||
idx := filepath.Join(mbpath, indexFileName)
|
idx := filepath.Join(mbpath, indexFileName)
|
||||||
mb := &FileMailbox{store: ds, dirName: mbdir, path: mbpath,
|
mb := &Mailbox{store: ds, dirName: mbdir, path: mbpath,
|
||||||
indexPath: idx}
|
indexPath: idx}
|
||||||
mailboxes = append(mailboxes, mb)
|
mailboxes = append(mailboxes, mb)
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ func (ds *FileDataStore) AllMailboxes() ([]datastore.Mailbox, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LockFor returns the RWMutex for this mailbox, or an error.
|
// LockFor returns the RWMutex for this mailbox, or an error.
|
||||||
func (ds *FileDataStore) LockFor(emailAddress string) (*sync.RWMutex, error) {
|
func (ds *Store) LockFor(emailAddress string) (*sync.RWMutex, error) {
|
||||||
name, err := stringutil.ParseMailboxName(emailAddress)
|
name, err := stringutil.ParseMailboxName(emailAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -150,38 +150,38 @@ func (ds *FileDataStore) LockFor(emailAddress string) (*sync.RWMutex, error) {
|
|||||||
return ds.hashLock.Get(hash), nil
|
return ds.hashLock.Get(hash), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileMailbox implements Mailbox, manages the mail for a specific user and
|
// Mailbox implements Mailbox, manages the mail for a specific user and
|
||||||
// correlates to a particular directory on disk.
|
// correlates to a particular directory on disk.
|
||||||
type FileMailbox struct {
|
type Mailbox struct {
|
||||||
store *FileDataStore
|
store *Store
|
||||||
name string
|
name string
|
||||||
dirName string
|
dirName string
|
||||||
path string
|
path string
|
||||||
indexLoaded bool
|
indexLoaded bool
|
||||||
indexPath string
|
indexPath string
|
||||||
messages []*FileMessage
|
messages []*Message
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name of the mailbox
|
// Name of the mailbox
|
||||||
func (mb *FileMailbox) Name() string {
|
func (mb *Mailbox) Name() string {
|
||||||
return mb.name
|
return mb.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// String renders the name and directory path of the mailbox
|
// String renders the name and directory path of the mailbox
|
||||||
func (mb *FileMailbox) String() string {
|
func (mb *Mailbox) String() string {
|
||||||
return mb.name + "[" + mb.dirName + "]"
|
return mb.name + "[" + mb.dirName + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMessages scans the mailbox directory for .gob files and decodes them into
|
// GetMessages scans the mailbox directory for .gob files and decodes them into
|
||||||
// a slice of Message objects.
|
// a slice of Message objects.
|
||||||
func (mb *FileMailbox) GetMessages() ([]datastore.Message, error) {
|
func (mb *Mailbox) GetMessages() ([]storage.Message, error) {
|
||||||
if !mb.indexLoaded {
|
if !mb.indexLoaded {
|
||||||
if err := mb.readIndex(); err != nil {
|
if err := mb.readIndex(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
messages := make([]datastore.Message, len(mb.messages))
|
messages := make([]storage.Message, len(mb.messages))
|
||||||
for i, m := range mb.messages {
|
for i, m := range mb.messages {
|
||||||
messages[i] = m
|
messages[i] = m
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ func (mb *FileMailbox) GetMessages() ([]datastore.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetMessage decodes a single message by Id and returns a Message object
|
// GetMessage decodes a single message by Id and returns a Message object
|
||||||
func (mb *FileMailbox) GetMessage(id string) (datastore.Message, error) {
|
func (mb *Mailbox) GetMessage(id string) (storage.Message, error) {
|
||||||
if !mb.indexLoaded {
|
if !mb.indexLoaded {
|
||||||
if err := mb.readIndex(); err != nil {
|
if err := mb.readIndex(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -206,17 +206,17 @@ func (mb *FileMailbox) GetMessage(id string) (datastore.Message, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, datastore.ErrNotExist
|
return nil, storage.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purge deletes all messages in this mailbox
|
// Purge deletes all messages in this mailbox
|
||||||
func (mb *FileMailbox) Purge() error {
|
func (mb *Mailbox) Purge() error {
|
||||||
mb.messages = mb.messages[:0]
|
mb.messages = mb.messages[:0]
|
||||||
return mb.writeIndex()
|
return mb.writeIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
// readIndex loads the mailbox index data from disk
|
// readIndex loads the mailbox index data from disk
|
||||||
func (mb *FileMailbox) readIndex() error {
|
func (mb *Mailbox) readIndex() error {
|
||||||
// Clear message slice, open index
|
// Clear message slice, open index
|
||||||
mb.messages = mb.messages[:0]
|
mb.messages = mb.messages[:0]
|
||||||
// Lock for reading
|
// Lock for reading
|
||||||
@@ -242,7 +242,7 @@ func (mb *FileMailbox) readIndex() error {
|
|||||||
// Decode gob data
|
// Decode gob data
|
||||||
dec := gob.NewDecoder(bufio.NewReader(file))
|
dec := gob.NewDecoder(bufio.NewReader(file))
|
||||||
for {
|
for {
|
||||||
msg := new(FileMessage)
|
msg := new(Message)
|
||||||
if err = dec.Decode(msg); err != nil {
|
if err = dec.Decode(msg); err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
// It's OK to get an EOF here
|
// It's OK to get an EOF here
|
||||||
@@ -259,7 +259,7 @@ func (mb *FileMailbox) readIndex() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeIndex overwrites the index on disk with the current mailbox data
|
// writeIndex overwrites the index on disk with the current mailbox data
|
||||||
func (mb *FileMailbox) writeIndex() error {
|
func (mb *Mailbox) writeIndex() error {
|
||||||
// Lock for writing
|
// Lock for writing
|
||||||
indexMx.Lock()
|
indexMx.Lock()
|
||||||
defer indexMx.Unlock()
|
defer indexMx.Unlock()
|
||||||
@@ -301,7 +301,7 @@ func (mb *FileMailbox) writeIndex() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createDir checks for the presence of the path for this mailbox, creates it if needed
|
// createDir checks for the presence of the path for this mailbox, creates it if needed
|
||||||
func (mb *FileMailbox) createDir() error {
|
func (mb *Mailbox) createDir() error {
|
||||||
dirMx.Lock()
|
dirMx.Lock()
|
||||||
defer dirMx.Unlock()
|
defer dirMx.Unlock()
|
||||||
if _, err := os.Stat(mb.path); err != nil {
|
if _, err := os.Stat(mb.path); err != nil {
|
||||||
@@ -314,7 +314,7 @@ func (mb *FileMailbox) createDir() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// removeDir removes the mailbox, plus empty higher level directories
|
// removeDir removes the mailbox, plus empty higher level directories
|
||||||
func (mb *FileMailbox) removeDir() error {
|
func (mb *Mailbox) removeDir() error {
|
||||||
dirMx.Lock()
|
dirMx.Lock()
|
||||||
defer dirMx.Unlock()
|
defer dirMx.Unlock()
|
||||||
// remove mailbox dir, including index file
|
// remove mailbox dir, including index file
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package filestore
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -359,7 +359,7 @@ func TestFSMissing(t *testing.T) {
|
|||||||
// Delete a message file without removing it from index
|
// Delete a message file without removing it from index
|
||||||
msg, err := mb.GetMessage(sentIds[1])
|
msg, err := mb.GetMessage(sentIds[1])
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
fmsg := msg.(*FileMessage)
|
fmsg := msg.(*Message)
|
||||||
_ = os.Remove(fmsg.rawPath())
|
_ = os.Remove(fmsg.rawPath())
|
||||||
msg, err = mb.GetMessage(sentIds[1])
|
msg, err = mb.GetMessage(sentIds[1])
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
@@ -508,7 +508,7 @@ func TestGetLatestMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setupDataStore creates a new FileDataStore in a temporary directory
|
// setupDataStore creates a new FileDataStore in a temporary directory
|
||||||
func setupDataStore(cfg config.DataStoreConfig) (*FileDataStore, *bytes.Buffer) {
|
func setupDataStore(cfg config.DataStoreConfig) (*Store, *bytes.Buffer) {
|
||||||
path, err := ioutil.TempDir("", "inbucket")
|
path, err := ioutil.TempDir("", "inbucket")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -519,12 +519,12 @@ func setupDataStore(cfg config.DataStoreConfig) (*FileDataStore, *bytes.Buffer)
|
|||||||
log.SetOutput(buf)
|
log.SetOutput(buf)
|
||||||
|
|
||||||
cfg.Path = path
|
cfg.Path = path
|
||||||
return NewFileDataStore(cfg).(*FileDataStore), buf
|
return New(cfg).(*Store), buf
|
||||||
}
|
}
|
||||||
|
|
||||||
// deliverMessage creates and delivers a message to the specific mailbox, returning
|
// deliverMessage creates and delivers a message to the specific mailbox, returning
|
||||||
// the size of the generated message.
|
// the size of the generated message.
|
||||||
func deliverMessage(ds *FileDataStore, mbName string, subject string,
|
func deliverMessage(ds *Store, mbName string, subject string,
|
||||||
date time.Time) (id string, size int64) {
|
date time.Time) (id string, size int64) {
|
||||||
// Build fake SMTP message for delivery
|
// Build fake SMTP message for delivery
|
||||||
testMsg := make([]byte, 0, 300)
|
testMsg := make([]byte, 0, 300)
|
||||||
@@ -544,7 +544,7 @@ func deliverMessage(ds *FileDataStore, mbName string, subject string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
fmsg := msg.(*FileMessage)
|
fmsg := msg.(*Message)
|
||||||
fmsg.Fdate = date
|
fmsg.Fdate = date
|
||||||
fmsg.Fid = id
|
fmsg.Fid = id
|
||||||
if err = msg.Append(testMsg); err != nil {
|
if err = msg.Append(testMsg); err != nil {
|
||||||
@@ -557,7 +557,7 @@ func deliverMessage(ds *FileDataStore, mbName string, subject string,
|
|||||||
return id, int64(len(testMsg))
|
return id, int64(len(testMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
func teardownDataStore(ds *FileDataStore) {
|
func teardownDataStore(ds *Store) {
|
||||||
if err := os.RemoveAll(ds.path); err != nil {
|
if err := os.RemoveAll(ds.path); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package datastore
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package datastore_test
|
package storage_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestHashLock(t *testing.T) {
|
func TestHashLock(t *testing.T) {
|
||||||
hl := &datastore.HashLock{}
|
hl := &storage.HashLock{}
|
||||||
|
|
||||||
// Invalid hashes
|
// Invalid hashes
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package datastore
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
@@ -47,14 +47,14 @@ func init() {
|
|||||||
type RetentionScanner struct {
|
type RetentionScanner struct {
|
||||||
globalShutdown chan bool // Closes when Inbucket needs to shut down
|
globalShutdown chan bool // Closes when Inbucket needs to shut down
|
||||||
retentionShutdown chan bool // Closed after the scanner has shut down
|
retentionShutdown chan bool // Closed after the scanner has shut down
|
||||||
ds DataStore
|
ds Store
|
||||||
retentionPeriod time.Duration
|
retentionPeriod time.Duration
|
||||||
retentionSleep time.Duration
|
retentionSleep time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRetentionScanner launches a go-routine that scans for expired
|
// NewRetentionScanner launches a go-routine that scans for expired
|
||||||
// messages, following the configured interval
|
// messages, following the configured interval
|
||||||
func NewRetentionScanner(ds DataStore, shutdownChannel chan bool) *RetentionScanner {
|
func NewRetentionScanner(ds Store, shutdownChannel chan bool) *RetentionScanner {
|
||||||
cfg := config.GetDataStoreConfig()
|
cfg := config.GetDataStoreConfig()
|
||||||
rs := &RetentionScanner{
|
rs := &RetentionScanner{
|
||||||
globalShutdown: shutdownChannel,
|
globalShutdown: shutdownChannel,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package datastore
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Package datastore contains implementation independent datastore logic
|
// Package storage contains implementation independent datastore logic
|
||||||
package datastore
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -19,8 +19,8 @@ var (
|
|||||||
ErrNotWritable = errors.New("Message not writable")
|
ErrNotWritable = errors.New("Message not writable")
|
||||||
)
|
)
|
||||||
|
|
||||||
// DataStore is an interface to get Mailboxes stored in Inbucket
|
// Store is an interface to get Mailboxes stored in Inbucket
|
||||||
type DataStore interface {
|
type Store interface {
|
||||||
MailboxFor(emailAddress string) (Mailbox, error)
|
MailboxFor(emailAddress string) (Mailbox, error)
|
||||||
AllMailboxes() ([]Mailbox, error)
|
AllMailboxes() ([]Mailbox, error)
|
||||||
// LockFor is a temporary hack to fix #77 until Datastore revamp
|
// LockFor is a temporary hack to fix #77 until Datastore revamp
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package datastore
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ func MailboxShow(w http.ResponseWriter, req *http.Request, ctx *web.Context) (er
|
|||||||
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
msg, err := mb.GetMessage(id)
|
msg, err := mb.GetMessage(id)
|
||||||
if err == datastore.ErrNotExist {
|
if err == storage.ErrNotExist {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ func MailboxHTML(w http.ResponseWriter, req *http.Request, ctx *web.Context) (er
|
|||||||
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
message, err := mb.GetMessage(id)
|
message, err := mb.GetMessage(id)
|
||||||
if err == datastore.ErrNotExist {
|
if err == storage.ErrNotExist {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -191,7 +191,7 @@ func MailboxSource(w http.ResponseWriter, req *http.Request, ctx *web.Context) (
|
|||||||
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
message, err := mb.GetMessage(id)
|
message, err := mb.GetMessage(id)
|
||||||
if err == datastore.ErrNotExist {
|
if err == storage.ErrNotExist {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -237,7 +237,7 @@ func MailboxDownloadAttach(w http.ResponseWriter, req *http.Request, ctx *web.Co
|
|||||||
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
message, err := mb.GetMessage(id)
|
message, err := mb.GetMessage(id)
|
||||||
if err == datastore.ErrNotExist {
|
if err == storage.ErrNotExist {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -290,7 +290,7 @@ func MailboxViewAttach(w http.ResponseWriter, req *http.Request, ctx *web.Contex
|
|||||||
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
message, err := mb.GetMessage(id)
|
message, err := mb.GetMessage(id)
|
||||||
if err == datastore.ErrNotExist {
|
if err == storage.ErrNotExist {
|
||||||
http.NotFound(w, req)
|
http.NotFound(w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user