1
0
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:
Ralph Slooten
2025-07-24 17:04:15 +12:00
parent f3e3536cdb
commit e1ed21abff

View File

@@ -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
}