Skip to content
This repository was archived by the owner on Jan 20, 2024. It is now read-only.

Commit 2030d5e

Browse files
authored
Merge pull request #9 from Ackar/empty-from
Allow empty `FROM`
2 parents b611bb5 + bb5f4fe commit 2030d5e

3 files changed

Lines changed: 22 additions & 12 deletions

File tree

processors.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,31 @@ func mailProcessor(req *Request) error {
135135
return req.TextProto.PrintfLine("%d %s", 501, "MAIL command contained invalid address")
136136
}
137137

138-
// extraxt the from email address
139-
from := emailRegExp.FindStringSubmatch(req.Line[1][i+1:])[1]
140-
fromParts := strings.SplitN(from, "@", 2)
138+
req.MailFromReceived = true
141139

140+
// extract the from email address
141+
fromParts := emailRegExp.FindStringSubmatch(strings.TrimSpace(req.Line[1][i+1:]))
142+
143+
from := fromParts[1]
142144
req.From = from
143-
ip, _, _ := net.SplitHostPort(req.RemoteAddr)
144145

145-
// check the spf result
146-
req.SPFResult, _, _ = spf.CheckHost(net.ParseIP(ip), fromParts[1], from)
146+
if from != "" {
147+
ip, _, _ := net.SplitHostPort(req.RemoteAddr)
148+
149+
// check the spf result
150+
domain := fromParts[3]
151+
req.SPFResult, _, _ = spf.CheckHost(net.ParseIP(ip), domain, from)
147152

148-
// check the mx records of the from hostname
149-
mxs, err := net.LookupMX(fromParts[1])
150-
req.Mailable = (err == nil) && len(mxs) > 0
153+
// check the mx records of the from hostname
154+
mxs, err := net.LookupMX(domain)
155+
req.Mailable = (err == nil) && len(mxs) > 0
156+
}
151157

152158
return req.TextProto.PrintfLine("%d %s", 250, "Ok")
153159
}
154160

155161
func rcptProcessor(req *Request) error {
156-
if req.From == "" {
162+
if !req.MailFromReceived {
157163
return req.TextProto.PrintfLine("%d %s", 503, "Bad sequence of commands")
158164
}
159165
if len(req.Line) < 2 {
@@ -177,7 +183,7 @@ func rcptProcessor(req *Request) error {
177183
}
178184

179185
func dataProcessor(req *Request) error {
180-
if req.To == nil || req.From == "" || len(req.To) == 0 {
186+
if req.To == nil || len(req.To) == 0 || !req.MailFromReceived {
181187
return req.TextProto.PrintfLine("%d %s", 503, "Bad sequence of commands")
182188
}
183189
err := req.TextProto.PrintfLine("%d %s", 354, "End data with <CR><LF>.<CR><LF>")

request.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ type Request struct {
3333
// whether EHLO/HELO called or not
3434
HelloRecieved bool
3535

36+
// whether MAIL FROM was received or not
37+
MailFromReceived bool
38+
3639
// the login username used for login, empty means that this is an anonymous attempt
3740
AuthUser string
3841

@@ -93,6 +96,7 @@ func (req *Request) Serve() {
9396
// Reset resets to the defaults
9497
func (req *Request) Reset() {
9598
req.From = ""
99+
req.MailFromReceived = false
96100
req.To = make([]string, 0)
97101
req.Message = nil
98102
}

vars.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ var (
3636
)
3737

3838
var (
39-
emailRegExp = regexp.MustCompile(`^<((\S+)@(\S+))>$`)
39+
emailRegExp = regexp.MustCompile(`^<((\S+)@(\S+))?>$`)
4040
)

0 commit comments

Comments
 (0)