-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathsmtp.go
128 lines (111 loc) · 3.17 KB
/
smtp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package utils
import (
"bytes"
"crypto/tls"
"fmt"
"gopkg.in/gomail.v2"
"strings"
"text/template"
)
type SmtpPoster struct {
Host string
Protocol bool
Port int
Username string
Password string
From string
}
func NewSmtpPoster(host string, protocol bool, port int, username string, password string, from string) *SmtpPoster {
return &SmtpPoster{
Host: host,
Protocol: protocol,
Port: port,
Username: username,
Password: password,
From: from,
}
}
func (s *SmtpPoster) Valid() bool {
return s.Host != "" && s.Port > 0 && s.Port <= 65535 && s.Username != "" && s.Password != "" && s.From != ""
}
func (s *SmtpPoster) SendMail(to string, subject string, body string) error {
if !s.Valid() {
return fmt.Errorf("smtp not configured properly")
}
// Create gomail message object
message := gomail.NewMessage()
// Determine sender address based on whether the username contains "@"
var from string
if strings.Contains(s.Username, "@") {
// If the username contains "@", use From as the sender
from = s.From
} else {
// Otherwise, combine the username and From to form the sender's email address
from = fmt.Sprintf("%s <%s>", s.Username, s.From)
}
message.SetHeader("From", from)
message.SetHeader("To", to)
message.SetHeader("Subject", subject)
message.SetBody("text/html", body)
dialer := gomail.NewDialer(s.Host, s.Port, s.Username, s.Password)
// If TLS protocol is enabled
if s.Protocol {
dialer.TLSConfig = &tls.Config{
InsecureSkipVerify: false, // Disable insecure certificate verification
ServerName: s.Host, // Set ServerName to the SMTP host
}
} else {
// When SSL is enabled, no need for STARTTLS, directly establish an encrypted connection
dialer.SSL = true
}
// Specific handling for different providers
switch {
case strings.Contains(s.Host, "outlook"):
dialer.TLSConfig = &tls.Config{
InsecureSkipVerify: false,
ServerName: s.Host,
}
case strings.Contains(s.Host, "qq"):
dialer.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
ServerName: s.Host,
}
case strings.Contains(s.Host, "office365"):
dialer.TLSConfig = &tls.Config{
InsecureSkipVerify: false,
ServerName: s.Host,
}
case strings.Contains(s.Host, "resend"):
dialer.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
ServerName: s.Host,
}
case strings.Contains(s.Host, "tencent"):
dialer.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
ServerName: s.Host,
}
}
if err := dialer.DialAndSend(message); err != nil {
return fmt.Errorf("sent mail failed: %s", err.Error())
}
return nil
}
func (s *SmtpPoster) RenderTemplate(filename string, data interface{}) (string, error) {
tmpl, err := template.New(filename).ParseFiles(fmt.Sprintf("utils/templates/%s", filename))
if err != nil {
return "", err
}
var buf bytes.Buffer
if err := tmpl.ExecuteTemplate(&buf, filename, data); err != nil {
return "", err
}
return buf.String(), nil
}
func (s *SmtpPoster) RenderMail(filename string, data interface{}, to string, subject string) error {
body, err := s.RenderTemplate(filename, data)
if err != nil {
return err
}
return s.SendMail(to, subject, body)
}