Browse Source

Merge pull request #2143 from slingamn/emailsending.1

fix #2142
master
Shivaram Lingamneni 2 weeks ago
parent
commit
74fa04c5ea
No account linked to committer's email address
4 changed files with 38 additions and 7 deletions
  1. 4
    0
      default.yaml
  2. 23
    1
      irc/email/email.go
  3. 7
    6
      irc/smtp/smtp.go
  4. 4
    0
      traditional.yaml

+ 4
- 0
default.yaml View File

@@ -409,6 +409,10 @@ accounts:
409 409
             sender: "admin@my.network"
410 410
             require-tls: true
411 411
             helo-domain: "my.network" # defaults to server name if unset
412
+            # set to `tcp4` to force sending over IPv4, `tcp6` to force IPv6:
413
+            # protocol: "tcp4"
414
+            # set to force a specific source/local IPv4 or IPv6 address:
415
+            # local-address: "1.2.3.4"
412 416
             # options to enable DKIM signing of outgoing emails (recommended, but
413 417
             # requires creating a DNS entry for the public key):
414 418
             # dkim:

+ 23
- 1
irc/email/email.go View File

@@ -75,6 +75,9 @@ type MailtoConfig struct {
75 75
 	Sender                 string
76 76
 	HeloDomain             string `yaml:"helo-domain"`
77 77
 	RequireTLS             bool   `yaml:"require-tls"`
78
+	Protocol               string `yaml:"protocol"`
79
+	LocalAddress           string `yaml:"local-address"`
80
+	localAddress           net.Addr
78 81
 	VerifyMessageSubject   string `yaml:"verify-message-subject"`
79 82
 	DKIM                   DKIMConfig
80 83
 	MTAReal                MTAConfig       `yaml:"mta"`
@@ -159,6 +162,25 @@ func (config *MailtoConfig) Postprocess(heloDomain string) (err error) {
159 162
 		}
160 163
 	}
161 164
 
165
+	config.Protocol = strings.ToLower(config.Protocol)
166
+	if config.Protocol == "" {
167
+		config.Protocol = "tcp"
168
+	}
169
+	if !(config.Protocol == "tcp" || config.Protocol == "tcp4" || config.Protocol == "tcp6") {
170
+		return fmt.Errorf("Invalid protocol for email sending: `%s`", config.Protocol)
171
+	}
172
+
173
+	if config.LocalAddress != "" {
174
+		ipAddr := net.ParseIP(config.LocalAddress)
175
+		if ipAddr == nil {
176
+			return fmt.Errorf("Could not parse local-address for email sending: `%s`", config.LocalAddress)
177
+		}
178
+		config.localAddress = &net.TCPAddr{
179
+			IP:   ipAddr,
180
+			Port: 0,
181
+		}
182
+	}
183
+
162 184
 	if config.MTAConfig.Server != "" {
163 185
 		// smarthost, nothing more to validate
164 186
 		return nil
@@ -241,6 +263,6 @@ func SendMail(config MailtoConfig, recipient string, msg []byte) (err error) {
241 263
 
242 264
 	return smtp.SendMail(
243 265
 		addr, auth, config.HeloDomain, config.Sender, []string{recipient}, msg,
244
-		config.RequireTLS, implicitTLS, config.Timeout,
266
+		config.RequireTLS, implicitTLS, config.Protocol, config.localAddress, config.Timeout,
245 267
 	)
246 268
 }

+ 7
- 6
irc/smtp/smtp.go View File

@@ -55,17 +55,18 @@ type Client struct {
55 55
 
56 56
 // Dial returns a new Client connected to an SMTP server at addr.
57 57
 // The addr must include a port, as in "mail.example.com:smtp".
58
-func Dial(addr string, timeout time.Duration, implicitTLS bool) (*Client, error) {
58
+func Dial(protocol, addr string, localAddress net.Addr, timeout time.Duration, implicitTLS bool) (*Client, error) {
59 59
 	var conn net.Conn
60 60
 	var err error
61 61
 	dialer := net.Dialer{
62
-		Timeout: timeout,
62
+		Timeout:   timeout,
63
+		LocalAddr: localAddress,
63 64
 	}
64 65
 	start := time.Now()
65 66
 	if !implicitTLS {
66
-		conn, err = dialer.Dial("tcp", addr)
67
+		conn, err = dialer.Dial(protocol, addr)
67 68
 	} else {
68
-		conn, err = tls.DialWithDialer(&dialer, "tcp", addr, nil)
69
+		conn, err = tls.DialWithDialer(&dialer, protocol, addr, nil)
69 70
 	}
70 71
 	if err != nil {
71 72
 		return nil, err
@@ -341,7 +342,7 @@ var testHookStartTLS func(*tls.Config) // nil, except for tests
341 342
 // functionality. Higher-level packages exist outside of the standard
342 343
 // library.
343 344
 // XXX: modified in Ergo to add `requireTLS`, `heloDomain`, and `timeout` arguments
344
-func SendMail(addr string, a Auth, heloDomain string, from string, to []string, msg []byte, requireTLS, implicitTLS bool, timeout time.Duration) error {
345
+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 {
345 346
 	if err := validateLine(from); err != nil {
346 347
 		return err
347 348
 	}
@@ -350,7 +351,7 @@ func SendMail(addr string, a Auth, heloDomain string, from string, to []string,
350 351
 			return err
351 352
 		}
352 353
 	}
353
-	c, err := Dial(addr, timeout, implicitTLS)
354
+	c, err := Dial(protocol, addr, localAddress, timeout, implicitTLS)
354 355
 	if err != nil {
355 356
 		return err
356 357
 	}

+ 4
- 0
traditional.yaml View File

@@ -381,6 +381,10 @@ accounts:
381 381
             sender: "admin@my.network"
382 382
             require-tls: true
383 383
             helo-domain: "my.network" # defaults to server name if unset
384
+            # set to `tcp4` to force sending over IPv4, `tcp6` to force IPv6:
385
+            # protocol: "tcp4"
386
+            # set to force a specific source/local IPv4 or IPv6 address:
387
+            # local-address: "1.2.3.4"
384 388
             # options to enable DKIM signing of outgoing emails (recommended, but
385 389
             # requires creating a DNS entry for the public key):
386 390
             # dkim:

Loading…
Cancel
Save