Browse Source

Code cleanup (#171)

code cleanup #171
Till 6 years ago
parent
commit
b803e062a6
20 changed files with 121 additions and 123 deletions
  1. 3 3
      api.go
  2. 11 11
      api_test.go
  3. 5 5
      backends/gateway.go
  4. 7 7
      client.go
  5. 9 9
      cmd/guerrillad/serve_test.go
  6. 31 36
      config.go
  7. 1 1
      config_test.go
  8. 4 0
      guerrilla.go
  9. 1 0
      guerrilla_unix.go
  10. 8 6
      log/hook.go
  11. 5 5
      log/log.go
  12. 7 7
      mail/envelope.go
  13. 8 11
      mail/rfc5321/parse.go
  14. 0 2
      mocks/client.go
  15. 1 2
      response/quote.go
  16. 7 7
      server.go
  17. 6 5
      server_test.go
  18. 1 1
      tests/client.go
  19. 2 2
      tests/guerrilla_test.go
  20. 4 3
      version.go

+ 3 - 3
api.go

@@ -127,10 +127,10 @@ func (d *Daemon) ReloadConfig(c AppConfig) error {
 	if err != nil {
 	if err != nil {
 		d.Log().WithError(err).Error("Error while reloading config")
 		d.Log().WithError(err).Error("Error while reloading config")
 		return err
 		return err
-	} else {
-		d.Log().Infof("Configuration was reloaded at %s", d.configLoadTime)
-		d.Config.EmitChangeEvents(&oldConfig, d.g)
 	}
 	}
+	d.Log().Infof("Configuration was reloaded at %s", d.configLoadTime)
+	d.Config.EmitChangeEvents(&oldConfig, d.g)
+
 	return nil
 	return nil
 }
 }
 
 

+ 11 - 11
api_test.go

@@ -257,10 +257,10 @@ func TestReopenLog(t *testing.T) {
 		t.Error("could not read logfile")
 		t.Error("could not read logfile")
 		return
 		return
 	}
 	}
-	if strings.Index(string(b), "re-opened log file") < 0 {
+	if !strings.Contains(string(b), "re-opened log file") {
 		t.Error("Server log did not re-opened, expecting \"re-opened log file\"")
 		t.Error("Server log did not re-opened, expecting \"re-opened log file\"")
 	}
 	}
-	if strings.Index(string(b), "re-opened main log file") < 0 {
+	if !strings.Contains(string(b), "re-opened main log file") {
 		t.Error("Main log did not re-opened, expecting \"re-opened main log file\"")
 		t.Error("Main log did not re-opened, expecting \"re-opened main log file\"")
 	}
 	}
 }
 }
@@ -305,7 +305,7 @@ func TestSetConfig(t *testing.T) {
 	}
 	}
 	//fmt.Println(string(b))
 	//fmt.Println(string(b))
 	// has 127.0.0.1:2527 started?
 	// has 127.0.0.1:2527 started?
-	if strings.Index(string(b), "127.0.0.1:2527") < 0 {
+	if !strings.Contains(string(b), "127.0.0.1:2527") {
 		t.Error("expecting 127.0.0.1:2527 to start")
 		t.Error("expecting 127.0.0.1:2527 to start")
 	}
 	}
 
 
@@ -409,18 +409,18 @@ func TestSetAddProcessor(t *testing.T) {
 		return
 		return
 	}
 	}
 	// lets check for fingerprints
 	// lets check for fingerprints
-	if strings.Index(string(b), "another funky recipient") < 0 {
+	if !strings.Contains(string(b), "another funky recipient") {
 		t.Error("did not log: another funky recipient")
 		t.Error("did not log: another funky recipient")
 	}
 	}
 
 
-	if strings.Index(string(b), "Another funky email!") < 0 {
+	if !strings.Contains(string(b), "Another funky email!") {
 		t.Error("Did not log: Another funky email!")
 		t.Error("Did not log: Another funky email!")
 	}
 	}
 
 
-	if strings.Index(string(b), "Funky logger is up & down to funk") < 0 {
+	if !strings.Contains(string(b), "Funky logger is up & down to funk") {
 		t.Error("Did not log: Funky logger is up & down to funk")
 		t.Error("Did not log: Funky logger is up & down to funk")
 	}
 	}
-	if strings.Index(string(b), "The funk has been stopped!") < 0 {
+	if !strings.Contains(string(b), "The funk has been stopped!") {
 		t.Error("Did not log:The funk has been stopped!")
 		t.Error("Did not log:The funk has been stopped!")
 	}
 	}
 
 
@@ -576,7 +576,7 @@ func TestPubSubAPI(t *testing.T) {
 		return
 		return
 	}
 	}
 	// lets interrogate the log
 	// lets interrogate the log
-	if strings.Index(string(b), "number1") < 0 {
+	if !strings.Contains(string(b), "number1") {
 		t.Error("it lools like d.ReloadConfig(cfg) did not fire EventConfigPidFile, pidEvHandler not called")
 		t.Error("it lools like d.ReloadConfig(cfg) did not fire EventConfigPidFile, pidEvHandler not called")
 	}
 	}
 
 
@@ -609,7 +609,7 @@ func TestAPILog(t *testing.T) {
 		return
 		return
 	}
 	}
 	// lets interrogate the log
 	// lets interrogate the log
-	if strings.Index(string(b), "logtest1") < 0 {
+	if !strings.Contains(string(b), "logtest1") {
 		t.Error("hai was not found in the log, it should have been in tests/testlog")
 		t.Error("hai was not found in the log, it should have been in tests/testlog")
 	}
 	}
 }
 }
@@ -700,11 +700,11 @@ func TestCustomBackendResult(t *testing.T) {
 		return
 		return
 	}
 	}
 	// lets check for fingerprints
 	// lets check for fingerprints
-	if strings.Index(string(b), "451 4.3.0 Error") < 0 {
+	if !strings.Contains(string(b), "451 4.3.0 Error") {
 		t.Error("did not log: 451 4.3.0 Error")
 		t.Error("did not log: 451 4.3.0 Error")
 	}
 	}
 
 
-	if strings.Index(string(b), "system shock") < 0 {
+	if !strings.Contains(string(b), "system shock") {
 		t.Error("did not log: system shock")
 		t.Error("did not log: system shock")
 	}
 	}
 
 

+ 5 - 5
backends/gateway.go

@@ -7,11 +7,12 @@ import (
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"runtime/debug"
+	"strings"
+
 	"github.com/flashmob/go-guerrilla/log"
 	"github.com/flashmob/go-guerrilla/log"
 	"github.com/flashmob/go-guerrilla/mail"
 	"github.com/flashmob/go-guerrilla/mail"
 	"github.com/flashmob/go-guerrilla/response"
 	"github.com/flashmob/go-guerrilla/response"
-	"runtime/debug"
-	"strings"
 )
 )
 
 
 var ErrProcessorNotFound error
 var ErrProcessorNotFound error
@@ -266,7 +267,7 @@ func (gw *BackendGateway) newStack(stackConfig string) (Processor, error) {
 		if makeFunc, ok := processors[name]; ok {
 		if makeFunc, ok := processors[name]; ok {
 			decorators = append(decorators, makeFunc())
 			decorators = append(decorators, makeFunc())
 		} else {
 		} else {
-			ErrProcessorNotFound = errors.New(fmt.Sprintf("processor [%s] not found", name))
+			ErrProcessorNotFound = fmt.Errorf("processor [%s] not found", name)
 			return nil, ErrProcessorNotFound
 			return nil, ErrProcessorNotFound
 		}
 		}
 	}
 	}
@@ -371,7 +372,7 @@ func (gw *BackendGateway) Start() error {
 		gw.State = BackendStateRunning
 		gw.State = BackendStateRunning
 		return nil
 		return nil
 	} else {
 	} else {
-		return errors.New(fmt.Sprintf("cannot start backend because it's in %s state", gw.State))
+		return fmt.Errorf("cannot start backend because it's in %s state", gw.State)
 	}
 	}
 }
 }
 
 
@@ -442,7 +443,6 @@ func (gw *BackendGateway) workDispatcher(
 			return
 			return
 		}
 		}
 		// state is dispatcherStateStopped if it reached here
 		// state is dispatcherStateStopped if it reached here
-		return
 
 
 	}()
 	}()
 	state = dispatcherStateIdle
 	state = dispatcherStateIdle

+ 7 - 7
client.go

@@ -6,14 +6,15 @@ import (
 	"crypto/tls"
 	"crypto/tls"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"github.com/flashmob/go-guerrilla/log"
-	"github.com/flashmob/go-guerrilla/mail"
-	"github.com/flashmob/go-guerrilla/mail/rfc5321"
-	"github.com/flashmob/go-guerrilla/response"
 	"net"
 	"net"
 	"net/textproto"
 	"net/textproto"
 	"sync"
 	"sync"
 	"time"
 	"time"
+
+	"github.com/flashmob/go-guerrilla/log"
+	"github.com/flashmob/go-guerrilla/mail"
+	"github.com/flashmob/go-guerrilla/mail/rfc5321"
+	"github.com/flashmob/go-guerrilla/response"
 )
 )
 
 
 // ClientState indicates which part of the SMTP transaction a given client is in.
 // ClientState indicates which part of the SMTP transaction a given client is in.
@@ -181,9 +182,8 @@ func (c *client) getID() uint64 {
 
 
 // UpgradeToTLS upgrades a client connection to TLS
 // UpgradeToTLS upgrades a client connection to TLS
 func (c *client) upgradeToTLS(tlsConfig *tls.Config) error {
 func (c *client) upgradeToTLS(tlsConfig *tls.Config) error {
-	var tlsConn *tls.Conn
 	// wrap c.conn in a new TLS server side connection
 	// wrap c.conn in a new TLS server side connection
-	tlsConn = tls.Server(c.conn, tlsConfig)
+	tlsConn := tls.Server(c.conn, tlsConfig)
 	// Call handshake here to get any handshake error before reading starts
 	// Call handshake here to get any handshake error before reading starts
 	err := tlsConn.Handshake()
 	err := tlsConn.Handshake()
 	if err != nil {
 	if err != nil {
@@ -235,6 +235,6 @@ func (c *client) parsePath(in []byte, p pathParser) (mail.Address, error) {
 	return address, err
 	return address, err
 }
 }
 
 
-func (s *server) rcptTo(in []byte) (address mail.Address, err error) {
+func (s *server) rcptTo() (address mail.Address, err error) {
 	return address, err
 	return address, err
 }
 }

+ 9 - 9
cmd/guerrillad/serve_test.go

@@ -20,7 +20,7 @@ import (
 	"github.com/flashmob/go-guerrilla"
 	"github.com/flashmob/go-guerrilla"
 	"github.com/flashmob/go-guerrilla/backends"
 	"github.com/flashmob/go-guerrilla/backends"
 	"github.com/flashmob/go-guerrilla/log"
 	"github.com/flashmob/go-guerrilla/log"
-	"github.com/flashmob/go-guerrilla/tests"
+	test "github.com/flashmob/go-guerrilla/tests"
 	"github.com/flashmob/go-guerrilla/tests/testcert"
 	"github.com/flashmob/go-guerrilla/tests/testcert"
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
 )
 )
@@ -672,7 +672,7 @@ func TestServerAddEvent(t *testing.T) {
 	newConf := conf                                      // copy the cmdConfg
 	newConf := conf                                      // copy the cmdConfg
 	newConf.Servers = append(newConf.Servers, newServer) // add the new server
 	newConf.Servers = append(newConf.Servers, newServer) // add the new server
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
-		if err := ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644); err != nil {
+		if err := ioutil.WriteFile("configJsonA.json", jsonbytes, 0644); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	}
 	}
@@ -749,7 +749,7 @@ func TestServerStartEvent(t *testing.T) {
 	newConf.Servers[1].IsEnabled = true
 	newConf.Servers[1].IsEnabled = true
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 		//fmt.Println(string(jsonbytes))
 		//fmt.Println(string(jsonbytes))
-		if err = ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644); err != nil {
+		if err = ioutil.WriteFile("configJsonA.json", jsonbytes, 0644); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	} else {
 	} else {
@@ -830,7 +830,7 @@ func TestServerStopEvent(t *testing.T) {
 	newConf.Servers[1].IsEnabled = true // enable 2nd server
 	newConf.Servers[1].IsEnabled = true // enable 2nd server
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 		//fmt.Println(string(jsonbytes))
 		//fmt.Println(string(jsonbytes))
-		if err = ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644); err != nil {
+		if err = ioutil.WriteFile("configJsonA.json", jsonbytes, 0644); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	} else {
 	} else {
@@ -863,7 +863,7 @@ func TestServerStopEvent(t *testing.T) {
 	newerConf.Servers[1].IsEnabled = false
 	newerConf.Servers[1].IsEnabled = false
 	if jsonbytes, err := json.Marshal(newerConf); err == nil {
 	if jsonbytes, err := json.Marshal(newerConf); err == nil {
 		//fmt.Println(string(jsonbytes))
 		//fmt.Println(string(jsonbytes))
-		if err = ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644); err != nil {
+		if err = ioutil.WriteFile("configJsonA.json", jsonbytes, 0644); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	} else {
 	} else {
@@ -980,7 +980,7 @@ func TestAllowedHostsEvent(t *testing.T) {
 	newConf := conf
 	newConf := conf
 	newConf.AllowedHosts = append(newConf.AllowedHosts, "grr.la")
 	newConf.AllowedHosts = append(newConf.AllowedHosts, "grr.la")
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
-		if err = ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644); err != nil {
+		if err = ioutil.WriteFile("configJsonD.json", jsonbytes, 0644); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	} else {
 	} else {
@@ -1277,7 +1277,7 @@ func TestBadTLSReload(t *testing.T) {
 	newConf := conf // copy the cmdConfg
 	newConf := conf // copy the cmdConfg
 
 
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
-		if err = ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644); err != nil {
+		if err = ioutil.WriteFile("configJsonD.json", jsonbytes, 0644); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	} else {
 	} else {
@@ -1353,7 +1353,7 @@ func TestSetTimeoutEvent(t *testing.T) {
 	newConf := conf // copy the cmdConfg
 	newConf := conf // copy the cmdConfg
 	newConf.Servers[0].Timeout = 1
 	newConf.Servers[0].Timeout = 1
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
-		if err = ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644); err != nil {
+		if err = ioutil.WriteFile("configJsonD.json", jsonbytes, 0644); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	} else {
 	} else {
@@ -1456,7 +1456,7 @@ func TestDebugLevelChange(t *testing.T) {
 	newConf := conf // copy the cmdConfg
 	newConf := conf // copy the cmdConfg
 	newConf.LogLevel = log.InfoLevel.String()
 	newConf.LogLevel = log.InfoLevel.String()
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
 	if jsonbytes, err := json.Marshal(newConf); err == nil {
-		if err = ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644); err != nil {
+		if err = ioutil.WriteFile("configJsonD.json", jsonbytes, 0644); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	} else {
 	} else {

+ 31 - 36
config.go

@@ -5,12 +5,13 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"github.com/flashmob/go-guerrilla/backends"
-	"github.com/flashmob/go-guerrilla/log"
 	"os"
 	"os"
 	"reflect"
 	"reflect"
 	"strings"
 	"strings"
 	"time"
 	"time"
+
+	"github.com/flashmob/go-guerrilla/backends"
+	"github.com/flashmob/go-guerrilla/log"
 )
 )
 
 
 // AppConfig is the holder of the configuration of the app
 // AppConfig is the holder of the configuration of the app
@@ -34,44 +35,32 @@ type AppConfig struct {
 
 
 // ServerConfig specifies config options for a single server
 // ServerConfig specifies config options for a single server
 type ServerConfig struct {
 type ServerConfig struct {
-	// IsEnabled set to true to start the server, false will ignore it
-	IsEnabled bool `json:"is_enabled"`
+	// TLS Configuration
+	TLS ServerTLSConfig `json:"tls,omitempty"`
+	// LogFile is where the logs go. Use path to file, or "stderr", "stdout" or "off".
+	// defaults to AppConfig.Log file setting
+	LogFile string `json:"log_file,omitempty"`
 	// Hostname will be used in the server's reply to HELO/EHLO. If TLS enabled
 	// Hostname will be used in the server's reply to HELO/EHLO. If TLS enabled
 	// make sure that the Hostname matches the cert. Defaults to os.Hostname()
 	// make sure that the Hostname matches the cert. Defaults to os.Hostname()
 	Hostname string `json:"host_name"`
 	Hostname string `json:"host_name"`
+	// Listen interface specified in <ip>:<port> - defaults to 127.0.0.1:2525
+	ListenInterface string `json:"listen_interface"`
 	// MaxSize is the maximum size of an email that will be accepted for delivery.
 	// MaxSize is the maximum size of an email that will be accepted for delivery.
 	// Defaults to 10 Mebibytes
 	// Defaults to 10 Mebibytes
 	MaxSize int64 `json:"max_size"`
 	MaxSize int64 `json:"max_size"`
-	// TLS Configuration
-	TLS ServerTLSConfig `json:"tls,omitempty"`
 	// Timeout specifies the connection timeout in seconds. Defaults to 30
 	// Timeout specifies the connection timeout in seconds. Defaults to 30
 	Timeout int `json:"timeout"`
 	Timeout int `json:"timeout"`
-	// Listen interface specified in <ip>:<port> - defaults to 127.0.0.1:2525
-	ListenInterface string `json:"listen_interface"`
-
 	// MaxClients controls how many maximum clients we can handle at once.
 	// MaxClients controls how many maximum clients we can handle at once.
 	// Defaults to defaultMaxClients
 	// Defaults to defaultMaxClients
 	MaxClients int `json:"max_clients"`
 	MaxClients int `json:"max_clients"`
-	// LogFile is where the logs go. Use path to file, or "stderr", "stdout" or "off".
-	// defaults to AppConfig.Log file setting
-	LogFile string `json:"log_file,omitempty"`
+	// IsEnabled set to true to start the server, false will ignore it
+	IsEnabled bool `json:"is_enabled"`
 	// XClientOn when using a proxy such as Nginx, XCLIENT command is used to pass the
 	// XClientOn when using a proxy such as Nginx, XCLIENT command is used to pass the
 	// original client's IP address & client's HELO
 	// original client's IP address & client's HELO
 	XClientOn bool `json:"xclient_on,omitempty"`
 	XClientOn bool `json:"xclient_on,omitempty"`
 }
 }
 
 
 type ServerTLSConfig struct {
 type ServerTLSConfig struct {
-
-	// StartTLSOn should we offer STARTTLS command. Cert must be valid.
-	// False by default
-	StartTLSOn bool `json:"start_tls_on,omitempty"`
-	// AlwaysOn run this server as a pure TLS server, i.e. SMTPS
-	AlwaysOn bool `json:"tls_always_on,omitempty"`
-	// PrivateKeyFile path to cert private key in PEM format.
-	PrivateKeyFile string `json:"private_key_file"`
-	// PublicKeyFile path to cert (public key) chain in PEM format.
-	PublicKeyFile string `json:"public_key_file"`
-
 	// TLS Protocols to use. [0] = min, [1]max
 	// TLS Protocols to use. [0] = min, [1]max
 	// Use Go's default if empty
 	// Use Go's default if empty
 	Protocols []string `json:"protocols,omitempty"`
 	Protocols []string `json:"protocols,omitempty"`
@@ -81,19 +70,27 @@ type ServerTLSConfig struct {
 	// TLS Curves to use.
 	// TLS Curves to use.
 	// Use Go's default if empty
 	// Use Go's default if empty
 	Curves []string `json:"curves,omitempty"`
 	Curves []string `json:"curves,omitempty"`
+	// PrivateKeyFile path to cert private key in PEM format.
+	PrivateKeyFile string `json:"private_key_file"`
+	// PublicKeyFile path to cert (public key) chain in PEM format.
+	PublicKeyFile string `json:"public_key_file"`
 	// TLS Root cert authorities to use. "A PEM encoded CA's certificate file.
 	// TLS Root cert authorities to use. "A PEM encoded CA's certificate file.
 	// Defaults to system's root CA file if empty
 	// Defaults to system's root CA file if empty
 	RootCAs string `json:"root_cas_file,omitempty"`
 	RootCAs string `json:"root_cas_file,omitempty"`
 	// declares the policy the server will follow for TLS Client Authentication.
 	// declares the policy the server will follow for TLS Client Authentication.
 	// Use Go's default if empty
 	// Use Go's default if empty
 	ClientAuthType string `json:"client_auth_type,omitempty"`
 	ClientAuthType string `json:"client_auth_type,omitempty"`
-	// controls whether the server selects the
-	// client's most preferred cipher suite
-	PreferServerCipherSuites bool `json:"prefer_server_cipher_suites,omitempty"`
-
 	// The following used to watch certificate changes so that the TLS can be reloaded
 	// The following used to watch certificate changes so that the TLS can be reloaded
 	_privateKeyFileMtime int64
 	_privateKeyFileMtime int64
 	_publicKeyFileMtime  int64
 	_publicKeyFileMtime  int64
+	// controls whether the server selects the
+	// client's most preferred cipher suite
+	PreferServerCipherSuites bool `json:"prefer_server_cipher_suites,omitempty"`
+	// StartTLSOn should we offer STARTTLS command. Cert must be valid.
+	// False by default
+	StartTLSOn bool `json:"start_tls_on,omitempty"`
+	// AlwaysOn run this server as a pure TLS server, i.e. SMTPS
+	AlwaysOn bool `json:"tls_always_on,omitempty"`
 }
 }
 
 
 // https://golang.org/pkg/crypto/tls/#pkg-constants
 // https://golang.org/pkg/crypto/tls/#pkg-constants
@@ -303,7 +300,7 @@ func (c *AppConfig) setDefaults() error {
 				c.Servers[i].MaxSize = defaultMaxSize // 10 Mebibytes
 				c.Servers[i].MaxSize = defaultMaxSize // 10 Mebibytes
 			}
 			}
 			if c.Servers[i].ListenInterface == "" {
 			if c.Servers[i].ListenInterface == "" {
-				return errors.New(fmt.Sprintf("Listen interface not specified for server at index %d", i))
+				return fmt.Errorf("Listen interface not specified for server at index %d", i)
 			}
 			}
 			if c.Servers[i].LogFile == "" {
 			if c.Servers[i].LogFile == "" {
 				c.Servers[i].LogFile = c.LogFile
 				c.Servers[i].LogFile = c.LogFile
@@ -408,11 +405,10 @@ func (sc *ServerConfig) emitChangeEvents(oldServer *ServerConfig, app Guerrilla)
 // Loads in timestamps for the ssl keys
 // Loads in timestamps for the ssl keys
 func (sc *ServerConfig) loadTlsKeyTimestamps() error {
 func (sc *ServerConfig) loadTlsKeyTimestamps() error {
 	var statErr = func(iface string, err error) error {
 	var statErr = func(iface string, err error) error {
-		return errors.New(
-			fmt.Sprintf(
-				"could not stat key for server [%s], %s",
-				iface,
-				err.Error()))
+		return fmt.Errorf(
+			"could not stat key for server [%s], %s",
+			iface,
+			err.Error())
 	}
 	}
 	if sc.TLS.PrivateKeyFile == "" {
 	if sc.TLS.PrivateKeyFile == "" {
 		sc.TLS._privateKeyFileMtime = time.Now().Unix()
 		sc.TLS._privateKeyFileMtime = time.Now().Unix()
@@ -447,8 +443,7 @@ func (sc *ServerConfig) Validate() error {
 			errs = append(errs, errors.New("PrivateKeyFile is empty"))
 			errs = append(errs, errors.New("PrivateKeyFile is empty"))
 		}
 		}
 		if _, err := tls.LoadX509KeyPair(sc.TLS.PublicKeyFile, sc.TLS.PrivateKeyFile); err != nil {
 		if _, err := tls.LoadX509KeyPair(sc.TLS.PublicKeyFile, sc.TLS.PrivateKeyFile); err != nil {
-			errs = append(errs,
-				errors.New(fmt.Sprintf("cannot use TLS config for [%s], %v", sc.ListenInterface, err)))
+			errs = append(errs, fmt.Errorf("cannot use TLS config for [%s], %v", sc.ListenInterface, err))
 		}
 		}
 	}
 	}
 	if len(errs) > 0 {
 	if len(errs) > 0 {
@@ -504,7 +499,7 @@ func getChanges(a interface{}, b interface{}) map[string]interface{} {
 // only able to convert int, bool, slice-of-strings and string; not recursive
 // only able to convert int, bool, slice-of-strings and string; not recursive
 // slices are marshal'd to json for convenient comparison later
 // slices are marshal'd to json for convenient comparison later
 func structtomap(obj interface{}) map[string]interface{} {
 func structtomap(obj interface{}) map[string]interface{} {
-	ret := make(map[string]interface{}, 0)
+	ret := make(map[string]interface{})
 	v := reflect.ValueOf(obj)
 	v := reflect.ValueOf(obj)
 	t := v.Type()
 	t := v.Type()
 	for index := 0; index < v.NumField(); index++ {
 	for index := 0; index < v.NumField(); index++ {

+ 1 - 1
config_test.go

@@ -276,7 +276,7 @@ func TestConfigChangeEvents(t *testing.T) {
 	for event := range expectedEvents {
 	for event := range expectedEvents {
 		// Put in anon func since range is overwriting event
 		// Put in anon func since range is overwriting event
 		func(e Event) {
 		func(e Event) {
-			if strings.Index(e.String(), "config_change") != -1 {
+			if strings.Contains(e.String(), "config_change") {
 				f := func(c *AppConfig) {
 				f := func(c *AppConfig) {
 					expectedEvents[e] = true
 					expectedEvents[e] = true
 				}
 				}

+ 4 - 0
guerrilla.go

@@ -102,6 +102,9 @@ func New(ac *AppConfig, b backends.Backend, l log.Logger) (Guerrilla, error) {
 
 
 	g.state = daemonStateNew
 	g.state = daemonStateNew
 	err := g.makeServers()
 	err := g.makeServers()
+	if err != nil {
+		return g, err
+	}
 
 
 	// start backend for processing email
 	// start backend for processing email
 	err = g.backend().Start()
 	err = g.backend().Start()
@@ -129,6 +132,7 @@ func (g *guerrilla) makeServers() error {
 			errs = append(errs, err)
 			errs = append(errs, err)
 			continue
 			continue
 		} else {
 		} else {
+			sc := sc // pin!
 			server, err := newServer(&sc, g.backend(), g.mainlog())
 			server, err := newServer(&sc, g.backend(), g.mainlog())
 			if err != nil {
 			if err != nil {
 				g.mainlog().WithError(err).Errorf("Failed to create server [%s]", sc.ListenInterface)
 				g.mainlog().WithError(err).Errorf("Failed to create server [%s]", sc.ListenInterface)

+ 1 - 0
guerrilla_unix.go

@@ -11,5 +11,6 @@ func getFileLimit() (uint64, error) {
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
+	//unnecessary type conversions to uint64 is needed for FreeBSD
 	return uint64(rLimit.Max), nil
 	return uint64(rLimit.Max), nil
 }
 }

+ 8 - 6
log/hook.go

@@ -143,7 +143,10 @@ func (hook *LogrusHook) openCreate(dest string) (err error) {
 func (hook *LogrusHook) Fire(entry *log.Entry) error {
 func (hook *LogrusHook) Fire(entry *log.Entry) error {
 	hookMu.Lock()
 	hookMu.Lock()
 	defer hookMu.Unlock()
 	defer hookMu.Unlock()
-	if line, err := entry.String(); err == nil {
+
+	line, err := entry.String()
+
+	if err == nil {
 		r := strings.NewReader(line)
 		r := strings.NewReader(line)
 		if _, err = io.Copy(hook.w, r); err != nil {
 		if _, err = io.Copy(hook.w, r); err != nil {
 			return err
 			return err
@@ -157,9 +160,8 @@ func (hook *LogrusHook) Fire(entry *log.Entry) error {
 			}
 			}
 		}
 		}
 		return err
 		return err
-	} else {
-		return err
 	}
 	}
+	return err
 }
 }
 
 
 // Levels implements the logrus Hook interface
 // Levels implements the logrus Hook interface
@@ -177,12 +179,12 @@ func (hook *LogrusHook) Reopen() error {
 			return err
 			return err
 		}
 		}
 		// The file could have been re-named by an external program such as logrotate(8)
 		// The file could have been re-named by an external program such as logrotate(8)
-		if _, err := os.Stat(hook.fname); err != nil {
+		_, err := os.Stat(hook.fname)
+		if err != nil {
 			// The file doesn't exist, create a new one.
 			// The file doesn't exist, create a new one.
 			return hook.openCreate(hook.fname)
 			return hook.openCreate(hook.fname)
-		} else {
-			return hook.openAppend(hook.fname)
 		}
 		}
+		return hook.openAppend(hook.fname)
 	}
 	}
 	return err
 	return err
 
 

+ 5 - 5
log/log.go

@@ -130,17 +130,17 @@ func GetLogger(dest string, level string) (Logger, error) {
 	// we'll use the hook to output instead
 	// we'll use the hook to output instead
 	logrus.Out = ioutil.Discard
 	logrus.Out = ioutil.Discard
 	// setup the hook
 	// setup the hook
-	if h, err := NewLogrusHook(dest); err != nil {
+	h, err := NewLogrusHook(dest)
+	if err != nil {
 		// revert back to stderr
 		// revert back to stderr
 		logrus.Out = os.Stderr
 		logrus.Out = os.Stderr
 		return l, err
 		return l, err
-	} else {
-		logrus.Hooks.Add(h)
-		l.h = h
 	}
 	}
 
 
-	return l, nil
+	logrus.Hooks.Add(h)
+	l.h = h
 
 
+	return l, nil
 }
 }
 
 
 func newLogrus(o OutputOption, level string) (*log.Logger, error) {
 func newLogrus(o OutputOption, level string) (*log.Logger, error) {

+ 7 - 7
mail/envelope.go

@@ -71,7 +71,7 @@ func NewAddress(str string) (Address, error) {
 	return Address{}, errors.New("invalid address")
 	return Address{}, errors.New("invalid address")
 }
 }
 
 
-// Email represents a single SMTP message.
+// Envelope of Email represents a single SMTP message.
 type Envelope struct {
 type Envelope struct {
 	// Remote IP address
 	// Remote IP address
 	RemoteIP string
 	RemoteIP string
@@ -150,7 +150,7 @@ func (e *Envelope) Len() int {
 	return len(e.DeliveryHeader) + e.Data.Len()
 	return len(e.DeliveryHeader) + e.Data.Len()
 }
 }
 
 
-// Returns a new reader for reading the email contents, including the delivery headers
+// NewReader returns a new reader for reading the email contents, including the delivery headers
 func (e *Envelope) NewReader() io.Reader {
 func (e *Envelope) NewReader() io.Reader {
 	return io.MultiReader(
 	return io.MultiReader(
 		strings.NewReader(e.DeliveryHeader),
 		strings.NewReader(e.DeliveryHeader),
@@ -185,9 +185,9 @@ func (e *Envelope) ResetTransaction() {
 	e.Values = make(map[string]interface{})
 	e.Values = make(map[string]interface{})
 }
 }
 
 
-// Seed is called when used with a new connection, once it's accepted
-func (e *Envelope) Reseed(RemoteIP string, clientID uint64) {
-	e.RemoteIP = RemoteIP
+// Reseed is called when used with a new connection, once it's accepted
+func (e *Envelope) Reseed(remoteIP string, clientID uint64) {
+	e.RemoteIP = remoteIP
 	e.QueuedId = queuedID(clientID)
 	e.QueuedId = queuedID(clientID)
 	e.Helo = ""
 	e.Helo = ""
 	e.TLS = false
 	e.TLS = false
@@ -198,14 +198,14 @@ func (e *Envelope) PushRcpt(addr Address) {
 	e.RcptTo = append(e.RcptTo, addr)
 	e.RcptTo = append(e.RcptTo, addr)
 }
 }
 
 
-// Pop removes the last email address that was pushed to the envelope
+// PopRcpt removes the last email address that was pushed to the envelope
 func (e *Envelope) PopRcpt() Address {
 func (e *Envelope) PopRcpt() Address {
 	ret := e.RcptTo[len(e.RcptTo)-1]
 	ret := e.RcptTo[len(e.RcptTo)-1]
 	e.RcptTo = e.RcptTo[:len(e.RcptTo)-1]
 	e.RcptTo = e.RcptTo[:len(e.RcptTo)-1]
 	return ret
 	return ret
 }
 }
 
 
-// Converts 7 bit encoded mime header strings to UTF-8
+// MimeHeaderDecode converts 7 bit encoded mime header strings to UTF-8
 func MimeHeaderDecode(str string) string {
 func MimeHeaderDecode(str string) string {
 	state := 0
 	state := 0
 	var buf bytes.Buffer
 	var buf bytes.Buffer

+ 8 - 11
mail/rfc5321/parse.go

@@ -23,18 +23,15 @@ const (
 
 
 // Parse Email Addresses according to https://tools.ietf.org/html/rfc5321
 // Parse Email Addresses according to https://tools.ietf.org/html/rfc5321
 type Parser struct {
 type Parser struct {
-	NullPath  bool
-	LocalPart string
-	Domain    string
-
-	ADL        []string
+	accept     bytes.Buffer
+	buf        []byte
 	PathParams [][]string
 	PathParams [][]string
-
-	pos int
-	ch  byte
-
-	buf    []byte
-	accept bytes.Buffer
+	ADL        []string
+	LocalPart  string
+	Domain     string
+	pos        int
+	NullPath   bool
+	ch         byte
 }
 }
 
 
 func NewParser(buf []byte) *Parser {
 func NewParser(buf []byte) *Parser {

+ 0 - 2
mocks/client.go

@@ -11,8 +11,6 @@ const (
 
 
 func lastWords(message string, err error) {
 func lastWords(message string, err error) {
 	fmt.Println(message, err.Error())
 	fmt.Println(message, err.Error())
-	return
-	// panic(err)
 }
 }
 
 
 func sendMail(i int) {
 func sendMail(i int) {

+ 1 - 2
response/quote.go

@@ -1,7 +1,6 @@
 package response
 package response
 
 
 import (
 import (
-	"fmt"
 	"math/rand"
 	"math/rand"
 	"time"
 	"time"
 )
 )
@@ -156,5 +155,5 @@ var quotes = struct {
 // GetQuote returns a random quote from The big Lebowski
 // GetQuote returns a random quote from The big Lebowski
 func GetQuote() string {
 func GetQuote() string {
 	rand.Seed(time.Now().UnixNano())
 	rand.Seed(time.Now().UnixNano())
-	return fmt.Sprintf("%s", quotes.m[rand.Intn(len(quotes.m))])
+	return quotes.m[rand.Intn(len(quotes.m))]
 }
 }

+ 7 - 7
server.go

@@ -214,7 +214,7 @@ func (s *server) setAllowedHosts(allowedHosts []string) {
 	s.hosts.table = make(map[string]bool, len(allowedHosts))
 	s.hosts.table = make(map[string]bool, len(allowedHosts))
 	s.hosts.wildcards = nil
 	s.hosts.wildcards = nil
 	for _, h := range allowedHosts {
 	for _, h := range allowedHosts {
-		if strings.Index(h, "*") != -1 {
+		if strings.Contains(h, "*") {
 			s.hosts.wildcards = append(s.hosts.wildcards, strings.ToLower(h))
 			s.hosts.wildcards = append(s.hosts.wildcards, strings.ToLower(h))
 		} else {
 		} else {
 			s.hosts.table[strings.ToLower(h)] = true
 			s.hosts.table[strings.ToLower(h)] = true
@@ -447,14 +447,14 @@ func (s *server) handleClient(client *client) {
 				if toks := bytes.Split(input[8:], []byte{' '}); len(toks) > 0 {
 				if toks := bytes.Split(input[8:], []byte{' '}); len(toks) > 0 {
 					for i := range toks {
 					for i := range toks {
 						if vals := bytes.Split(toks[i], []byte{'='}); len(vals) == 2 {
 						if vals := bytes.Split(toks[i], []byte{'='}); len(vals) == 2 {
-							if bytes.Compare(vals[1], []byte("[UNAVAILABLE]")) == 0 {
+							if bytes.Equal(vals[1], []byte("[UNAVAILABLE]")) {
 								// skip
 								// skip
 								continue
 								continue
 							}
 							}
-							if bytes.Compare(vals[0], []byte("ADDR")) == 0 {
+							if bytes.Equal(vals[0], []byte("ADDR")) {
 								client.RemoteIP = string(vals[1])
 								client.RemoteIP = string(vals[1])
 							}
 							}
-							if bytes.Compare(vals[0], []byte("HELO")) == 0 {
+							if bytes.Equal(vals[0], []byte("HELO")) {
 								client.Helo = string(vals[1])
 								client.Helo = string(vals[1])
 							}
 							}
 						}
 						}
@@ -466,7 +466,7 @@ func (s *server) handleClient(client *client) {
 					client.sendResponse(r.FailNestedMailCmd)
 					client.sendResponse(r.FailNestedMailCmd)
 					break
 					break
 				}
 				}
-				client.MailFrom, err = client.parsePath([]byte(input[10:]), client.parser.MailFrom)
+				client.MailFrom, err = client.parsePath(input[10:], client.parser.MailFrom)
 				if err != nil {
 				if err != nil {
 					s.log().WithError(err).Error("MAIL parse error", "["+string(input[10:])+"]")
 					s.log().WithError(err).Error("MAIL parse error", "["+string(input[10:])+"]")
 					client.sendResponse(err)
 					client.sendResponse(err)
@@ -482,7 +482,7 @@ func (s *server) handleClient(client *client) {
 					client.sendResponse(r.ErrorTooManyRecipients)
 					client.sendResponse(r.ErrorTooManyRecipients)
 					break
 					break
 				}
 				}
-				to, err := client.parsePath([]byte(input[8:]), client.parser.RcptTo)
+				to, err := client.parsePath(input[8:], client.parser.RcptTo)
 				if err != nil {
 				if err != nil {
 					s.log().WithError(err).Error("RCPT parse error", "["+string(input[8:])+"]")
 					s.log().WithError(err).Error("RCPT parse error", "["+string(input[8:])+"]")
 					client.sendResponse(err.Error())
 					client.sendResponse(err.Error())
@@ -541,7 +541,7 @@ func (s *server) handleClient(client *client) {
 
 
 			// intentionally placed the limit 1MB above so that reading does not return with an error
 			// intentionally placed the limit 1MB above so that reading does not return with an error
 			// if the client goes a little over. Anything above will err
 			// if the client goes a little over. Anything above will err
-			client.bufin.setLimit(int64(sc.MaxSize) + 1024000) // This a hard limit.
+			client.bufin.setLimit(sc.MaxSize + 1024000) // This a hard limit.
 
 
 			n, err := client.Data.ReadFrom(client.smtpReader.DotReader())
 			n, err := client.Data.ReadFrom(client.smtpReader.DotReader())
 			if n > sc.MaxSize {
 			if n > sc.MaxSize {

+ 6 - 5
server_test.go

@@ -11,12 +11,13 @@ import (
 
 
 	"crypto/tls"
 	"crypto/tls"
 	"fmt"
 	"fmt"
+	"io/ioutil"
+	"net"
+
 	"github.com/flashmob/go-guerrilla/backends"
 	"github.com/flashmob/go-guerrilla/backends"
 	"github.com/flashmob/go-guerrilla/log"
 	"github.com/flashmob/go-guerrilla/log"
 	"github.com/flashmob/go-guerrilla/mail"
 	"github.com/flashmob/go-guerrilla/mail"
 	"github.com/flashmob/go-guerrilla/mocks"
 	"github.com/flashmob/go-guerrilla/mocks"
-	"io/ioutil"
-	"net"
 )
 )
 
 
 // getMockServerConfig gets a mock ServerConfig struct used for creating a new server
 // getMockServerConfig gets a mock ServerConfig struct used for creating a new server
@@ -232,7 +233,7 @@ func TestTLSConfig(t *testing.T) {
 	} else if c.CurvePreferences[0] != tls.CurveP521 && c.CurvePreferences[1] != tls.CurveP384 {
 	} else if c.CurvePreferences[0] != tls.CurveP521 && c.CurvePreferences[1] != tls.CurveP384 {
 		t.Error("c.CurvePreferences curves not setup")
 		t.Error("c.CurvePreferences curves not setup")
 	}
 	}
-	if strings.Index(string(c.RootCAs.Subjects()[0]), "Mountain View") == -1 {
+	if !strings.Contains(string(c.RootCAs.Subjects()[0]), "Mountain View") {
 		t.Error("c.RootCAs not correctly set")
 		t.Error("c.RootCAs not correctly set")
 	}
 	}
 	if c.ClientAuth != tls.NoClientCert {
 	if c.ClientAuth != tls.NoClientCert {
@@ -440,7 +441,7 @@ func TestGatewayTimeout(t *testing.T) {
 			expect := "transaction timeout"
 			expect := "transaction timeout"
 			if err != nil {
 			if err != nil {
 				t.Error(err)
 				t.Error(err)
-			} else if strings.Index(str, expect) == -1 {
+			} else if !strings.Contains(str, expect) {
 				t.Error("Expected the reply to have'", expect, "'but got", str)
 				t.Error("Expected the reply to have'", expect, "'but got", str)
 			}
 			}
 		}
 		}
@@ -530,7 +531,7 @@ func TestGatewayPanic(t *testing.T) {
 				t.Error(err)
 				t.Error(err)
 			} else {
 			} else {
 				expect := "storage failed"
 				expect := "storage failed"
-				if strings.Index(str, expect) == -1 {
+				if !strings.Contains(str, expect) {
 					t.Error("Expected the reply to have'", expect, "'but got", str)
 					t.Error("Expected the reply to have'", expect, "'but got", str)
 				}
 				}
 			}
 			}

+ 1 - 1
tests/client.go

@@ -32,7 +32,7 @@ func Connect(serverConfig guerrilla.ServerConfig, deadline time.Duration) (net.C
 	bufin = bufio.NewReader(conn)
 	bufin = bufio.NewReader(conn)
 
 
 	// should be ample time to complete the test
 	// should be ample time to complete the test
-	if err = conn.SetDeadline(time.Now().Add(time.Duration(time.Second * deadline))); err != nil {
+	if err = conn.SetDeadline(time.Now().Add(time.Second * deadline)); err != nil {
 		return conn, bufin, err
 		return conn, bufin, err
 	}
 	}
 	// read greeting, ignore it
 	// read greeting, ignore it

+ 2 - 2
tests/guerrilla_test.go

@@ -249,7 +249,7 @@ func TestGreeting(t *testing.T) {
 			// handle error
 			// handle error
 			t.Error("Cannot dial server", config.Servers[0].ListenInterface)
 			t.Error("Cannot dial server", config.Servers[0].ListenInterface)
 		}
 		}
-		if err := conn.SetReadDeadline(time.Now().Add(time.Duration(time.Millisecond * 500))); err != nil {
+		if err := conn.SetReadDeadline(time.Now().Add(time.Millisecond * 500)); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 		greeting, err := bufio.NewReader(conn).ReadString('\n')
 		greeting, err := bufio.NewReader(conn).ReadString('\n')
@@ -276,7 +276,7 @@ func TestGreeting(t *testing.T) {
 			t.Error(err, "Cannot dial server (TLS)", config.Servers[1].ListenInterface)
 			t.Error(err, "Cannot dial server (TLS)", config.Servers[1].ListenInterface)
 			t.FailNow()
 			t.FailNow()
 		}
 		}
-		if err := conn.SetReadDeadline(time.Now().Add(time.Duration(time.Millisecond * 500))); err != nil {
+		if err := conn.SetReadDeadline(time.Now().Add(time.Millisecond * 500)); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 		greeting, err = bufio.NewReader(conn).ReadString('\n')
 		greeting, err = bufio.NewReader(conn).ReadString('\n')

+ 4 - 3
version.go

@@ -13,14 +13,15 @@ var (
 
 
 func init() {
 func init() {
 	// If version, commit, or build time are not set, make that clear.
 	// If version, commit, or build time are not set, make that clear.
+	const unknown = "unknown"
 	if Version == "" {
 	if Version == "" {
-		Version = "unknown"
+		Version = unknown
 	}
 	}
 	if Commit == "" {
 	if Commit == "" {
-		Commit = "unknown"
+		Commit = unknown
 	}
 	}
 	if BuildTime == "" {
 	if BuildTime == "" {
-		BuildTime = "unknown"
+		BuildTime = unknown
 	}
 	}
 
 
 	StartTime = time.Now()
 	StartTime = time.Now()