mirror of
https://gitlab.com/ric_harvey/MailHog.git
synced 2024-11-23 14:24:03 +00:00
Add session tests
This commit is contained in:
parent
fe4748f583
commit
cb5e79debb
4 changed files with 125 additions and 16 deletions
|
@ -1,6 +1,7 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/data"
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/storage"
|
||||
)
|
||||
|
||||
|
@ -22,7 +23,7 @@ type Config struct {
|
|||
MongoUri string
|
||||
MongoDb string
|
||||
MongoColl string
|
||||
MessageChan chan interface{}
|
||||
MessageChan chan *data.Message
|
||||
Storage storage.Storage
|
||||
Assets func(asset string) ([]byte, error)
|
||||
}
|
||||
|
|
|
@ -7,26 +7,27 @@ import (
|
|||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/config"
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/data"
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/smtp/protocol"
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/storage"
|
||||
)
|
||||
|
||||
// Session represents a SMTP session using net.TCPConn
|
||||
type Session struct {
|
||||
conn io.ReadWriteCloser
|
||||
proto *protocol.Protocol
|
||||
conf *config.Config
|
||||
storage storage.Storage
|
||||
messageChan chan *data.Message
|
||||
remoteAddress string
|
||||
isTLS bool
|
||||
line string
|
||||
}
|
||||
|
||||
// Accept starts a new SMTP session using io.ReadWriteCloser
|
||||
func Accept(remoteAddress string, conn io.ReadWriteCloser, conf *config.Config) {
|
||||
func Accept(remoteAddress string, conn io.ReadWriteCloser, storage storage.Storage, messageChan chan *data.Message, hostname string) {
|
||||
proto := protocol.NewProtocol()
|
||||
proto.Hostname = conf.Hostname
|
||||
session := &Session{conn, proto, conf, remoteAddress, false, ""}
|
||||
proto.Hostname = hostname
|
||||
session := &Session{conn, proto, storage, messageChan, remoteAddress, false, ""}
|
||||
proto.LogHandler = session.logf
|
||||
proto.MessageReceivedHandler = session.acceptMessage
|
||||
proto.ValidateSenderHandler = session.validateSender
|
||||
|
@ -54,8 +55,8 @@ func (c *Session) validateSender(from string) bool {
|
|||
|
||||
func (c *Session) acceptMessage(msg *data.Message) (id string, err error) {
|
||||
c.logf("Storing message %s", msg.ID)
|
||||
id, err = c.conf.Storage.Store(msg)
|
||||
c.conf.MessageChan <- msg
|
||||
id, err = c.storage.Store(msg)
|
||||
c.messageChan <- msg
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -72,8 +73,10 @@ func (c *Session) Read() bool {
|
|||
|
||||
if n == 0 {
|
||||
c.logf("Connection closed by remote host\n")
|
||||
io.Closer(c.conn).Close() // not sure this is necessary?
|
||||
return false
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.logf("Error reading from socket: %s\n", err)
|
||||
return false
|
||||
|
@ -86,13 +89,15 @@ func (c *Session) Read() bool {
|
|||
|
||||
c.line += text
|
||||
|
||||
line, reply := c.proto.Parse(c.line)
|
||||
c.line = line
|
||||
for strings.Contains(c.line, "\n") {
|
||||
line, reply := c.proto.Parse(c.line)
|
||||
c.line = line
|
||||
|
||||
if reply != nil {
|
||||
c.Write(reply)
|
||||
if reply.Status == 221 {
|
||||
io.Closer(c.conn).Close()
|
||||
if reply != nil {
|
||||
c.Write(reply)
|
||||
if reply.Status == 221 {
|
||||
io.Closer(c.conn).Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,107 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/data"
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/storage"
|
||||
)
|
||||
|
||||
type fakeRw struct {
|
||||
_read func(p []byte) (n int, err error)
|
||||
_write func(p []byte) (n int, err error)
|
||||
_close func() error
|
||||
}
|
||||
|
||||
func (rw *fakeRw) Read(p []byte) (n int, err error) {
|
||||
if rw._read != nil {
|
||||
return rw._read(p)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
func (rw *fakeRw) Close() error {
|
||||
if rw._close != nil {
|
||||
return rw._close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (rw *fakeRw) Write(p []byte) (n int, err error) {
|
||||
if rw._write != nil {
|
||||
return rw._write(p)
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func TestAccept(t *testing.T) {
|
||||
Convey("Accept should handle a connection", t, func() {
|
||||
frw := &fakeRw{}
|
||||
mChan := make(chan *data.Message)
|
||||
Accept("1.1.1.1:11111", frw, storage.CreateInMemory(), mChan, "localhost")
|
||||
})
|
||||
}
|
||||
|
||||
func TestSocketError(t *testing.T) {
|
||||
Convey("Socket errors should return from Accept", t, func() {
|
||||
frw := &fakeRw{
|
||||
_read: func(p []byte) (n int, err error) {
|
||||
return -1, errors.New("OINK")
|
||||
},
|
||||
}
|
||||
mChan := make(chan *data.Message)
|
||||
Accept("1.1.1.1:11111", frw, storage.CreateInMemory(), mChan, "localhost")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAcceptMessage(t *testing.T) {
|
||||
Convey("acceptMessage should be called", t, func() {
|
||||
mbuf := "EHLO localhost\nMAIL FROM:<test>\nRCPT TO:<test>\nDATA\nHi.\r\n.\r\nQUIT\n"
|
||||
var rbuf []byte
|
||||
frw := &fakeRw{
|
||||
_read: func(p []byte) (n int, err error) {
|
||||
if len(p) >= len(mbuf) {
|
||||
ba := []byte(mbuf)
|
||||
mbuf = ""
|
||||
for i, b := range ba {
|
||||
p[i] = b
|
||||
}
|
||||
return len(ba), nil
|
||||
}
|
||||
|
||||
ba := []byte(mbuf[0:len(p)])
|
||||
mbuf = mbuf[len(p):]
|
||||
for i, b := range ba {
|
||||
p[i] = b
|
||||
}
|
||||
return len(ba), nil
|
||||
},
|
||||
_write: func(p []byte) (n int, err error) {
|
||||
rbuf = append(rbuf, p...)
|
||||
return len(p), nil
|
||||
},
|
||||
_close: func() error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
mChan := make(chan *data.Message)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
handlerCalled := false
|
||||
go func() {
|
||||
handlerCalled = true
|
||||
m := <-mChan
|
||||
So(m, ShouldNotBeNil)
|
||||
wg.Done()
|
||||
}()
|
||||
Accept("1.1.1.1:11111", frw, storage.CreateInMemory(), mChan, "localhost")
|
||||
wg.Wait()
|
||||
So(handlerCalled, ShouldBeTrue)
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidateAuthentication(t *testing.T) {
|
||||
Convey("validateAuthentication is always successful", t, func() {
|
||||
c := &Session{}
|
||||
|
|
11
main.go
11
main.go
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/config"
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/data"
|
||||
mhhttp "github.com/ian-kent/Go-MailHog/mailhog/http"
|
||||
"github.com/ian-kent/Go-MailHog/mailhog/http/api"
|
||||
smtp "github.com/ian-kent/Go-MailHog/mailhog/smtp/server"
|
||||
|
@ -42,7 +43,7 @@ func configure() {
|
|||
MongoDb: mongodb,
|
||||
MongoColl: mongocoll,
|
||||
Assets: Asset,
|
||||
MessageChan: make(chan interface{}),
|
||||
MessageChan: make(chan *data.Message),
|
||||
}
|
||||
|
||||
if storage_type == "mongodb" {
|
||||
|
@ -123,6 +124,12 @@ func smtp_listen() *net.TCPListener {
|
|||
}
|
||||
defer conn.Close()
|
||||
|
||||
go smtp.Accept(conn.(*net.TCPConn).RemoteAddr().String(), io.ReadWriteCloser(conn), conf)
|
||||
go smtp.Accept(
|
||||
conn.(*net.TCPConn).RemoteAddr().String(),
|
||||
io.ReadWriteCloser(conn),
|
||||
conf.Storage,
|
||||
conf.MessageChan,
|
||||
conf.Hostname,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue