Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some smtp vendor request a ssl connect but does't require a CA file. … #157

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion cfg_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const (
userPassID = "password"
cACertDirpathID = "cacertdirpath"
subjectID = "subject"
sslEnabledId = "ssl"
splitterDispatcherID = "splitter"
consoleWriterID = "console"
customReceiverID = "custom"
Expand Down Expand Up @@ -779,7 +780,7 @@ func createfileWriter(node *xmlNode, formatFromParent *formatter, formats map[st

// Creates new SMTP writer if encountered in the config file.
func createSMTPWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
err := checkUnexpectedAttribute(node, outputFormatID, senderaddressID, senderNameID, hostNameID, hostPortID, userNameID, userPassID, subjectID)
err := checkUnexpectedAttribute(node, outputFormatID, senderaddressID, senderNameID, hostNameID, hostPortID, userNameID, userPassID, subjectID, sslEnabledId)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -872,6 +873,19 @@ func createSMTPWriter(node *xmlNode, formatFromParent *formatter, formats map[st
subjectPhrase = subject
}

// sslEnabled is optionally set by configuration.
// considering the situation of sending email via ssl connection without a CA file.
// default is false
var sslEnabled = false

sslEnabledStr, ok := node.attributes[sslEnabledId]
if ok {
sslEnabled, err = strconv.ParseBool(sslEnabledStr)
if err != nil {
return nil, errors.New("only true/false can be set in ssl field")
}
}

smtpWriter := NewSMTPWriter(
senderAddress,
senderName,
Expand All @@ -883,6 +897,7 @@ func createSMTPWriter(node *xmlNode, formatFromParent *formatter, formats map[st
caCertDirPaths,
subjectPhrase,
mailHeaders,
sslEnabled,
)

return NewFormattedWriter(smtpWriter, currentFormat)
Expand Down
65 changes: 54 additions & 11 deletions writers_smtpwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"net/smtp"
"path/filepath"
"strings"
"net"
)

const (
Expand All @@ -55,10 +56,11 @@ type smtpWriter struct {
caCertDirPaths []string
mailHeaders []string
subject string
sslEnabled bool
}

// NewSMTPWriter returns a new SMTP-writer.
func NewSMTPWriter(sa, sn string, ras []string, hn, hp, un, pwd string, cacdps []string, subj string, headers []string) *smtpWriter {
func NewSMTPWriter(sa, sn string, ras []string, hn, hp, un, pwd string, cacdps []string, subj string, headers []string, ssl bool) *smtpWriter {
return &smtpWriter{
auth: smtp.PlainAuth("", un, pwd, hn),
hostName: hn,
Expand All @@ -70,6 +72,7 @@ func NewSMTPWriter(sa, sn string, ras []string, hn, hp, un, pwd string, cacdps [
caCertDirPaths: cacdps,
subject: subj,
mailHeaders: headers,
sslEnabled: ssl,
}
}

Expand All @@ -83,6 +86,17 @@ func prepareMessage(senderAddr, senderName, subject string, body []byte, headers
return append([]byte(headerLines), body...)
}

// getSimpleTLSConfig sets InsecureSkipVerify as true if no CA is given and ssl is necessary.
// tls accepts any certificate presented by the server and any host name in that certificate
func getSimpleTLSConfig(hostName string) (config *tls.Config) {
config = &tls.Config {
InsecureSkipVerify: true,
ServerName: hostName,
}

return
}

// getTLSConfig gets paths of PEM files with certificates,
// host server name and tries to create an appropriate TLS.Config.
func getTLSConfig(pemFileDirPaths []string, hostName string) (config *tls.Config, err error) {
Expand Down Expand Up @@ -131,9 +145,26 @@ func getTLSConfig(pemFileDirPaths []string, hostName string) (config *tls.Config
// switches to TLS if possible, authenticates with mechanism a if possible,
// and then sends an email from address from, to addresses to, with message msg.
func sendMailWithTLSConfig(config *tls.Config, addr string, a smtp.Auth, from string, to []string, msg []byte) error {
c, err := smtp.Dial(addr)
if err != nil {
return err
var c *smtp.Client
var err error

if config.InsecureSkipVerify {
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
return err
}

host, _, _ := net.SplitHostPort(addr)

c, err = smtp.NewClient(conn, host)
if err != nil {
return err
}
} else {
c, err = smtp.Dial(addr)
if err != nil {
return err
}
}
// Check if the server supports STARTTLS extension.
if ok, _ := c.Extension("STARTTLS"); ok {
Expand Down Expand Up @@ -180,13 +211,25 @@ func (smtpw *smtpWriter) Write(data []byte) (int, error) {
var err error

if smtpw.caCertDirPaths == nil {
err = smtp.SendMail(
smtpw.hostNameWithPort,
smtpw.auth,
smtpw.senderAddress,
smtpw.recipientAddresses,
prepareMessage(smtpw.senderAddress, smtpw.senderName, smtpw.subject, data, smtpw.mailHeaders),
)
if smtpw.sslEnabled {
config := getSimpleTLSConfig(smtpw.hostName)
err = sendMailWithTLSConfig(
config,
smtpw.hostNameWithPort,
smtpw.auth,
smtpw.senderAddress,
smtpw.recipientAddresses,
prepareMessage(smtpw.senderAddress, smtpw.senderName, smtpw.subject, data, smtpw.mailHeaders),
)
} else {
err = smtp.SendMail(
smtpw.hostNameWithPort,
smtpw.auth,
smtpw.senderAddress,
smtpw.recipientAddresses,
prepareMessage(smtpw.senderAddress, smtpw.senderName, smtpw.subject, data, smtpw.mailHeaders),
)
}
} else {
config, e := getTLSConfig(smtpw.caCertDirPaths, smtpw.hostName)
if e != nil {
Expand Down