|
@@ -55,14 +55,17 @@ 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) (*Client, error) {
|
|
58
|
+func Dial(addr string, timeout time.Duration, implicitTLS bool) (*Client, error) {
|
59
|
59
|
var conn net.Conn
|
60
|
60
|
var err error
|
|
61
|
+ dialer := net.Dialer{
|
|
62
|
+ Timeout: timeout,
|
|
63
|
+ }
|
61
|
64
|
start := time.Now()
|
62
|
|
- if timeout == 0 {
|
63
|
|
- conn, err = net.Dial("tcp", addr)
|
|
65
|
+ if !implicitTLS {
|
|
66
|
+ conn, err = dialer.Dial("tcp", addr)
|
64
|
67
|
} else {
|
65
|
|
- conn, err = net.DialTimeout("tcp", addr, timeout)
|
|
68
|
+ conn, err = tls.DialWithDialer(&dialer, "tcp", addr, nil)
|
66
|
69
|
}
|
67
|
70
|
if err != nil {
|
68
|
71
|
return nil, err
|
|
@@ -338,7 +341,7 @@ var testHookStartTLS func(*tls.Config) // nil, except for tests
|
338
|
341
|
// functionality. Higher-level packages exist outside of the standard
|
339
|
342
|
// library.
|
340
|
343
|
// XXX: modified in Ergo to add `requireTLS`, `heloDomain`, and `timeout` arguments
|
341
|
|
-func SendMail(addr string, a Auth, heloDomain string, from string, to []string, msg []byte, requireTLS bool, timeout time.Duration) error {
|
|
344
|
+func SendMail(addr string, a Auth, heloDomain string, from string, to []string, msg []byte, requireTLS, implicitTLS bool, timeout time.Duration) error {
|
342
|
345
|
if err := validateLine(from); err != nil {
|
343
|
346
|
return err
|
344
|
347
|
}
|
|
@@ -347,7 +350,7 @@ func SendMail(addr string, a Auth, heloDomain string, from string, to []string,
|
347
|
350
|
return err
|
348
|
351
|
}
|
349
|
352
|
}
|
350
|
|
- c, err := Dial(addr, timeout)
|
|
353
|
+ c, err := Dial(addr, timeout, implicitTLS)
|
351
|
354
|
if err != nil {
|
352
|
355
|
return err
|
353
|
356
|
}
|
|
@@ -355,23 +358,25 @@ func SendMail(addr string, a Auth, heloDomain string, from string, to []string,
|
355
|
358
|
if err = c.Hello(heloDomain); err != nil {
|
356
|
359
|
return err
|
357
|
360
|
}
|
358
|
|
- if ok, _ := c.Extension("STARTTLS"); ok {
|
359
|
|
- var config *tls.Config
|
360
|
|
- if requireTLS {
|
361
|
|
- config = &tls.Config{ServerName: c.serverName}
|
362
|
|
- } else {
|
363
|
|
- // if TLS isn't a hard requirement, don't verify the certificate either,
|
364
|
|
- // since a MITM attacker could just remove the STARTTLS advertisement
|
365
|
|
- config = &tls.Config{InsecureSkipVerify: true}
|
366
|
|
- }
|
367
|
|
- if testHookStartTLS != nil {
|
368
|
|
- testHookStartTLS(config)
|
369
|
|
- }
|
370
|
|
- if err = c.StartTLS(config); err != nil {
|
371
|
|
- return err
|
|
361
|
+ if !implicitTLS {
|
|
362
|
+ if ok, _ := c.Extension("STARTTLS"); ok {
|
|
363
|
+ var config *tls.Config
|
|
364
|
+ if requireTLS {
|
|
365
|
+ config = &tls.Config{ServerName: c.serverName}
|
|
366
|
+ } else {
|
|
367
|
+ // if TLS isn't a hard requirement, don't verify the certificate either,
|
|
368
|
+ // since a MITM attacker could just remove the STARTTLS advertisement
|
|
369
|
+ config = &tls.Config{InsecureSkipVerify: true}
|
|
370
|
+ }
|
|
371
|
+ if testHookStartTLS != nil {
|
|
372
|
+ testHookStartTLS(config)
|
|
373
|
+ }
|
|
374
|
+ if err = c.StartTLS(config); err != nil {
|
|
375
|
+ return err
|
|
376
|
+ }
|
|
377
|
+ } else if requireTLS {
|
|
378
|
+ return errors.New("TLS required, but not negotiated")
|
372
|
379
|
}
|
373
|
|
- } else if requireTLS {
|
374
|
|
- return errors.New("TLS required, but not negotiated")
|
375
|
380
|
}
|
376
|
381
|
if a != nil && c.ext != nil {
|
377
|
382
|
if _, ok := c.ext["AUTH"]; !ok {
|