Skip to content

Commit

Permalink
Merge pull request #2143 from slingamn/emailsending.1
Browse files Browse the repository at this point in the history
fix #2142
  • Loading branch information
slingamn authored Apr 15, 2024
2 parents 15d686c + b426dd8 commit 74fa04c
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 7 deletions.
4 changes: 4 additions & 0 deletions default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ accounts:
sender: "[email protected]"
require-tls: true
helo-domain: "my.network" # defaults to server name if unset
# set to `tcp4` to force sending over IPv4, `tcp6` to force IPv6:
# protocol: "tcp4"
# set to force a specific source/local IPv4 or IPv6 address:
# local-address: "1.2.3.4"
# options to enable DKIM signing of outgoing emails (recommended, but
# requires creating a DNS entry for the public key):
# dkim:
Expand Down
24 changes: 23 additions & 1 deletion irc/email/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ type MailtoConfig struct {
Sender string
HeloDomain string `yaml:"helo-domain"`
RequireTLS bool `yaml:"require-tls"`
Protocol string `yaml:"protocol"`
LocalAddress string `yaml:"local-address"`
localAddress net.Addr
VerifyMessageSubject string `yaml:"verify-message-subject"`
DKIM DKIMConfig
MTAReal MTAConfig `yaml:"mta"`
Expand Down Expand Up @@ -159,6 +162,25 @@ func (config *MailtoConfig) Postprocess(heloDomain string) (err error) {
}
}

config.Protocol = strings.ToLower(config.Protocol)
if config.Protocol == "" {
config.Protocol = "tcp"
}
if !(config.Protocol == "tcp" || config.Protocol == "tcp4" || config.Protocol == "tcp6") {
return fmt.Errorf("Invalid protocol for email sending: `%s`", config.Protocol)
}

if config.LocalAddress != "" {
ipAddr := net.ParseIP(config.LocalAddress)
if ipAddr == nil {
return fmt.Errorf("Could not parse local-address for email sending: `%s`", config.LocalAddress)
}
config.localAddress = &net.TCPAddr{
IP: ipAddr,
Port: 0,
}
}

if config.MTAConfig.Server != "" {
// smarthost, nothing more to validate
return nil
Expand Down Expand Up @@ -241,6 +263,6 @@ func SendMail(config MailtoConfig, recipient string, msg []byte) (err error) {

return smtp.SendMail(
addr, auth, config.HeloDomain, config.Sender, []string{recipient}, msg,
config.RequireTLS, implicitTLS, config.Timeout,
config.RequireTLS, implicitTLS, config.Protocol, config.localAddress, config.Timeout,
)
}
13 changes: 7 additions & 6 deletions irc/smtp/smtp.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,18 @@ type Client struct {

// Dial returns a new Client connected to an SMTP server at addr.
// The addr must include a port, as in "mail.example.com:smtp".
func Dial(addr string, timeout time.Duration, implicitTLS bool) (*Client, error) {
func Dial(protocol, addr string, localAddress net.Addr, timeout time.Duration, implicitTLS bool) (*Client, error) {
var conn net.Conn
var err error
dialer := net.Dialer{
Timeout: timeout,
Timeout: timeout,
LocalAddr: localAddress,
}
start := time.Now()
if !implicitTLS {
conn, err = dialer.Dial("tcp", addr)
conn, err = dialer.Dial(protocol, addr)
} else {
conn, err = tls.DialWithDialer(&dialer, "tcp", addr, nil)
conn, err = tls.DialWithDialer(&dialer, protocol, addr, nil)
}
if err != nil {
return nil, err
Expand Down Expand Up @@ -341,7 +342,7 @@ var testHookStartTLS func(*tls.Config) // nil, except for tests
// functionality. Higher-level packages exist outside of the standard
// library.
// XXX: modified in Ergo to add `requireTLS`, `heloDomain`, and `timeout` arguments
func SendMail(addr string, a Auth, heloDomain string, from string, to []string, msg []byte, requireTLS, implicitTLS bool, timeout time.Duration) error {
func SendMail(addr string, a Auth, heloDomain string, from string, to []string, msg []byte, requireTLS, implicitTLS bool, protocol string, localAddress net.Addr, timeout time.Duration) error {
if err := validateLine(from); err != nil {
return err
}
Expand All @@ -350,7 +351,7 @@ func SendMail(addr string, a Auth, heloDomain string, from string, to []string,
return err
}
}
c, err := Dial(addr, timeout, implicitTLS)
c, err := Dial(protocol, addr, localAddress, timeout, implicitTLS)
if err != nil {
return err
}
Expand Down
4 changes: 4 additions & 0 deletions traditional.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,10 @@ accounts:
sender: "[email protected]"
require-tls: true
helo-domain: "my.network" # defaults to server name if unset
# set to `tcp4` to force sending over IPv4, `tcp6` to force IPv6:
# protocol: "tcp4"
# set to force a specific source/local IPv4 or IPv6 address:
# local-address: "1.2.3.4"
# options to enable DKIM signing of outgoing emails (recommended, but
# requires creating a DNS entry for the public key):
# dkim:
Expand Down

0 comments on commit 74fa04c

Please sign in to comment.