This commit is contained in:
Christian Joergensen 2014-07-14 14:51:31 +02:00
parent b9243e732a
commit 1dd26fbd96
3 changed files with 32 additions and 14 deletions

View file

@ -5,6 +5,7 @@ import (
"strings"
)
// MailAddress holds an e-mail address
type MailAddress string
func parseMailAddress(src string) (MailAddress, error) {

View file

@ -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:

View file

@ -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: "<hostname> 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() {