-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsmtp_server.go
86 lines (75 loc) · 2.19 KB
/
smtp_server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Copyright 2016 Team 254. All Rights Reserved.
// Author: [email protected] (Patrick Fairbank)
//
// SMTP server implementation for receiving messages and passing them to a listener via channel.
// Inspired by https://github.com/flashmob/go-guerrilla.
package main
import (
"bufio"
"fmt"
"log"
"net"
"net/http"
"strconv"
)
const (
maxMessageSizeBytes = 15728640
timeoutSec = 60
)
type SmtpServer struct {
hostName string
smtpPort int
httpPort int
messageReceivedChan chan *MailMessage
}
func NewSmtpServer(config *Config) *SmtpServer {
server := new(SmtpServer)
server.hostName = config.GetString("host_name")
server.smtpPort = config.GetInt("smtp_port")
server.httpPort = config.GetInt("http_port")
server.messageReceivedChan = make(chan *MailMessage, 10)
return server
}
// Starts the SMTP server and loops indefinitely.
func (server *SmtpServer) Run() {
// Start the local HTTP server that NGINX uses for auth.
go server.runNginxHttp()
// Start listening for SMTP connections.
listenAddress := fmt.Sprintf("0.0.0.0:%d", server.smtpPort)
listener, err := net.Listen("tcp", listenAddress)
if err != nil {
log.Fatalf("Cannot listen on port: %v", err)
} else {
log.Printf("SMTP server listening on %s", listenAddress)
}
// Loop forever over incoming connections.
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("SMTP accept error: %v", err)
continue
}
// Handle each incoming request in a new goroutine.
client := ClientSession{
server: server,
state: OPEN_STATE,
conn: conn,
bufin: bufio.NewReader(conn),
bufout: bufio.NewWriter(conn),
}
go client.HandleSession()
}
}
func (server *SmtpServer) runNginxHttp() {
http.Handle("/", server)
err := http.ListenAndServe(fmt.Sprintf("127.0.0.1:%d", server.httpPort), nil)
if err != nil {
log.Fatalf("HTTP server error: %v", err)
}
}
// Responds to NGINX's auth requests with a set of headers pointing to the SMTP server to proxy to.
func (server *SmtpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Auth-Status", "OK")
w.Header().Add("Auth-Server", "0.0.0.0")
w.Header().Add("Auth-Port", strconv.Itoa(server.smtpPort))
}