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
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/axllent/mailpit/internal/logger"
|
"github.com/axllent/mailpit/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -27,7 +31,7 @@ func Send(addr string, from string, to []string, msg []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !isSocket {
|
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)
|
conn, err := net.Dial("unix", socketPath)
|
||||||
@@ -69,3 +73,82 @@ func Send(addr string, from string, to []string, msg []byte) error {
|
|||||||
|
|
||||||
return nil
|
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