Make Dialer's domain configurable

The net/smtp library sends "localhost" unless otherwise instructed. This
commit adds a new "LocalName" field to the Dialer struct that allows
users to override what gets sent with SMTP's HELO command.

Fixes #40
This commit is contained in:
Lorenzo Villani 2015-10-21 07:07:33 +02:00 committed by Alexandre Cesaro
parent b1e55520bf
commit c80f25c521
2 changed files with 31 additions and 1 deletions

23
smtp.go
View File

@ -24,6 +24,9 @@ type Dialer struct {
// TSLConfig represents the TLS configuration used for the TLS (when the // TSLConfig represents the TLS configuration used for the TLS (when the
// STARTTLS extension is used) or SSL connection. // STARTTLS extension is used) or SSL connection.
TLSConfig *tls.Config TLSConfig *tls.Config
// LocalName is the hostname sent to the SMTP server with the HELO command.
// By default, "localhost" is sent.
LocalName string
} }
// NewPlainDialer returns a Dialer. The given parameters are used to connect to // NewPlainDialer returns a Dialer. The given parameters are used to connect to
@ -77,6 +80,12 @@ func (d *Dialer) starttlsDial() (smtpClient, error) {
return nil, err return nil, err
} }
if d.LocalName != "" {
if err := c.Hello(d.LocalName); err != nil {
return nil, err
}
}
if ok, _ := c.Extension("STARTTLS"); ok { if ok, _ := c.Extension("STARTTLS"); ok {
if err := c.StartTLS(d.tlsConfig()); err != nil { if err := c.StartTLS(d.tlsConfig()); err != nil {
c.Close() c.Close()
@ -93,7 +102,18 @@ func (d *Dialer) sslDial() (smtpClient, error) {
return nil, err return nil, err
} }
return newClient(conn, d.Host) c, err := newClient(conn, d.Host)
if err != nil {
return nil, err
}
if d.LocalName != "" {
if err := c.Hello(d.LocalName); err != nil {
return nil, err
}
}
return c, nil
} }
func (d *Dialer) tlsConfig() *tls.Config { func (d *Dialer) tlsConfig() *tls.Config {
@ -164,6 +184,7 @@ var (
) )
type smtpClient interface { type smtpClient interface {
Hello(string) error
Extension(string) (bool, string) Extension(string) (bool, string)
StartTLS(*tls.Config) error StartTLS(*tls.Config) error
Auth(smtp.Auth) error Auth(smtp.Auth) error

View File

@ -56,8 +56,10 @@ func TestDialerSSL(t *testing.T) {
func TestDialerConfig(t *testing.T) { func TestDialerConfig(t *testing.T) {
d := NewPlainDialer(testHost, testPort, "user", "pwd") d := NewPlainDialer(testHost, testPort, "user", "pwd")
d.LocalName = "test"
d.TLSConfig = testConfig d.TLSConfig = testConfig
testSendMail(t, d, []string{ testSendMail(t, d, []string{
"Hello test",
"Extension STARTTLS", "Extension STARTTLS",
"StartTLS", "StartTLS",
"Extension AUTH", "Extension AUTH",
@ -75,8 +77,10 @@ func TestDialerConfig(t *testing.T) {
func TestDialerSSLConfig(t *testing.T) { func TestDialerSSLConfig(t *testing.T) {
d := NewPlainDialer(testHost, testSSLPort, "user", "pwd") d := NewPlainDialer(testHost, testSSLPort, "user", "pwd")
d.LocalName = "test"
d.TLSConfig = testConfig d.TLSConfig = testConfig
testSendMail(t, d, []string{ testSendMail(t, d, []string{
"Hello test",
"Extension AUTH", "Extension AUTH",
"Auth", "Auth",
"Mail " + testFrom, "Mail " + testFrom,
@ -118,6 +122,11 @@ type mockClient struct {
config *tls.Config config *tls.Config
} }
func (c *mockClient) Hello(localName string) error {
c.do("Hello " + localName)
return nil
}
func (c *mockClient) Extension(ext string) (bool, string) { func (c *mockClient) Extension(ext string) (bool, string) {
c.do("Extension " + ext) c.do("Extension " + ext)
return true, "" return true, ""