Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"reflect"
"strings"
"text/template"
"time"

"github.com/phires/go-guerrilla/backends"
Expand Down Expand Up @@ -60,6 +61,9 @@ type ServerConfig struct {
// XClientOn when using a proxy such as Nginx, XCLIENT command is used to pass the
// original client's IP address & client's HELO
XClientOn bool `json:"xclient_on,omitempty"`
// GreeterTemplate will be used to greet the client.
// Defaults to defaultGreeterString
GreeterTemplate *template.Template `json:"greeter_template"`
}

type ServerTLSConfig struct {
Expand Down Expand Up @@ -151,10 +155,13 @@ var TLSClientAuthTypes = map[string]tls.ClientAuthType{
"RequireAndVerifyClientCert": tls.RequireAndVerifyClientCert,
}

const defaultMaxClients = 100
const defaultTimeout = 30
const defaultInterface = "127.0.0.1:2525"
const defaultMaxSize = int64(10 << 20) // 10 Mebibytes
const (
defaultMaxClients = 100
defaultTimeout = 30
defaultInterface = "127.0.0.1:2525"
defaultMaxSize = int64(10 << 20) // 10 Mebibytes
defaultGreeterString = "220 {{ .Hostname }} SMTP Guerrilla({{ .Version }}) #{{ .ClientID }} ({{ .ActiveClientsCount }}) {{ .Time }}"
)

// Unmarshalls json data into AppConfig struct and any other initialization of the struct
// also does validation, returns error if validation failed or something went wrong
Expand Down Expand Up @@ -279,6 +286,10 @@ func (c *AppConfig) setDefaults() error {
if err != nil {
return err
}
defaultGreeterTemplate, err := template.New("greeter").Parse(defaultGreeterString)
if err != nil {
return fmt.Errorf("unable to parse template: %v", err)
}
if len(c.Servers) == 0 {
sc := ServerConfig{}
sc.LogFile = c.LogFile
Expand All @@ -288,6 +299,7 @@ func (c *AppConfig) setDefaults() error {
sc.MaxClients = defaultMaxClients
sc.Timeout = defaultTimeout
sc.MaxSize = defaultMaxSize
sc.GreeterTemplate = defaultGreeterTemplate
c.Servers = append(c.Servers, sc)
} else {
// make sure each server has defaults correctly configured
Expand All @@ -304,6 +316,9 @@ func (c *AppConfig) setDefaults() error {
if c.Servers[i].MaxSize == 0 {
c.Servers[i].MaxSize = defaultMaxSize // 10 Mebibytes
}
if c.Servers[i].GreeterTemplate == nil {
c.Servers[i].GreeterTemplate = defaultGreeterTemplate
}
if c.Servers[i].ListenInterface == "" {
return fmt.Errorf("listen interface not specified for server at index %d", i)
}
Expand Down
23 changes: 19 additions & 4 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ type allowedHosts struct {
sync.Mutex // guard access to the map
}

type greeterData struct {
Hostname string
Version string
ClientID uint64
ActiveClientsCount int
Time string
}

type command []byte

var (
Expand Down Expand Up @@ -368,9 +376,16 @@ func (s *server) handleClient(client *client) {
s.log().Infof("Handle client [%s], id: %d", client.RemoteIP, client.ID)

// Initial greeting
greeting := fmt.Sprintf("220 %s SMTP Guerrilla(%s) #%d (%d) %s",
sc.Hostname, Version, client.ID,
s.clientPool.GetActiveClientsCount(), time.Now().Format(time.RFC3339))
greeterData := greeterData{
Hostname: sc.Hostname,
Version: Version,
ClientID: client.ID,
ActiveClientsCount: s.clientPool.GetActiveClientsCount(),
Time: time.Now().Format(time.RFC3339),
}

var greeting bytes.Buffer
sc.GreeterTemplate.Execute(&greeting, greeterData)

helo := fmt.Sprintf("250 %s Hello", sc.Hostname)
// ehlo is a multi-line reply and need additional \r\n at the end
Expand Down Expand Up @@ -405,7 +420,7 @@ func (s *server) handleClient(client *client) {
for client.isAlive() {
switch client.state {
case ClientGreeting:
client.sendResponse(greeting)
client.sendResponse(greeting.String())
client.state = ClientCmd
case ClientCmd:
client.bufin.setLimit(CommandLineMaxLength)
Expand Down