Browse Source

pkg/mailer: support plaintext alt for HTML emails (#5568)

* Added option to use plain text alt to HTML emails. Should make the messages friendlier for spam filters.

* Check that plaintext conversion worked before adding the HTML alt

* Add description of ADD_PLAIN_TEXT_ALT to app.ini

* Added comment clarifying html AddAlternative
Guy Smoilov 6 years ago
parent
commit
5702e4bc24
3 changed files with 25 additions and 13 deletions
  1. 2 0
      conf/app.ini
  2. 9 1
      pkg/mailer/mailer.go
  3. 14 12
      pkg/setting/setting.go

+ 2 - 0
conf/app.ini

@@ -250,6 +250,8 @@ USER =
 PASSWD =
 ; Use text/plain as format of content
 USE_PLAIN_TEXT = false
+; If sending html emails, then also attach a plaintext alternative to the MIME message, to support older mail clients and make spam filters happier.
+ADD_PLAIN_TEXT_ALT = false
 
 [cache]
 ; Either "memory", "redis", or "memcache", default is "memory"

+ 9 - 1
pkg/mailer/mailer.go

@@ -39,16 +39,24 @@ func NewMessageFrom(to []string, from, subject, htmlBody string) *Message {
 
 	contentType := "text/html"
 	body := htmlBody
-	if setting.MailService.UsePlainText {
+	switchedToPlaintext := false
+	if setting.MailService.UsePlainText || setting.MailService.AddPlainTextAlt {
 		plainBody, err := html2text.FromString(htmlBody)
 		if err != nil {
 			log.Error(2, "html2text.FromString: %v", err)
 		} else {
 			contentType = "text/plain"
 			body = plainBody
+			switchedToPlaintext = true
 		}
 	}
 	msg.SetBody(contentType, body)
+	if switchedToPlaintext && setting.MailService.AddPlainTextAlt && !setting.MailService.UsePlainText {
+		// The AddAlternative method name is confusing - adding html as an "alternative" will actually cause mail 
+		// clients to show it as first priority, and the text "main body" is the 2nd priority fallback.
+		// See: https://godoc.org/gopkg.in/gomail.v2#Message.AddAlternative
+		msg.AddAlternative("text/html", htmlBody)
+	}
 	return &Message{
 		Message:     msg,
 		confirmChan: make(chan struct{}),

+ 14 - 12
pkg/setting/setting.go

@@ -861,6 +861,7 @@ type Mailer struct {
 	UseCertificate    bool
 	CertFile, KeyFile string
 	UsePlainText      bool
+	AddPlainTextAlt   bool
 }
 
 var (
@@ -876,18 +877,19 @@ func newMailService() {
 	}
 
 	MailService = &Mailer{
-		QueueLength:    sec.Key("SEND_BUFFER_LEN").MustInt(100),
-		SubjectPrefix:  sec.Key("SUBJECT_PREFIX").MustString("[" + AppName + "] "),
-		Host:           sec.Key("HOST").String(),
-		User:           sec.Key("USER").String(),
-		Passwd:         sec.Key("PASSWD").String(),
-		DisableHelo:    sec.Key("DISABLE_HELO").MustBool(),
-		HeloHostname:   sec.Key("HELO_HOSTNAME").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(),
-		UsePlainText:   sec.Key("USE_PLAIN_TEXT").MustBool(),
+		QueueLength:     sec.Key("SEND_BUFFER_LEN").MustInt(100),
+		SubjectPrefix:   sec.Key("SUBJECT_PREFIX").MustString("[" + AppName + "] "),
+		Host:            sec.Key("HOST").String(),
+		User:            sec.Key("USER").String(),
+		Passwd:          sec.Key("PASSWD").String(),
+		DisableHelo:     sec.Key("DISABLE_HELO").MustBool(),
+		HeloHostname:    sec.Key("HELO_HOSTNAME").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(),
+		UsePlainText:    sec.Key("USE_PLAIN_TEXT").MustBool(),
+		AddPlainTextAlt: sec.Key("ADD_PLAIN_TEXT_ALT").MustBool(),
 	}
 	MailService.From = sec.Key("FROM").MustString(MailService.User)