diff --git a/address.go b/address.go index 08c5046..1ffce35 100644 --- a/address.go +++ b/address.go @@ -5,6 +5,7 @@ import ( "strings" ) +// MailAddress holds an e-mail address type MailAddress string func parseMailAddress(src string) (MailAddress, error) { diff --git a/protocol.go b/protocol.go index 0c4ae2d..4c07fad 100644 --- a/protocol.go +++ b/protocol.go @@ -94,6 +94,11 @@ func (session *session) handleMAIL(cmd command) { return } + if !session.tls && session.server.ForceTLS { + session.reply(502, "Please turn on TLS by issuing a STARTTLS command.") + return + } + addr, err := parseMailAddress(cmd.params[1]) if err != nil { @@ -157,18 +162,18 @@ func (session *session) handleSTARTTLS(cmd command) { return } - tls_conn := tls.Server(session.conn, session.server.TLSConfig) + tlsConn := tls.Server(session.conn, session.server.TLSConfig) session.reply(250, "Go ahead") - if err := tls_conn.Handshake(); err != nil { + if err := tlsConn.Handshake(); err != nil { log.Printf("TLS Handshake error:", err) session.reply(550, "Handshake error") return } - session.conn = tls_conn - session.reader = bufio.NewReader(tls_conn) - session.writer = bufio.NewWriter(tls_conn) + session.conn = tlsConn + session.reader = bufio.NewReader(tlsConn) + session.writer = bufio.NewWriter(tlsConn) session.scanner = bufio.NewScanner(session.reader) session.tls = true @@ -206,6 +211,14 @@ func (session *session) handleDATA(cmd command) { return } + if data.Len() > session.server.MaxMessageSize { + session.reply(550, fmt.Sprintf( + "Message exceeded max message size of %d bytes", + session.server.MaxMessageSize, + )) + return + } + session.envelope.Data = data.Bytes() err := session.deliver() @@ -283,7 +296,7 @@ func (session *session) handleAUTH(cmd command) { return } - byte_username, err := base64.StdEncoding.DecodeString(session.scanner.Text()) + byteUsername, err := base64.StdEncoding.DecodeString(session.scanner.Text()) if err != nil { session.reply(502, "Couldn't decode your credentials") @@ -296,15 +309,15 @@ func (session *session) handleAUTH(cmd command) { return } - byte_password, err := base64.StdEncoding.DecodeString(session.scanner.Text()) + bytePassword, err := base64.StdEncoding.DecodeString(session.scanner.Text()) if err != nil { session.reply(502, "Couldn't decode your credentials") return } - username = string(byte_username) - password = string(byte_password) + username = string(byteUsername) + password = string(bytePassword) default: diff --git a/smtpd.go b/smtpd.go index 3de37cc..c2b0194 100644 --- a/smtpd.go +++ b/smtpd.go @@ -11,6 +11,7 @@ import ( "time" ) +// Server defines the parameters for running the SMTP server type Server struct { Addr string // Address to listen on when using ListenAndServe (default: "127.0.0.1:10025") WelcomeMessage string // Initial server banner (default: " ESMTP ready.") @@ -40,13 +41,15 @@ type Server struct { MaxMessageSize int // Max message size in bytes (default: 10240000) } +// Peer represents the client connecting to the server type Peer struct { HeloName string // Server name used in HELO/EHLO command - Username string // Username from authentication - Password string // Password from authentication + Username string // Username from authentication, if authenticated + Password string // Password from authentication, if authenticated Addr net.Addr // Network address } +// Envelope holds a message type Envelope struct { Sender MailAddress Recipients []MailAddress @@ -86,6 +89,7 @@ func (srv *Server) newSession(c net.Conn) (s *session, err error) { } +// ListenAndServe starts the SMTP server and listens on the address provided in Server.Addr func (srv *Server) ListenAndServe() error { srv.configureDefaults() @@ -98,6 +102,7 @@ func (srv *Server) ListenAndServe() error { return srv.Serve(l) } +// Serve starts the SMTP server and listens on the Listener provided func (srv *Server) Serve(l net.Listener) error { srv.configureDefaults() @@ -243,7 +248,7 @@ func (session *session) error(err error) { func (session *session) extensions() []string { extensions := []string{ - "SIZE 10240000", + fmt.Sprintf("SIZE %d", session.server.MaxMessageSize), } if session.server.TLSConfig != nil && !session.tls { @@ -261,9 +266,8 @@ func (session *session) extensions() []string { func (session *session) deliver() error { if session.server.Handler != nil { return session.server.Handler(session.peer, *session.envelope) - } else { - return nil } + return nil } func (session *session) close() {