mirror of
https://github.com/axllent/mailpit.git
synced 2025-08-13 20:04:49 +02:00
Chore: Allow sendmail to send to untrusted TLS server
This commit is contained in:
@@ -2,11 +2,15 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/mail"
|
||||
"net/smtp"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/axllent/mailpit/internal/logger"
|
||||
)
|
||||
@@ -27,7 +31,7 @@ func Send(addr string, from string, to []string, msg []byte) error {
|
||||
}
|
||||
|
||||
if !isSocket {
|
||||
return smtp.SendMail(addr, nil, fromAddress.Address, to, msg)
|
||||
return sendMail(addr, nil, fromAddress.Address, to, msg)
|
||||
}
|
||||
|
||||
conn, err := net.Dial("unix", socketPath)
|
||||
@@ -69,3 +73,82 @@ func Send(addr string, from string, to []string, msg []byte) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendMail(addr string, a smtp.Auth, from string, to []string, msg []byte) error {
|
||||
addrParsed, err := url.Parse(addr) // ensure addr is a valid URL
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid address: %s", addr)
|
||||
}
|
||||
|
||||
host := addrParsed.Host
|
||||
if err := validateLine(from); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, recipient := range to {
|
||||
if err := validateLine(recipient); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
c, err := smtp.Dial(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = c.Close() }()
|
||||
|
||||
if err = c.Hello(addr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ok, _ := c.Extension("STARTTLS"); ok {
|
||||
config := &tls.Config{ServerName: host, InsecureSkipVerify: true} // #nosec
|
||||
if err = c.StartTLS(config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if a != nil {
|
||||
if ok, _ := c.Extension("AUTH"); !ok {
|
||||
return errors.New("smtp: server doesn't support AUTH")
|
||||
}
|
||||
if err = c.Auth(a); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = c.Mail(from); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, addr := range to {
|
||||
if err = c.Rcpt(addr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
w, err := c.Data()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = w.Write(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Quit()
|
||||
}
|
||||
|
||||
// validateLine checks to see if a line has CR or LF as per RFC 5321.
|
||||
func validateLine(line string) error {
|
||||
if strings.ContainsAny(line, "\n\r") {
|
||||
return errors.New("smtp: A line must not contain CR or LF")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user