You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
synctv/utils/smtp/format.go

104 lines
2.5 KiB
Go

package smtp
import (
"bytes"
"encoding/base64"
"fmt"
"mime"
"strings"
"time"
smtp "github.com/emersion/go-smtp"
"github.com/zijiren233/stream"
)
type FormatMailConfig struct {
date string
mimeVersion string
contentType string
contentTransferEncoding string
}
type FormatMailOption func(c *FormatMailConfig)
func WithDate(date time.Time) FormatMailOption {
return func(c *FormatMailConfig) {
c.date = date.Format(time.RFC1123Z)
}
}
func WithMimeVersion(mimeVersion string) FormatMailOption {
return func(c *FormatMailConfig) {
c.mimeVersion = mimeVersion
}
}
func WithContentType(contentType string) FormatMailOption {
return func(c *FormatMailConfig) {
c.contentType = contentType
}
}
func WithContentTransferEncoding(contentTransferEncoding string) FormatMailOption {
return func(c *FormatMailConfig) {
c.contentTransferEncoding = contentTransferEncoding
}
}
func FormatMail(from string, to []string, subject string, body string, opts ...FormatMailOption) string {
c := &FormatMailConfig{
date: time.Now().Format(time.RFC1123Z),
mimeVersion: "1.0",
contentType: "text/html; charset=UTF-8",
contentTransferEncoding: "base64",
}
for _, opt := range opts {
opt(c)
}
buf := bytes.NewBuffer(nil)
buf.WriteString(fmt.Sprintf("From: %s\r\n", from))
buf.WriteString(fmt.Sprintf("To: %s\r\n", strings.Join(to, ", ")))
buf.WriteString(fmt.Sprintf("Subject: %s\r\n", mime.QEncoding.Encode("UTF-8", subject)))
buf.WriteString(fmt.Sprintf("Date: %s\r\n", c.date))
buf.WriteString(fmt.Sprintf("MIME-Version: %s\r\n", c.mimeVersion))
buf.WriteString(fmt.Sprintf("Content-Type: %s\r\n", c.contentType))
if c.contentTransferEncoding != "" {
buf.WriteString(fmt.Sprintf("Content-Transfer-Encoding: %s\r\n", c.contentTransferEncoding))
}
buf.WriteString("\r\n")
switch c.contentTransferEncoding {
case "base64":
encodedBody := base64.StdEncoding.EncodeToString(stream.StringToBytes(body))
for i := 0; i < len(encodedBody); i += 76 {
end := i + 76
if end > len(encodedBody) {
end = len(encodedBody)
}
buf.WriteString(encodedBody[i:end] + "\r\n")
}
case "":
buf.WriteString(body)
}
return buf.String()
}
func SendEmail(cli *smtp.Client, from string, to []string, subject, body string, opts ...FormatMailOption) error {
return cli.SendMail(
from,
to,
strings.NewReader(
FormatMail(
from,
to,
subject,
body,
opts...,
),
),
)
}