Skip to content

Commit

Permalink
server: Add BINARYMIME support
Browse files Browse the repository at this point in the history
  • Loading branch information
foxcpp authored and emersion committed Jul 7, 2020
1 parent 1a1f36a commit f9c7cbc
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 0 deletions.
11 changes: 11 additions & 0 deletions backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,20 @@ type Backend interface {
AnonymousLogin(state *ConnectionState) (Session, error)
}

type BodyType string

const (
Body7Bit BodyType = "7BIT"
Body8BitMIME BodyType = "8BITMIME"
BodyBinaryMIME BodyType = "BINARYMIME"
)

// MailOptions contains custom arguments that were
// passed as an argument to the MAIL command.
type MailOptions struct {
// Value of BODY= argument, 7BIT, 8BITMIME or BINARYMIME.
Body BodyType

// Size of the body. Can be 0 if not specified by client.
Size int

Expand Down
9 changes: 9 additions & 0 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ func (c *Conn) handleGreet(enhanced bool, arg string) {
if _, isTLS := c.TLSConnectionState(); isTLS && c.server.EnableREQUIRETLS {
caps = append(caps, "REQUIRETLS")
}
if c.server.EnableBINARYMIME {
caps = append(caps, "BINARYMIME")
}
if c.server.MaxMessageBytes > 0 {
caps = append(caps, fmt.Sprintf("SIZE %v", c.server.MaxMessageBytes))
}
Expand Down Expand Up @@ -350,11 +353,17 @@ func (c *Conn) handleMail(arg string) {
opts.RequireTLS = true
case "BODY":
switch value {
case "BINARYMIME":
if !c.server.EnableBINARYMIME {
c.WriteResponse(504, EnhancedCode{5, 5, 4}, "BINARYMIME is not implemented")
return
}
case "7BIT", "8BITMIME":
default:
c.WriteResponse(500, EnhancedCode{5, 5, 4}, "Unknown BODY value")
return
}
opts.Body = BodyType(value)
case "AUTH":
value, err := decodeXtext(value)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ type Server struct {
// Should be used only if backend supports it.
EnableREQUIRETLS bool

// Advertise BINARYMIME (RFC 3030) capability.
// Should be used only if backend supports it.
EnableBINARYMIME bool

// If set, the AUTH command will not be advertised and authentication
// attempts will be rejected. This setting overrides AllowInsecureAuth.
AuthDisabled bool
Expand Down
48 changes: 48 additions & 0 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1045,3 +1045,51 @@ func TestServer_Chunking_tooLongMessage(t *testing.T) {
t.Fatal("Invalid number of sent messages:", be.messages, be.anonmsgs)
}
}

func TestServer_Chunking_Binarymime(t *testing.T) {
be, s, c, scanner := testServerAuthenticated(t)
defer s.Close()
defer c.Close()
s.EnableBINARYMIME = true

io.WriteString(c, "MAIL FROM:<[email protected]> BODY=BINARYMIME\r\n")
scanner.Scan()
if !strings.HasPrefix(scanner.Text(), "250 ") {
t.Fatal("Invalid MAIL response:", scanner.Text())
}

io.WriteString(c, "RCPT TO:<[email protected]>\r\n")
scanner.Scan()
if !strings.HasPrefix(scanner.Text(), "250 ") {
t.Fatal("Invalid RCPT response:", scanner.Text())
}

io.WriteString(c, "BDAT 8\r\n")
io.WriteString(c, "Hey <3\r\n")
scanner.Scan()
if !strings.HasPrefix(scanner.Text(), "250 ") {
t.Fatal("Invalid BDAT response:", scanner.Text())
}

io.WriteString(c, "BDAT 8 LAST\r\n")
io.WriteString(c, "Hey :3\r\n")
scanner.Scan()
if !strings.HasPrefix(scanner.Text(), "250 ") {
t.Fatal("Invalid BDAT response:", scanner.Text())
}

if len(be.messages) != 1 || len(be.anonmsgs) != 0 {
t.Fatal("Invalid number of sent messages:", be.messages, be.anonmsgs)
}

msg := be.messages[0]
if msg.From != "[email protected]" {
t.Fatal("Invalid mail sender:", msg.From)
}
if len(msg.To) != 1 || msg.To[0] != "[email protected]" {
t.Fatal("Invalid mail recipients:", msg.To)
}
if want := "Hey <3\r\nHey :3\r\n"; string(msg.Data) != want {
t.Fatal("Invalid mail data:", string(msg.Data), msg.Data)
}
}
2 changes: 2 additions & 0 deletions smtp.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
// ENHANCEDSTATUSCODES RFC 2034
// SMTPUTF8 RFC 6531
// REQUIRETLS draft-ietf-uta-smtp-require-tls-09
// CHUNKING RFC 3030
// BINARYMIME RFC 3030
//
// LMTP (RFC 2033) is also supported.
//
Expand Down

0 comments on commit f9c7cbc

Please sign in to comment.