Skip to content

Commit

Permalink
fix issue #30
Browse files Browse the repository at this point in the history
  • Loading branch information
flashmob committed Mar 21, 2017
1 parent 14a83f6 commit ba404ee
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
3 changes: 3 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ type ServerConfig struct {
// LogFile is where the logs go. Use path to file, or "stderr", "stdout" or "off".
// defaults to AppConfig.Log file setting
LogFile string `json:"log_file,omitempty"`
// XClientOn when using a proxy such as Nginx, XCLIENT command is used to pass the
// original client's IP address & client's HELO
XClientOn bool `json:"xclient_on,omitempty"`

// The following used to watch certificate changes so that the TLS can be reloaded
_privateKeyFile_mtime int
Expand Down
18 changes: 18 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,24 @@ func (server *server) handleClient(client *client) {
quote := response.GetQuote()
client.sendResponse("214-OK\r\n" + quote)

case sc.XClientOn && strings.Index(cmd, "XCLIENT ") == 0:
if toks := strings.Split(input[8:], " "); len(toks) > 0 {
for i := range toks {
if vals := strings.Split(toks[i], "="); len(vals) == 2 {
if vals[1] == "[UNAVAILABLE]" {
// skip
continue
}
if vals[0] == "ADDR" {
client.RemoteIP = vals[1]
}
if vals[0] == "HELO" {
client.Helo = vals[1]
}
}
}
}
client.sendResponse(response.Canned.SuccessMailCmd)
case strings.Index(cmd, "MAIL FROM:") == 0:
if client.isInTransaction() {
client.sendResponse(response.Canned.FailNestedMailCmd)
Expand Down
51 changes: 51 additions & 0 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,56 @@ func TestHandleClient(t *testing.T) {
wg.Wait() // wait for handleClient to exit
}

func TestXClient(t *testing.T) {
var mainlog log.Logger
var logOpenError error
sc := getMockServerConfig()
sc.XClientOn = true
mainlog, logOpenError = log.GetLogger(sc.LogFile, "debug")
if logOpenError != nil {
mainlog.WithError(logOpenError).Errorf("Failed creating a logger for mock conn [%s]", sc.ListenInterface)
}
conn, server := getMockServerConn(sc, t)
// call the serve.handleClient() func in a goroutine.
client := NewClient(conn.Server, 1, mainlog, mail.NewPool(5))
var wg sync.WaitGroup
wg.Add(1)
go func() {
server.handleClient(client)
wg.Done()
}()
// Wait for the greeting from the server
r := textproto.NewReader(bufio.NewReader(conn.Client))
line, _ := r.ReadLine()
// fmt.Println(line)
w := textproto.NewWriter(bufio.NewWriter(conn.Client))
w.PrintfLine("HELO test.test.com")
line, _ = r.ReadLine()
//fmt.Println(line)
w.PrintfLine("XCLIENT ADDR=212.96.64.216 NAME=[UNAVAILABLE]")
line, _ = r.ReadLine()

if client.RemoteIP != "212.96.64.216" {
t.Error("client.RemoteIP should be 212.96.64.216, but got:", client.RemoteIP)
}
expected := "250 2.1.0 OK"
if strings.Index(line, expected) != 0 {
t.Error("expected", expected, "but got:", line)
}

// try malformed input
w.PrintfLine("XCLIENT c")
line, _ = r.ReadLine()

expected = "250 2.1.0 OK"
if strings.Index(line, expected) != 0 {
t.Error("expected", expected, "but got:", line)
}

w.PrintfLine("QUIT")
line, _ = r.ReadLine()
wg.Wait() // wait for handleClient to exit
}

// TODO
// - test github issue #44 and #42

0 comments on commit ba404ee

Please sign in to comment.