Golang邮件模板正文格式不正确问题如何解决

Golang邮件模板正文格式不正确问题如何解决 大家好,

我编写了这段使用模板发送邮件的Go代码,以便将来如果需要添加更多变量或让他人查看时,只需修改模板即可,这样会更方便。

package main

import (
	"bytes"
	"strings"
	"text/template"
	"net/smtp"
	"log"
)

type Email_struct struct {
	Status      string
	App         string
	Project     string
	TargetEnv   string
	AppVersion  string
	Url string
}

func SendmaiL(emailTo string, e Email_struct) bool {	
	from := "noreply@domain.com"
	to := []string{
		emailTo,
	}

	var tmplFile = "email.tmpl"
	tmpl, err := template.New(tmplFile).ParseFiles(tmplFile)
	if err != nil {
		panic(err)
	}
	var tpl bytes.Buffer
	if err := tmpl.Execute(&tpl, e); err != nil {
		panic(err)
	}
	message := tpl.Bytes()
	log.Print(string(message[:])) // print

	// Sending email.
  	errs := smtp.SendMail("mail.domain.com:25", nil, from, to, message) 
  	if errs != nil {
		log.Println(errs)
		return false
  	}
	return true
}

func main() {
	// nl := "\r"

	em := Email_struct{}
	em.Status = "Synced"
	app := "pipeline-gitops-notification-sit"
	em.App = app
	// em.Project = app + nl
	em.Project = app
	GitopsFolder := "gitops/sit"
	extractTargetEnv := strings.Split(GitopsFolder, "/") 
	// em.TargetEnv = extractTargetEnv[1] + nl
	em.TargetEnv = extractTargetEnv[1] 
	mes := "Manifest-63db30e: qa-0.0.110 by user@domain.com"
	extractVersion1 := strings.Split(mes, "-")
	extractVersion2 := strings.Split(extractVersion1[2], ".")
	extractVersion3 := strings.Split(extractVersion2[2], " ")
	// em.AppVersion = extractVersion2[0]+"."+extractVersion2[1]+"."+extractVersion3[0]  + nl
	em.AppVersion = extractVersion2[0]+"."+extractVersion2[1]+"."+extractVersion3[0] 
	RepoUrl := "https://cd.toronto.ca:6443/devops/pipeline/gitops-notification.git"
	em.Url = RepoUrl

	success := SendmaiL("user@domain.com", em) 
	if success {
		log.Println("Email SUCCESS to sent!")
	} else {
		log.Println("Email FAILED to send!")
	}

}

使用一个模板文件 email.tmpl

Subject: [{{ .Status }}] app {{ .App }} has been synced by argoCD

Project: {{ .Project }}
Target : {{ .TargetEnv }}
Version: {{ .AppVersion }}
URL: {{ .Url }}

Best regards,
Devops Team

期望的邮件正文应该是(主题没问题),

Project: PPPPPPPPPPPPPPPPP
Target : TTTTTTTTTTTTTTTTT
Version: VVVVVVVVVVVVVVVVV
URL: UUUUUUUUUUUUUUUUUUUU

Best regards,
Devops Team

但它却变成了一行,

Project: PPPPPPPPPPPPPPPPP Target : TTTTTTTTTTTTTTTTT Version: VVVVVVVVVVVVVVVVV URL: UUUUUUUUUUUUUUUUUUUU

Best regards,
Devops Team

如果我启用 nl := “\r”nl := “\n” 甚至两者都用。输出会是,

Project: PPPPPPPPPPPPPPPPP

Target : TTTTTTTTTTTTTTTTT

Version: VVVVVVVVVVVVVVVVV

URL: UUUUUUUUUUUUUUUUUUUU

Best regards,
Devops Team

这样看起来不美观。

请帮忙。

谢谢, Ric


更多关于Golang邮件模板正文格式不正确问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

确保您的模板为预期的电子邮件客户端使用适当的换行符。在将内容包含到模板之前,您可以使用诸如 strings.ReplaceAll("\n", "\r\n", body) 这样的字符串函数将换行符转换为所需的格式。

strings.ReplaceAll("\n", "\r\n", body)

更多关于Golang邮件模板正文格式不正确问题如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Ricky_V:

Project: PPPPPPPPPPPPPPPPP
Target : TTTTTTTTTTTTTTTTT
Version: VVVVVVVVVVVVVVVVV
URL: UUUUUUUUUUUUUUUUUUUU

Best regards,
Devops Team

实际上这工作得很好,只是在我实际使用时,目标是“Target Env”,但当我把它写成“Target-Env”时,它就能正常工作了。

问题出在模板文件中的换行符被 text/template 解析时处理掉了。text/template 默认会去除模板标签周围的空白字符,导致换行丢失。

以下是解决方案:

方案1:在模板中使用显式换行符 修改模板文件,在每行末尾添加 {{"\n"}}

Subject: [{{ .Status }}] app {{ .App }} has been synced by argoCD

Project: {{ .Project }}{{"\n"}}
Target : {{ .TargetEnv }}{{"\n"}}
Version: {{ .AppVersion }}{{"\n"}}
URL: {{ .Url }}{{"\n"}}

Best regards,
Devops Team

方案2:使用 template 包的 {{--}} 语法控制空白 修改模板文件,在模板标签前后添加空白控制符:

Subject: [{{ .Status }}] app {{ .App }} has been synced by argoCD

Project: {{ .Project -}}
Target : {{ .TargetEnv -}}
Version: {{ .AppVersion -}}
URL: {{ .Url -}}

Best regards,
Devops Team

方案3:在代码中处理换行 保持模板文件不变,在结构体字段值中直接包含换行符:

em.Project = app + "\n"
em.TargetEnv = extractTargetEnv[1] + "\n"
em.AppVersion = extractVersion2[0]+"."+extractVersion2[1]+"."+extractVersion3[0] + "\n"

方案4:使用 HTML 模板 如果需要更复杂的格式控制,可以使用 html/template

package main

import (
	"bytes"
	"html/template"
	"net/smtp"
	"log"
)

// ... 其他代码保持不变 ...

func SendmaiL(emailTo string, e Email_struct) bool {
	// ... 前面的代码保持不变 ...
	
	var tmplFile = "email.html.tmpl"
	tmpl, err := template.New(tmplFile).ParseFiles(tmplFile)
	if err != nil {
		panic(err)
	}
	
	// ... 后面的代码保持不变 ...
}

创建 email.html.tmpl 文件:

Subject: [{{ .Status }}] app {{ .App }} has been synced by argoCD

<p>Project: {{ .Project }}</p>
<p>Target : {{ .TargetEnv }}</p>
<p>Version: {{ .AppVersion }}</p>
<p>URL: {{ .Url }}</p>

<p>Best regards,<br>
Devops Team</p>

方案5:使用原始字符串模板 在代码中直接定义模板字符串:

func SendmaiL(emailTo string, e Email_struct) bool {
	// ... 前面的代码保持不变 ...
	
	tmplStr := `Subject: [{{ .Status }}] app {{ .App }} has been synced by argoCD

Project: {{ .Project }}
Target : {{ .TargetEnv }}
Version: {{ .AppVersion }}
URL: {{ .Url }}

Best regards,
Devops Team`
	
	tmpl, err := template.New("email").Parse(tmplStr)
	if err != nil {
		panic(err)
	}
	
	// ... 后面的代码保持不变 ...
}

推荐使用方案1或方案5,这两种方法能保持模板的清晰性和可维护性。方案1通过 {{"\n"}} 显式添加换行符,方案5将模板内嵌在代码中,避免了外部文件依赖。

回到顶部