Add sender/recipient validate hooks

This commit is contained in:
Ian Kent 2014-11-22 19:20:47 +00:00
parent 6db4e904be
commit 256849f2c6
2 changed files with 26 additions and 3 deletions

View file

@ -23,8 +23,10 @@ type Protocol struct {
message *data.SMTPMessage message *data.SMTPMessage
hostname string hostname string
LogHandler func(message string, args ...interface{}) LogHandler func(message string, args ...interface{})
MessageReceivedHandler func(*data.Message) (string, error) MessageReceivedHandler func(*data.Message) (string, error)
ValidateSenderHandler func(from string) bool
ValidateRecipientHandler func(to string) bool
} }
// NewProtocol returns a new SMTP state machine in INVALID state // NewProtocol returns a new SMTP state machine in INVALID state
@ -85,7 +87,6 @@ func (proto *Protocol) Parse(line string) (string, *Reply) {
// ProcessData handles content received (with newlines stripped) while // ProcessData handles content received (with newlines stripped) while
// in the SMTP DATA state // in the SMTP DATA state
func (proto *Protocol) ProcessData(line string) (reply *Reply) { func (proto *Protocol) ProcessData(line string) (reply *Reply) {
proto.message.Data += line + "\n" proto.message.Data += line + "\n"
if strings.HasSuffix(proto.message.Data, "\r\n.\r\n") { if strings.HasSuffix(proto.message.Data, "\r\n.\r\n") {
@ -191,6 +192,12 @@ func (proto *Protocol) Command(command *Command) (reply *Reply) {
if err != nil { if err != nil {
return ReplyError(err) return ReplyError(err)
} }
if proto.ValidateSenderHandler != nil {
if !proto.ValidateSenderHandler(from) {
// TODO correct sender error response
return ReplyError(errors.New("Invalid sender " + from))
}
}
proto.message.From = from proto.message.From = from
proto.state = RCPT proto.state = RCPT
return ReplySenderOk(from) return ReplySenderOk(from)
@ -210,6 +217,12 @@ func (proto *Protocol) Command(command *Command) (reply *Reply) {
if err != nil { if err != nil {
return ReplyError(err) return ReplyError(err)
} }
if proto.ValidateRecipientHandler != nil {
if !proto.ValidateRecipientHandler(to) {
// TODO correct send error response
return ReplyError(errors.New("Invalid recipient " + to))
}
}
proto.message.To = append(proto.message.To, to) proto.message.To = append(proto.message.To, to)
proto.state = RCPT proto.state = RCPT
return ReplyRecipientOk(to) return ReplyRecipientOk(to)

View file

@ -29,6 +29,8 @@ func Accept(conn *net.TCPConn, conf *config.Config) {
session := &Session{conn, proto, conf, false, ""} session := &Session{conn, proto, conf, false, ""}
proto.LogHandler = session.logf proto.LogHandler = session.logf
proto.MessageReceivedHandler = session.acceptMessageHandler proto.MessageReceivedHandler = session.acceptMessageHandler
proto.ValidateSenderHandler = session.validateSender
proto.ValidateRecipientHandler = session.validateRecipient
session.logf("Starting session") session.logf("Starting session")
session.Write(proto.Start(conf.Hostname)) session.Write(proto.Start(conf.Hostname))
@ -37,6 +39,14 @@ func Accept(conn *net.TCPConn, conf *config.Config) {
session.logf("Session ended") session.logf("Session ended")
} }
func (c *Session) validateRecipient(to string) bool {
return true
}
func (c *Session) validateSender(from string) bool {
return true
}
func (c *Session) acceptMessageHandler(msg *data.Message) (id string, err error) { func (c *Session) acceptMessageHandler(msg *data.Message) (id string, err error) {
switch c.conf.Storage.(type) { switch c.conf.Storage.(type) {
case *storage.MongoDB: case *storage.MongoDB: