mirror of
https://gitlab.com/ric_harvey/MailHog.git
synced 2024-11-27 16:24:04 +00:00
update storage
This commit is contained in:
parent
d4927bc7e6
commit
50802a0753
6 changed files with 4 additions and 515 deletions
184
vendor/github.com/mailhog/storage/maildir.go
generated
vendored
184
vendor/github.com/mailhog/storage/maildir.go
generated
vendored
|
@ -1,184 +0,0 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/mailhog/data"
|
||||
)
|
||||
|
||||
// Maildir is a maildir storage backend
|
||||
type Maildir struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// CreateMaildir creates a new maildir storage backend
|
||||
func CreateMaildir(path string) *Maildir {
|
||||
if len(path) == 0 {
|
||||
dir, err := ioutil.TempDir("", "mailhog")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
path = dir
|
||||
}
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
err := os.MkdirAll(path, 0770)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
log.Println("Maildir path is", path)
|
||||
return &Maildir{
|
||||
Path: path,
|
||||
}
|
||||
}
|
||||
|
||||
// Store stores a message and returns its storage ID
|
||||
func (maildir *Maildir) Store(m *data.Message) (string, error) {
|
||||
b, err := ioutil.ReadAll(m.Raw.Bytes())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(maildir.Path, string(m.ID)), b, 0660)
|
||||
return string(m.ID), err
|
||||
}
|
||||
|
||||
// Count returns the number of stored messages
|
||||
func (maildir *Maildir) Count() int {
|
||||
// FIXME may be wrong, ../. ?
|
||||
// and handle error?
|
||||
dir, err := os.Open(maildir.Path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer dir.Close()
|
||||
n, _ := dir.Readdirnames(0)
|
||||
return len(n)
|
||||
}
|
||||
|
||||
// Search finds messages matching the query
|
||||
func (maildir *Maildir) Search(kind, query string, start, limit int) (*data.Messages, int, error) {
|
||||
query = strings.ToLower(query)
|
||||
var filteredMessages = make([]data.Message, 0)
|
||||
|
||||
var matched int
|
||||
|
||||
err := filepath.Walk(maildir.Path, func(path string, info os.FileInfo, err error) error {
|
||||
if limit > 0 && len(filteredMessages) >= limit {
|
||||
return errors.New("reached limit")
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
msg, err := maildir.Load(info.Name())
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case "to":
|
||||
for _, t := range msg.To {
|
||||
if strings.Contains(strings.ToLower(t.Mailbox+"@"+t.Domain), query) {
|
||||
if start > matched {
|
||||
matched++
|
||||
break
|
||||
}
|
||||
filteredMessages = append(filteredMessages, *msg)
|
||||
break
|
||||
}
|
||||
}
|
||||
case "from":
|
||||
if strings.Contains(strings.ToLower(msg.From.Mailbox+"@"+msg.From.Domain), query) {
|
||||
if start > matched {
|
||||
matched++
|
||||
break
|
||||
}
|
||||
filteredMessages = append(filteredMessages, *msg)
|
||||
}
|
||||
case "containing":
|
||||
if strings.Contains(strings.ToLower(msg.Raw.Data), query) {
|
||||
if start > matched {
|
||||
matched++
|
||||
break
|
||||
}
|
||||
filteredMessages = append(filteredMessages, *msg)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
msgs := data.Messages(filteredMessages)
|
||||
return &msgs, len(filteredMessages), nil
|
||||
}
|
||||
|
||||
// List lists stored messages by index
|
||||
func (maildir *Maildir) List(start, limit int) (*data.Messages, error) {
|
||||
log.Println("Listing messages in", maildir.Path)
|
||||
messages := make([]data.Message, 0)
|
||||
|
||||
dir, err := os.Open(maildir.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
n, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, fileinfo := range n {
|
||||
b, err := ioutil.ReadFile(filepath.Join(maildir.Path, fileinfo.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg := data.FromBytes(b)
|
||||
// FIXME domain
|
||||
m := *msg.Parse("mailhog.example")
|
||||
m.ID = data.MessageID(fileinfo.Name())
|
||||
m.Created = fileinfo.ModTime()
|
||||
messages = append(messages, m)
|
||||
}
|
||||
|
||||
log.Printf("Found %d messages", len(messages))
|
||||
msgs := data.Messages(messages)
|
||||
return &msgs, nil
|
||||
}
|
||||
|
||||
// DeleteOne deletes an individual message by storage ID
|
||||
func (maildir *Maildir) DeleteOne(id string) error {
|
||||
return os.Remove(filepath.Join(maildir.Path, id))
|
||||
}
|
||||
|
||||
// DeleteAll deletes all in memory messages
|
||||
func (maildir *Maildir) DeleteAll() error {
|
||||
err := os.RemoveAll(maildir.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Mkdir(maildir.Path, 0770)
|
||||
}
|
||||
|
||||
// Load returns an individual message by storage ID
|
||||
func (maildir *Maildir) Load(id string) (*data.Message, error) {
|
||||
b, err := ioutil.ReadFile(filepath.Join(maildir.Path, id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// FIXME domain
|
||||
m := data.FromBytes(b).Parse("mailhog.example")
|
||||
m.ID = data.MessageID(id)
|
||||
return m, nil
|
||||
}
|
191
vendor/github.com/mailhog/storage/memory.go
generated
vendored
191
vendor/github.com/mailhog/storage/memory.go
generated
vendored
|
@ -1,191 +0,0 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/mailhog/data"
|
||||
)
|
||||
|
||||
// InMemory is an in memory storage backend
|
||||
type InMemory struct {
|
||||
MessageIDIndex map[string]int
|
||||
Messages []*data.Message
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// CreateInMemory creates a new in memory storage backend
|
||||
func CreateInMemory() *InMemory {
|
||||
return &InMemory{
|
||||
MessageIDIndex: make(map[string]int),
|
||||
Messages: make([]*data.Message, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// Store stores a message and returns its storage ID
|
||||
func (memory *InMemory) Store(m *data.Message) (string, error) {
|
||||
memory.mu.Lock()
|
||||
defer memory.mu.Unlock()
|
||||
memory.Messages = append(memory.Messages, m)
|
||||
memory.MessageIDIndex[string(m.ID)] = len(memory.Messages) - 1
|
||||
return string(m.ID), nil
|
||||
}
|
||||
|
||||
// Count returns the number of stored messages
|
||||
func (memory *InMemory) Count() int {
|
||||
return len(memory.Messages)
|
||||
}
|
||||
|
||||
// Search finds messages matching the query
|
||||
func (memory *InMemory) Search(kind, query string, start, limit int) (*data.Messages, int, error) {
|
||||
// FIXME needs optimising, or replacing with a proper db!
|
||||
query = strings.ToLower(query)
|
||||
var filteredMessages = make([]*data.Message, 0)
|
||||
for _, m := range memory.Messages {
|
||||
doAppend := false
|
||||
|
||||
switch kind {
|
||||
case "to":
|
||||
for _, to := range m.To {
|
||||
if strings.Contains(strings.ToLower(to.Mailbox+"@"+to.Domain), query) {
|
||||
doAppend = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !doAppend {
|
||||
if hdr, ok := m.Content.Headers["To"]; ok {
|
||||
for _, to := range hdr {
|
||||
if strings.Contains(strings.ToLower(to), query) {
|
||||
doAppend = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case "from":
|
||||
if strings.Contains(strings.ToLower(m.From.Mailbox+"@"+m.From.Domain), query) {
|
||||
doAppend = true
|
||||
}
|
||||
if !doAppend {
|
||||
if hdr, ok := m.Content.Headers["From"]; ok {
|
||||
for _, from := range hdr {
|
||||
if strings.Contains(strings.ToLower(from), query) {
|
||||
doAppend = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case "containing":
|
||||
if strings.Contains(strings.ToLower(m.Content.Body), query) {
|
||||
doAppend = true
|
||||
}
|
||||
if !doAppend {
|
||||
for _, hdr := range m.Content.Headers {
|
||||
for _, v := range hdr {
|
||||
if strings.Contains(strings.ToLower(v), query) {
|
||||
doAppend = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if doAppend {
|
||||
filteredMessages = append(filteredMessages, m)
|
||||
}
|
||||
}
|
||||
|
||||
var messages = make([]data.Message, 0)
|
||||
|
||||
if len(filteredMessages) == 0 || start > len(filteredMessages) {
|
||||
msgs := data.Messages(messages)
|
||||
return &msgs, 0, nil
|
||||
}
|
||||
|
||||
if start+limit > len(filteredMessages) {
|
||||
limit = len(filteredMessages) - start
|
||||
}
|
||||
|
||||
start = len(filteredMessages) - start - 1
|
||||
end := start - limit
|
||||
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if end < -1 {
|
||||
end = -1
|
||||
}
|
||||
|
||||
for i := start; i > end; i-- {
|
||||
//for _, m := range memory.MessageIndex[start:end] {
|
||||
messages = append(messages, *filteredMessages[i])
|
||||
}
|
||||
|
||||
msgs := data.Messages(messages)
|
||||
return &msgs, len(filteredMessages), nil
|
||||
}
|
||||
|
||||
// List lists stored messages by index
|
||||
func (memory *InMemory) List(start int, limit int) (*data.Messages, error) {
|
||||
var messages = make([]data.Message, 0)
|
||||
|
||||
if len(memory.Messages) == 0 || start > len(memory.Messages) {
|
||||
msgs := data.Messages(messages)
|
||||
return &msgs, nil
|
||||
}
|
||||
|
||||
if start+limit > len(memory.Messages) {
|
||||
limit = len(memory.Messages) - start
|
||||
}
|
||||
|
||||
start = len(memory.Messages) - start - 1
|
||||
end := start - limit
|
||||
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if end < -1 {
|
||||
end = -1
|
||||
}
|
||||
|
||||
for i := start; i > end; i-- {
|
||||
//for _, m := range memory.MessageIndex[start:end] {
|
||||
messages = append(messages, *memory.Messages[i])
|
||||
}
|
||||
|
||||
msgs := data.Messages(messages)
|
||||
return &msgs, nil
|
||||
}
|
||||
|
||||
// DeleteOne deletes an individual message by storage ID
|
||||
func (memory *InMemory) DeleteOne(id string) error {
|
||||
memory.mu.Lock()
|
||||
defer memory.mu.Unlock()
|
||||
index := memory.MessageIDIndex[id]
|
||||
delete(memory.MessageIDIndex, id)
|
||||
for k, v := range memory.MessageIDIndex {
|
||||
if v > index {
|
||||
memory.MessageIDIndex[k] = v - 1
|
||||
}
|
||||
}
|
||||
memory.Messages = append(memory.Messages[:index], memory.Messages[index+1:]...)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAll deletes all in memory messages
|
||||
func (memory *InMemory) DeleteAll() error {
|
||||
memory.mu.Lock()
|
||||
defer memory.mu.Unlock()
|
||||
memory.Messages = make([]*data.Message, 0)
|
||||
memory.MessageIDIndex = make(map[string]int)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load returns an individual message by storage ID
|
||||
func (memory *InMemory) Load(id string) (*data.Message, error) {
|
||||
if idx, ok := memory.MessageIDIndex[id]; ok {
|
||||
return memory.Messages[idx], nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
122
vendor/github.com/mailhog/storage/mongodb.go
generated
vendored
122
vendor/github.com/mailhog/storage/mongodb.go
generated
vendored
|
@ -1,122 +0,0 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"log"
|
||||
"github.com/mailhog/data"
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
// MongoDB represents MongoDB backed storage backend
|
||||
type MongoDB struct {
|
||||
Session *mgo.Session
|
||||
Collection *mgo.Collection
|
||||
}
|
||||
|
||||
// CreateMongoDB creates a MongoDB backed storage backend
|
||||
func CreateMongoDB(uri, db, coll string) *MongoDB {
|
||||
log.Printf("Connecting to MongoDB: %s\n", uri)
|
||||
session, err := mgo.Dial(uri)
|
||||
if err != nil {
|
||||
log.Printf("Error connecting to MongoDB: %s", err)
|
||||
return nil
|
||||
}
|
||||
err = session.DB(db).C(coll).EnsureIndexKey("created")
|
||||
if err != nil {
|
||||
log.Printf("Failed creating index: %s", err)
|
||||
return nil
|
||||
}
|
||||
return &MongoDB{
|
||||
Session: session,
|
||||
Collection: session.DB(db).C(coll),
|
||||
}
|
||||
}
|
||||
|
||||
// Store stores a message in MongoDB and returns its storage ID
|
||||
func (mongo *MongoDB) Store(m *data.Message) (string, error) {
|
||||
err := mongo.Collection.Insert(m)
|
||||
if err != nil {
|
||||
log.Printf("Error inserting message: %s", err)
|
||||
return "", err
|
||||
}
|
||||
return string(m.ID), nil
|
||||
}
|
||||
|
||||
// Count returns the number of stored messages
|
||||
func (mongo *MongoDB) Count() int {
|
||||
c, _ := mongo.Collection.Count()
|
||||
return c
|
||||
}
|
||||
|
||||
// Search finds messages matching the query
|
||||
func (mongo *MongoDB) Search(kind, query string, start, limit int) (*data.Messages, int, error) {
|
||||
messages := &data.Messages{}
|
||||
var count = 0
|
||||
var field = "raw.data"
|
||||
switch kind {
|
||||
case "to":
|
||||
field = "raw.to"
|
||||
case "from":
|
||||
field = "raw.from"
|
||||
}
|
||||
err := mongo.Collection.Find(bson.M{field: bson.RegEx{Pattern: query, Options: "i"}}).Skip(start).Limit(limit).Sort("-created").Select(bson.M{
|
||||
"id": 1,
|
||||
"_id": 1,
|
||||
"from": 1,
|
||||
"to": 1,
|
||||
"content.headers": 1,
|
||||
"content.size": 1,
|
||||
"created": 1,
|
||||
"raw": 1,
|
||||
}).All(messages)
|
||||
if err != nil {
|
||||
log.Printf("Error loading messages: %s", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
count, _ = mongo.Collection.Find(bson.M{field: bson.RegEx{Pattern: query, Options: "i"}}).Count()
|
||||
|
||||
return messages, count, nil
|
||||
}
|
||||
|
||||
// List returns a list of messages by index
|
||||
func (mongo *MongoDB) List(start int, limit int) (*data.Messages, error) {
|
||||
messages := &data.Messages{}
|
||||
err := mongo.Collection.Find(bson.M{}).Skip(start).Limit(limit).Sort("-created").Select(bson.M{
|
||||
"id": 1,
|
||||
"_id": 1,
|
||||
"from": 1,
|
||||
"to": 1,
|
||||
"content.headers": 1,
|
||||
"content.size": 1,
|
||||
"created": 1,
|
||||
"raw": 1,
|
||||
}).All(messages)
|
||||
if err != nil {
|
||||
log.Printf("Error loading messages: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// DeleteOne deletes an individual message by storage ID
|
||||
func (mongo *MongoDB) DeleteOne(id string) error {
|
||||
_, err := mongo.Collection.RemoveAll(bson.M{"id": id})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteAll deletes all messages stored in MongoDB
|
||||
func (mongo *MongoDB) DeleteAll() error {
|
||||
_, err := mongo.Collection.RemoveAll(bson.M{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Load loads an individual message by storage ID
|
||||
func (mongo *MongoDB) Load(id string) (*data.Message, error) {
|
||||
result := &data.Message{}
|
||||
err := mongo.Collection.Find(bson.M{"id": id}).One(&result)
|
||||
if err != nil {
|
||||
log.Printf("Error loading message: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
14
vendor/github.com/mailhog/storage/storage.go
generated
vendored
14
vendor/github.com/mailhog/storage/storage.go
generated
vendored
|
@ -1,14 +0,0 @@
|
|||
package storage
|
||||
|
||||
import "github.com/mailhog/data"
|
||||
|
||||
// Storage represents a storage backend
|
||||
type Storage interface {
|
||||
Store(m *data.Message) (string, error)
|
||||
List(start, limit int) (*data.Messages, error)
|
||||
Search(kind, query string, start, limit int) (*data.Messages, int, error)
|
||||
Count() int
|
||||
DeleteOne(id string) error
|
||||
DeleteAll() error
|
||||
Load(id string) (*data.Message, error)
|
||||
}
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
@ -147,10 +147,10 @@
|
|||
"revisionTime": "2016-11-19T23:01:07Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Kd53/4cZ1KNfatXBgCg4VWzowis=",
|
||||
"checksumSHA1": "bnVk1LzeVwAk47vHdu1jU6KZQZU=",
|
||||
"path": "github.com/mailhog/storage",
|
||||
"revision": "970ad63c574405c1d31aade44081611047343c77",
|
||||
"revisionTime": "2017-04-16T18:53:22Z"
|
||||
"revision": "295f257171af29ea8ee6411a9a0ee3cc04338482",
|
||||
"revisionTime": "2017-04-16T22:26:00Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "mbhJnsNwGAwkTQH5c2hVRO9YmxA=",
|
||||
|
|
Loading…
Reference in a new issue