1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 17:47:03 +00:00

server: -netdebug flag now controls tracing for #90

Network trace is sent to stdout, no longer part of normal debug
logging.
This commit is contained in:
James Hillyerd
2018-03-31 13:37:42 -07:00
parent cbdb96a421
commit 92f2da5025
6 changed files with 56 additions and 52 deletions

View File

@@ -59,6 +59,7 @@ func main() {
pidfile := flag.String("pidfile", "", "Write our PID into the specified file.") pidfile := flag.String("pidfile", "", "Write our PID into the specified file.")
logfile := flag.String("logfile", "stderr", "Write out log into the specified file.") logfile := flag.String("logfile", "stderr", "Write out log into the specified file.")
logjson := flag.Bool("logjson", false, "Logs are written in JSON format.") logjson := flag.Bool("logjson", false, "Logs are written in JSON format.")
netdebug := flag.Bool("netdebug", false, "Dump SMTP & POP3 network traffic to stdout.")
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintln(os.Stderr, "Usage: inbucket [options]") fmt.Fprintln(os.Stderr, "Usage: inbucket [options]")
flag.PrintDefaults() flag.PrintDefaults()
@@ -89,6 +90,10 @@ func main() {
fmt.Fprintf(os.Stderr, "Configuration error: %v\n", err) fmt.Fprintf(os.Stderr, "Configuration error: %v\n", err)
os.Exit(1) os.Exit(1)
} }
if *netdebug {
conf.POP3.Debug = true
conf.SMTP.Debug = true
}
// Setup signal handler. // Setup signal handler.
sigChan := make(chan os.Signal, 1) sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGINT) signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGINT)

View File

@@ -45,6 +45,7 @@ type SMTP struct {
MaxMessageBytes int `required:"true" default:"10240000" desc:"Maximum message size"` MaxMessageBytes int `required:"true" default:"10240000" desc:"Maximum message size"`
StoreMessages bool `required:"true" default:"true" desc:"Store incoming mail?"` StoreMessages bool `required:"true" default:"true" desc:"Store incoming mail?"`
Timeout time.Duration `required:"true" default:"300s" desc:"Idle network timeout"` Timeout time.Duration `required:"true" default:"300s" desc:"Idle network timeout"`
Debug bool `ignored:"true"`
} }
// POP3 contains the POP3 server configuration. // POP3 contains the POP3 server configuration.
@@ -52,6 +53,7 @@ type POP3 struct {
Addr string `required:"true" default:"0.0.0.0:1100" desc:"POP3 server IP4 host:port"` Addr string `required:"true" default:"0.0.0.0:1100" desc:"POP3 server IP4 host:port"`
Domain string `required:"true" default:"inbucket" desc:"HELLO domain"` Domain string `required:"true" default:"inbucket" desc:"HELLO domain"`
Timeout time.Duration `required:"true" default:"600s" desc:"Idle network timeout"` Timeout time.Duration `required:"true" default:"600s" desc:"Idle network timeout"`
Debug bool `ignored:"true"`
} }
// Web contains the HTTP server configuration. // Web contains the HTTP server configuration.

View File

@@ -2,7 +2,6 @@ package pop3
import ( import (
"bufio" "bufio"
"bytes"
"fmt" "fmt"
"io" "io"
"net" "net"
@@ -58,26 +57,35 @@ var commands = map[string]bool{
// Session defines an active POP3 session // Session defines an active POP3 session
type Session struct { type Session struct {
server *Server // Reference to the server we belong to server *Server // Reference to the server we belong to.
id int // Session ID number id int // Session ID number.
conn net.Conn // Our network connection conn net.Conn // Our network connection.
remoteHost string // IP address of client remoteHost string // IP address of client.
sendError error // Used to bail out of read loop on send error sendError error // Used to bail out of read loop on send error.
state State // Current session state state State // Current session state.
reader *bufio.Reader // Buffered reader for our net conn reader *bufio.Reader // Buffered reader for our net conn.
user string // Mailbox name user string // Mailbox name.
messages []storage.Message // Slice of messages in mailbox messages []storage.Message // Slice of messages in mailbox.
retain []bool // Messages to retain upon UPDATE (true=retain) retain []bool // Messages to retain upon UPDATE (true=retain).
msgCount int // Number of undeleted messages msgCount int // Number of undeleted messages.
logger zerolog.Logger logger zerolog.Logger // Session specific logger.
debug bool // Print network traffic to stdout.
} }
// NewSession creates a new POP3 session // NewSession creates a new POP3 session
func NewSession(server *Server, id int, conn net.Conn, logger zerolog.Logger) *Session { func NewSession(server *Server, id int, conn net.Conn, logger zerolog.Logger) *Session {
reader := bufio.NewReader(conn) reader := bufio.NewReader(conn)
host, _, _ := net.SplitHostPort(conn.RemoteAddr().String()) host, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
return &Session{server: server, id: id, conn: conn, state: AUTHORIZATION, return &Session{
reader: reader, remoteHost: host, logger: logger} server: server,
id: id,
conn: conn,
state: AUTHORIZATION,
reader: reader,
remoteHost: host,
logger: logger,
debug: server.config.Debug,
}
} }
func (s *Session) String() string { func (s *Session) String() string {
@@ -550,41 +558,12 @@ func (s *Session) send(msg string) {
} }
if _, err := fmt.Fprint(s.conn, msg+"\r\n"); err != nil { if _, err := fmt.Fprint(s.conn, msg+"\r\n"); err != nil {
s.sendError = err s.sendError = err
s.logger.Warn().Msgf("Failed to send: '%v'", msg) s.logger.Warn().Msgf("Failed to send: %q", msg)
return return
} }
s.logger.Debug().Msgf(">> %v >>", msg) if s.debug {
} fmt.Printf("%04d > %v\n", s.id, msg)
// readByteLine reads a line of input into the provided buffer. Does
// not reset the Buffer - please do so prior to calling.
func (s *Session) readByteLine(buf *bytes.Buffer) error {
if err := s.conn.SetReadDeadline(s.nextDeadline()); err != nil {
return err
} }
for {
line, err := s.reader.ReadBytes('\r')
if err != nil {
return err
}
if _, err = buf.Write(line); err != nil {
return err
}
// Read the next byte looking for '\n'
c, err := s.reader.ReadByte()
if err != nil {
return err
}
if err := buf.WriteByte(c); err != nil {
return err
}
if c == '\n' {
// We've reached the end of the line, return
return nil
}
// Else, keep looking
}
// Should be unreachable
} }
// Reads a line of input // Reads a line of input
@@ -596,7 +575,9 @@ func (s *Session) readLine() (line string, err error) {
if err != nil { if err != nil {
return "", err return "", err
} }
s.logger.Debug().Msgf("<< %v <<", strings.TrimRight(line, "\r\n")) if s.debug {
fmt.Printf("%04d %v\n", s.id, strings.TrimRight(line, "\r\n"))
}
return line, nil return line, nil
} }

View File

@@ -13,6 +13,8 @@ import (
// Server defines an instance of our POP3 server // Server defines an instance of our POP3 server
type Server struct { type Server struct {
// TODO(#91) Refactor config items out of this struct
config config.POP3
host string host string
domain string domain string
timeout time.Duration timeout time.Duration
@@ -25,6 +27,7 @@ type Server struct {
// New creates a new Server struct // New creates a new Server struct
func New(cfg config.POP3, shutdownChan chan bool, store storage.Store) *Server { func New(cfg config.POP3, shutdownChan chan bool, store storage.Store) *Server {
return &Server{ return &Server{
config: cfg,
host: cfg.Addr, host: cfg.Addr,
domain: cfg.Domain, domain: cfg.Domain,
store: store, store: store,

View File

@@ -80,7 +80,8 @@ type Session struct {
reader *bufio.Reader reader *bufio.Reader
from string from string
recipients []*policy.Recipient recipients []*policy.Recipient
logger zerolog.Logger logger zerolog.Logger // Session specific logger.
debug bool // Print network traffic to stdout.
} }
// NewSession creates a new Session for the given connection // NewSession creates a new Session for the given connection
@@ -96,6 +97,7 @@ func NewSession(server *Server, id int, conn net.Conn, logger zerolog.Logger) *S
remoteHost: host, remoteHost: host,
recipients: make([]*policy.Recipient, 0), recipients: make([]*policy.Recipient, 0),
logger: logger, logger: logger,
debug: server.config.Debug,
} }
} }
@@ -433,7 +435,9 @@ func (s *Session) send(msg string) {
s.logger.Warn().Msgf("Failed to send: %q", msg) s.logger.Warn().Msgf("Failed to send: %q", msg)
return return
} }
s.logger.Debug().Msgf(">> %v >>", msg) if s.debug {
fmt.Printf("%04d > %v\n", s.id, msg)
}
} }
// readByteLine reads a line of input, returns byte slice. // readByteLine reads a line of input, returns byte slice.
@@ -441,7 +445,11 @@ func (s *Session) readByteLine() ([]byte, error) {
if err := s.conn.SetReadDeadline(s.nextDeadline()); err != nil { if err := s.conn.SetReadDeadline(s.nextDeadline()); err != nil {
return nil, err return nil, err
} }
return s.reader.ReadBytes('\n') b, err := s.reader.ReadBytes('\n')
if err == nil && s.debug {
fmt.Printf("%04d %s\n", s.id, bytes.TrimRight(b, "\r\n"))
}
return b, err
} }
// Reads a line of input // Reads a line of input
@@ -453,7 +461,9 @@ func (s *Session) readLine() (line string, err error) {
if err != nil { if err != nil {
return "", err return "", err
} }
s.logger.Debug().Msgf("<< %v <<", strings.TrimRight(line, "\r\n")) if s.debug {
fmt.Printf("%04d %v\n", s.id, strings.TrimRight(line, "\r\n"))
}
return line, nil return line, nil
} }

View File

@@ -38,6 +38,8 @@ func init() {
// Server holds the configuration and state of our SMTP server // Server holds the configuration and state of our SMTP server
type Server struct { type Server struct {
// TODO(#91) Refactor config items out of this struct
config config.SMTP
// Configuration // Configuration
host string host string
domain string domain string
@@ -86,6 +88,7 @@ func NewServer(
apolicy *policy.Addressing, apolicy *policy.Addressing,
) *Server { ) *Server {
return &Server{ return &Server{
config: cfg,
host: cfg.Addr, host: cfg.Addr,
domain: cfg.Domain, domain: cfg.Domain,
domainNoStore: strings.ToLower(cfg.DomainNoStore), domainNoStore: strings.ToLower(cfg.DomainNoStore),