refactor: constructor functions

This commit is contained in:
2023-12-26 09:16:21 +01:00
parent 1371889d6d
commit 624a269454
3 changed files with 141 additions and 89 deletions
+67 -1
View File
@@ -3,10 +3,13 @@ package email
import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"fmt"
"io"
"net/smtp"
"slices"
"time"
)
const (
@@ -35,7 +38,7 @@ type EmailService struct {
dial SmtpDialFn
}
func NewMailService(config MailServiceConfig) *EmailService {
func NewInsecure(config MailServiceConfig) *EmailService {
return &EmailService{
auth: config.Auth,
host: config.Host,
@@ -49,6 +52,69 @@ func NewMailService(config MailServiceConfig) *EmailService {
}
}
var validCommonNames = []string{"ISRG Root X1", "R3", "DST Root CA X3"}
func NewSecure(config MailServiceConfig) *EmailService {
return &EmailService{
auth: config.Auth,
host: config.Host,
port: config.Port,
from: config.From,
tlsconfig: &tls.Config{
InsecureSkipVerify: true,
ServerName: config.Host,
VerifyConnection: func(cs tls.ConnectionState) error {
// // Check the server's common name
// for _, cert := range cs.PeerCertificates {
// log.Println("cert.DNSNames", cert.DNSNames)
// if err := cert.VerifyHostname(config.Host); err != nil {
// return fmt.Errorf("invalid common name: %w", err)
// }
// }
// Check the certificate chain
opts := x509.VerifyOptions{
Intermediates: x509.NewCertPool(),
}
for _, cert := range cs.PeerCertificates[1:] {
opts.Intermediates.AddCert(cert)
}
_, err := cs.PeerCertificates[0].Verify(opts)
if err != nil {
return fmt.Errorf("invalid certificate chain: %w", err)
}
// Iterate over the certificates again to perform custom checks
for _, cert := range cs.PeerCertificates {
// TODO: add more checks here...
if time.Now().After(cert.NotAfter) {
return fmt.Errorf("certificate has expired")
}
if time.Now().Add(30 * 24 * time.Hour).After(cert.NotAfter) {
return fmt.Errorf("certificate will expire within 30 days")
}
if !slices.Contains(validCommonNames, cert.Issuer.CommonName) {
return fmt.Errorf("certificate is not issued by a trusted CA")
}
// log.Println("cert.ExtKeyUsage", cert.ExtKeyUsage)
// if cert.KeyUsage&x509.KeyUsageDigitalSignature == 0 || len(cert.ExtKeyUsage) == 0 || !slices.Contains(cert.ExtKeyUsage, x509.ExtKeyUsageServerAuth) {
// log.Printf("%+v", cert)
// return fmt.Errorf("certificate cannot be used for server authentication")
// }
if cert.PublicKeyAlgorithm != x509.RSA {
return fmt.Errorf("unsupported public key algorithm")
}
}
return nil
},
},
dial: dial,
}
}
type MailServiceConfig struct {
Auth smtp.Auth
Host string