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:
@@ -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)
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
Reference in New Issue
Block a user