mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-18 18:17:03 +00:00
Mixed use support
You can now optionally configure a "no store" domain. When inbucket receives a message destined for a user at that domain, it will accept the message but not store it to disk. This allows the same instance of Inbucket to be shared by people who wish to view email content and those who want to load test.
This commit is contained in:
@@ -15,6 +15,7 @@ type SmtpConfig struct {
|
|||||||
Ip4address net.IP
|
Ip4address net.IP
|
||||||
Ip4port int
|
Ip4port int
|
||||||
Domain string
|
Domain string
|
||||||
|
DomainNoStore string
|
||||||
MaxRecipients int
|
MaxRecipients int
|
||||||
MaxIdleSeconds int
|
MaxIdleSeconds int
|
||||||
MaxMessageBytes int
|
MaxMessageBytes int
|
||||||
@@ -177,6 +178,15 @@ func parseSmtpConfig() error {
|
|||||||
}
|
}
|
||||||
smtpConfig.Domain = str
|
smtpConfig.Domain = str
|
||||||
|
|
||||||
|
option = "domain.nostore"
|
||||||
|
if Config.HasOption(section, option) {
|
||||||
|
str, err = Config.String(section, option)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||||
|
}
|
||||||
|
smtpConfig.DomainNoStore = str
|
||||||
|
}
|
||||||
|
|
||||||
option = "max.recipients"
|
option = "max.recipients"
|
||||||
smtpConfig.MaxRecipients, err = Config.Int(section, option)
|
smtpConfig.MaxRecipients, err = Config.Int(section, option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ ip4.port=2500
|
|||||||
# used in SMTP greeting
|
# used in SMTP greeting
|
||||||
domain=inbucket.local
|
domain=inbucket.local
|
||||||
|
|
||||||
|
# optional: mail sent to accounts at this domain will not be stored,
|
||||||
|
# for mixed use (content and load testing)
|
||||||
|
domain.nostore=bitbucket.local
|
||||||
|
|
||||||
# Maximum number of RCPT TO: addresses we allow from clients, the SMTP
|
# Maximum number of RCPT TO: addresses we allow from clients, the SMTP
|
||||||
# RFC recommends this be at least 100.
|
# RFC recommends this be at least 100.
|
||||||
max.recipients=100
|
max.recipients=100
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ ip4.port=2500
|
|||||||
# used in SMTP greeting
|
# used in SMTP greeting
|
||||||
domain=inbucket.local
|
domain=inbucket.local
|
||||||
|
|
||||||
|
# optional: mail sent to accounts at this domain will not be stored,
|
||||||
|
# for mixed use (content and load testing)
|
||||||
|
#domain.nostore=bitbucket.local
|
||||||
|
|
||||||
# Maximum number of RCPT TO: addresses we allow from clients, the SMTP
|
# Maximum number of RCPT TO: addresses we allow from clients, the SMTP
|
||||||
# RFC recommends this be at least 100.
|
# RFC recommends this be at least 100.
|
||||||
max.recipients=100
|
max.recipients=100
|
||||||
|
|||||||
@@ -300,6 +300,8 @@ func (ss *Session) dataHandler() {
|
|||||||
i := 0
|
i := 0
|
||||||
for e := ss.recipients.Front(); e != nil; e = e.Next() {
|
for e := ss.recipients.Front(); e != nil; e = e.Next() {
|
||||||
recip := e.Value.(string)
|
recip := e.Value.(string)
|
||||||
|
if !strings.HasSuffix(strings.ToLower(recip), "@" + ss.server.domainNoStore) {
|
||||||
|
// Not our "no store" domain, so store the message
|
||||||
mb, err := ss.server.dataStore.MailboxFor(recip)
|
mb, err := ss.server.dataStore.MailboxFor(recip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ss.error("Failed to open mailbox for %v", recip)
|
ss.error("Failed to open mailbox for %v", recip)
|
||||||
@@ -309,6 +311,9 @@ func (ss *Session) dataHandler() {
|
|||||||
}
|
}
|
||||||
mailboxes[i] = mb
|
mailboxes[i] = mb
|
||||||
messages[i] = mb.NewMessage()
|
messages[i] = mb.NewMessage()
|
||||||
|
} else {
|
||||||
|
log.Trace("Not storing message for '%v'", recip)
|
||||||
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,9 +338,11 @@ func (ss *Session) dataHandler() {
|
|||||||
// Mail data complete
|
// Mail data complete
|
||||||
if ss.server.storeMessages {
|
if ss.server.storeMessages {
|
||||||
for _, m := range messages {
|
for _, m := range messages {
|
||||||
|
if m != nil {
|
||||||
m.Close()
|
m.Close()
|
||||||
expDeliveredTotal.Add(1)
|
expDeliveredTotal.Add(1)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
expDeliveredTotal.Add(1)
|
expDeliveredTotal.Add(1)
|
||||||
}
|
}
|
||||||
@@ -360,6 +367,7 @@ func (ss *Session) dataHandler() {
|
|||||||
// Append to message objects
|
// Append to message objects
|
||||||
if ss.server.storeMessages {
|
if ss.server.storeMessages {
|
||||||
for i, m := range messages {
|
for i, m := range messages {
|
||||||
|
if m != nil {
|
||||||
if err := m.Append(line); err != nil {
|
if err := m.Append(line); err != nil {
|
||||||
ss.error("Failed to append to mailbox %v: %v", mailboxes[i], err)
|
ss.error("Failed to append to mailbox %v: %v", mailboxes[i], err)
|
||||||
ss.send("554 Something went wrong")
|
ss.send("554 Something went wrong")
|
||||||
@@ -370,6 +378,7 @@ func (ss *Session) dataHandler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *Session) enterState(state State) {
|
func (ss *Session) enterState(state State) {
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ import (
|
|||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/config"
|
||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/log"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Real server code starts here
|
// Real server code starts here
|
||||||
type Server struct {
|
type Server struct {
|
||||||
domain string
|
domain string
|
||||||
|
domainNoStore string
|
||||||
maxRecips int
|
maxRecips int
|
||||||
maxIdleSeconds int
|
maxIdleSeconds int
|
||||||
maxMessageBytes int
|
maxMessageBytes int
|
||||||
@@ -45,7 +47,7 @@ func New() *Server {
|
|||||||
cfg := config.GetSmtpConfig()
|
cfg := config.GetSmtpConfig()
|
||||||
return &Server{dataStore: ds, domain: cfg.Domain, maxRecips: cfg.MaxRecipients,
|
return &Server{dataStore: ds, domain: cfg.Domain, maxRecips: cfg.MaxRecipients,
|
||||||
maxIdleSeconds: cfg.MaxIdleSeconds, maxMessageBytes: cfg.MaxMessageBytes,
|
maxIdleSeconds: cfg.MaxIdleSeconds, maxMessageBytes: cfg.MaxMessageBytes,
|
||||||
storeMessages: cfg.StoreMessages}
|
storeMessages: cfg.StoreMessages, domainNoStore: strings.ToLower(cfg.DomainNoStore)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main listener loop
|
// Main listener loop
|
||||||
@@ -69,6 +71,8 @@ func (s *Server) Start() {
|
|||||||
|
|
||||||
if !s.storeMessages {
|
if !s.storeMessages {
|
||||||
log.Info("Load test mode active, messages will not be stored")
|
log.Info("Load test mode active, messages will not be stored")
|
||||||
|
} else if s.domainNoStore != "" {
|
||||||
|
log.Info("Messages sent to domain '%v' will be discarded", s.domainNoStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start retention scanner
|
// Start retention scanner
|
||||||
|
|||||||
Reference in New Issue
Block a user