From 8a6c86644e6d73421e325c937916cefe7495bc38 Mon Sep 17 00:00:00 2001
From: Dmitry Azhichakov <dmitry@dsa.pp.ru>
Date: Thu, 12 Feb 2015 18:54:51 +0300
Subject: [PATCH 1/3] New feature: SMTP connection may use client certificate.

New config keys in [mailer] section:
 - CERT_FILE: path to a certificate file.
 - KEY_FILE: path to a key file.
---
 modules/mailer/mailer.go   |  6 ++++++
 modules/setting/setting.go | 13 ++++++++-----
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go
index 6a23e5d09..792e44354 100644
--- a/modules/mailer/mailer.go
+++ b/modules/mailer/mailer.go
@@ -72,9 +72,15 @@ func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte)
 		return err
 	}
 
+	cert, err := tls.LoadX509KeyPair(settings.CertFile, settings.KeyFile)
+	if err != nil {
+		return err
+	}
+
 	tlsconfig := &tls.Config{
 		InsecureSkipVerify: settings.SkipVerify,
 		ServerName:         host,
+		Certificates:       []tls.Certificate{cert},
 	}
 
 	conn, err := net.Dial("tcp", net.JoinHostPort(host, port))
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index d71a8cda5..cf19b1aa8 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -446,11 +446,12 @@ func newSessionService() {
 
 // Mailer represents mail service.
 type Mailer struct {
-	Name         string
-	Host         string
-	From         string
-	User, Passwd string
-	SkipVerify   bool
+	Name              string
+	Host              string
+	From              string
+	User, Passwd      string
+	SkipVerify        bool
+	CertFile, KeyFile string
 }
 
 type OauthInfo struct {
@@ -483,6 +484,8 @@ func newMailService() {
 		User:       sec.Key("USER").String(),
 		Passwd:     sec.Key("PASSWD").String(),
 		SkipVerify: sec.Key("SKIP_VERIFY").MustBool(),
+		CertFile:   sec.Key("CERT_FILE").String(),
+		KeyFile:    sec.Key("KEY_FILE").String(),
 	}
 	MailService.From = sec.Key("FROM").MustString(MailService.User)
 	log.Info("Mail Service Enabled")

From 3aaf292ba8c222003048e695bf9b9ec43191ff01 Mon Sep 17 00:00:00 2001
From: Dmitry Azhichakov <dmitry@dsa.pp.ru>
Date: Fri, 13 Feb 2015 10:33:55 +0300
Subject: [PATCH 2/3] Fix "forcing" client certificate for SMTP

---
 conf/app.ini               |  4 ++++
 modules/mailer/mailer.go   | 14 ++++++++------
 modules/setting/setting.go | 16 +++++++++-------
 3 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/conf/app.ini b/conf/app.ini
index e80d77a9c..6a7c67ca0 100644
--- a/conf/app.ini
+++ b/conf/app.ini
@@ -105,6 +105,10 @@ SUBJECT = %(APP_NAME)s
 HOST =
 ; Do not verify the certificate of the server. Only use this for self-signed certificates
 SKIP_VERIFY = 
+; Use client certificate
+; USE_CERTIFICATE = true
+; CERT_FILE = custom/mailer/cert.pem
+; KEY_FILE = custom/mailer/key.pem
 ; Mail from address, RFC 5322. This can be just an email address, or the "Name" <email@example.com> format 
 FROM =
 ; Mailer user name and password
diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go
index 792e44354..f658427c1 100644
--- a/modules/mailer/mailer.go
+++ b/modules/mailer/mailer.go
@@ -72,15 +72,17 @@ func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte)
 		return err
 	}
 
-	cert, err := tls.LoadX509KeyPair(settings.CertFile, settings.KeyFile)
-	if err != nil {
-		return err
-	}
-
 	tlsconfig := &tls.Config{
 		InsecureSkipVerify: settings.SkipVerify,
 		ServerName:         host,
-		Certificates:       []tls.Certificate{cert},
+	}
+
+	if settings.UseCertificate {
+		cert, err := tls.LoadX509KeyPair(settings.CertFile, settings.KeyFile)
+		if err != nil {
+			return err
+		}
+		tlsconfig.Certificates = []tls.Certificate{cert}
 	}
 
 	conn, err := net.Dial("tcp", net.JoinHostPort(host, port))
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index cf19b1aa8..32284b423 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -451,6 +451,7 @@ type Mailer struct {
 	From              string
 	User, Passwd      string
 	SkipVerify        bool
+	UseCertificate    bool
 	CertFile, KeyFile string
 }
 
@@ -479,13 +480,14 @@ func newMailService() {
 	}
 
 	MailService = &Mailer{
-		Name:       sec.Key("NAME").MustString(AppName),
-		Host:       sec.Key("HOST").String(),
-		User:       sec.Key("USER").String(),
-		Passwd:     sec.Key("PASSWD").String(),
-		SkipVerify: sec.Key("SKIP_VERIFY").MustBool(),
-		CertFile:   sec.Key("CERT_FILE").String(),
-		KeyFile:    sec.Key("KEY_FILE").String(),
+		Name:           sec.Key("NAME").MustString(AppName),
+		Host:           sec.Key("HOST").String(),
+		User:           sec.Key("USER").String(),
+		Passwd:         sec.Key("PASSWD").String(),
+		SkipVerify:     sec.Key("SKIP_VERIFY").MustBool(),
+		UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
+		CertFile:       sec.Key("CERT_FILE").String(),
+		KeyFile:        sec.Key("KEY_FILE").String(),
 	}
 	MailService.From = sec.Key("FROM").MustString(MailService.User)
 	log.Info("Mail Service Enabled")

From 2692d4aa49deec286058cd2196da379a97534787 Mon Sep 17 00:00:00 2001
From: Dmitry Azhichakov <dmitry@dsa.pp.ru>
Date: Fri, 13 Feb 2015 11:06:12 +0300
Subject: [PATCH 3/3] Make conf/app.ini changes match the style

---
 conf/app.ini | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/conf/app.ini b/conf/app.ini
index 6a7c67ca0..6f4ae897f 100644
--- a/conf/app.ini
+++ b/conf/app.ini
@@ -106,9 +106,9 @@ HOST =
 ; Do not verify the certificate of the server. Only use this for self-signed certificates
 SKIP_VERIFY = 
 ; Use client certificate
-; USE_CERTIFICATE = true
-; CERT_FILE = custom/mailer/cert.pem
-; KEY_FILE = custom/mailer/key.pem
+USE_CERTIFICATE = false
+CERT_FILE = custom/mailer/cert.pem
+KEY_FILE = custom/mailer/key.pem
 ; Mail from address, RFC 5322. This can be just an email address, or the "Name" <email@example.com> format 
 FROM =
 ; Mailer user name and password