emersion / go-smtp

📤 An SMTP client & server library written in Go
MIT License
1.72k stars 216 forks source link

Critical bug in v0.20.1: i/o timeout in `DATA` stage #247

Closed iredmail closed 8 months ago

iredmail commented 9 months ago

Note:

In Session interface, DATA method (https://github.com/emersion/go-smtp/blob/master/backend.go#L50C25-L50C25), reading full message with io.ReadAll() always fails with error i/o timeout.

Postfix (acts as smtp client in our case) gets error message: xxxxxx (in reply to end of DATA command) (xxxxxx is our custom error message returned by go-smtp server code).

Using smtp-debug-server for example (https://github.com/emersion/go-smtp/blob/master/cmd/smtp-debug-server/main.go#L38):

func (s *session) Data(r io.Reader) error {
    _, err := io.ReadAll(r)             // It always fail with error `i/o timeout`.

    return nil
}
emersion commented 9 months ago

i/o timeout would typically happen if the final DATA dot is not received. Are you sure that the final dot is sent with a CRLF instead of lone LFs? That is, the final DATA dot must be \r\n.\r\n and not \n.\n.

This change is by-design to protect against SMTP smuggling attacks.

iredmail commented 9 months ago

i/o timeout would typically happen if the final DATA dot is not received. Are you sure that the final dot is sent with a CRLF instead of lone LFs? That is, the final DATA dot must be \r\n.\r\n and not \n.\n.

This change is by-design to protect against SMTP smuggling attacks.

The email was sent by Postfix, and all other emails sent by same Postfix server work fine, so i assume it sends correct smtp commands.

iredmail commented 8 months ago

Interesting, this issue was fixed by #250 (Tested on production server with latest git version of go-smtp).