Chore: Set HELO/EHLO hostname when connecting to external SMTP server (#556)

When a message is forwarded or released, Mailpit introduces itself as
`localhost` to the upstream server. This happens because `net/smtp` forces the
value to be `localhost` if `client.Hello` is not called. This is explicitly
documented at https://pkg.go.dev/net/smtp#Client.Hello

Therefore, both `internal/smtpd/relay.go` (`createRelaySMTPClient`) and
`internal/smtpd/forward.go` (`createForwardingSMTPClient`) should either call
`client.Hello(os.Hostname())` or create a config (perhaps `config.HeloHostname`)
and use `client.Hello()` with that value immediately before returning from
either of those functions. (The HELO/EHLO command comes after TLS negotiation
but before any other SMTP commands.) This commit does the former.

Without this feature, Mailpit cannot be used in combination with Google
Workspace's SMTP Relay functionality, as it rejects any connection that
identifies itself as `localhost`.

Relates to #146
This commit is contained in:
Peter Krawczyk
2025-08-22 00:04:03 -04:00
committed by GitHub
parent 933d064a51
commit 8ce6fc0db5
2 changed files with 16 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ import (
"crypto/tls"
"fmt"
"net/smtp"
"os"
"strings"
"github.com/axllent/mailpit/config"
@@ -60,6 +61,13 @@ func createForwardingSMTPClient(config config.SMTPForwardConfigStruct, addr stri
}
}
// Set the hostname for HELO/EHLO
if hostname, err := os.Hostname(); err == nil {
if err := client.Hello(hostname); err != nil {
return nil, fmt.Errorf("error saying HELO/EHLO to %s: %v", addr, err)
}
}
// Note: The caller is responsible for closing the client
return client, nil
}

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net/smtp"
"os"
"strings"
"github.com/axllent/mailpit/config"
@@ -94,6 +95,13 @@ func createRelaySMTPClient(config config.SMTPRelayConfigStruct, addr string) (*s
}
}
// Set the hostname for HELO/EHLO
if hostname, err := os.Hostname(); err == nil {
if err := client.Hello(hostname); err != nil {
return nil, fmt.Errorf("error saying HELO/EHLO to %s: %v", addr, err)
}
}
// Note: The caller is responsible for closing the client
return client, nil
}