Initial commit: 网络验证平台
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"mime"
|
||||
"net/smtp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type EmailService struct{}
|
||||
|
||||
func NewEmailService() *EmailService {
|
||||
return &EmailService{}
|
||||
}
|
||||
|
||||
type EmailConfig struct {
|
||||
Host string
|
||||
Port int
|
||||
User string
|
||||
Password string
|
||||
FromName string
|
||||
FromEmail string
|
||||
UseSSL bool
|
||||
}
|
||||
|
||||
func (s *EmailService) SendEmail(config EmailConfig, to, subject, body string) error {
|
||||
if config.Host == "" || config.User == "" || config.Password == "" {
|
||||
return fmt.Errorf("邮件配置不完整")
|
||||
}
|
||||
|
||||
from := config.FromEmail
|
||||
if from == "" {
|
||||
from = config.User
|
||||
}
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", config.Host, config.Port)
|
||||
|
||||
msg := s.buildMessage(config.FromName, from, to, subject, body)
|
||||
|
||||
auth := smtp.PlainAuth("", config.User, config.Password, config.Host)
|
||||
|
||||
if config.UseSSL || config.Port == 465 || config.Port == 587 {
|
||||
return s.sendWithTLS(addr, auth, from, []string{to}, []byte(msg))
|
||||
}
|
||||
|
||||
return smtp.SendMail(addr, auth, from, []string{to}, []byte(msg))
|
||||
}
|
||||
|
||||
func (s *EmailService) sendWithTLS(addr string, auth smtp.Auth, from string, to []string, msg []byte) error {
|
||||
host := strings.Split(addr, ":")[0]
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
ServerName: host,
|
||||
}
|
||||
|
||||
conn, err := tls.Dial("tcp", addr, tlsConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("TLS连接失败: %v", err)
|
||||
}
|
||||
|
||||
client, err := smtp.NewClient(conn, host)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建SMTP客户端失败: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
if err = client.Auth(auth); err != nil {
|
||||
return fmt.Errorf("SMTP认证失败: %v", err)
|
||||
}
|
||||
|
||||
if err = client.Mail(from); err != nil {
|
||||
return fmt.Errorf("设置发件人失败: %v", err)
|
||||
}
|
||||
|
||||
for _, addr := range to {
|
||||
if err = client.Rcpt(addr); err != nil {
|
||||
return fmt.Errorf("设置收件人失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
w, err := client.Data()
|
||||
if err != nil {
|
||||
return fmt.Errorf("准备邮件数据失败: %v", err)
|
||||
}
|
||||
|
||||
_, err = w.Write(msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("写入邮件内容失败: %v", err)
|
||||
}
|
||||
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("关闭邮件写入失败: %v", err)
|
||||
}
|
||||
|
||||
return client.Quit()
|
||||
}
|
||||
|
||||
func (s *EmailService) buildMessage(fromName, from, to, subject, body string) string {
|
||||
msg := ""
|
||||
|
||||
if fromName != "" {
|
||||
encodedName := mime.QEncoding.Encode("UTF-8", fromName)
|
||||
msg += fmt.Sprintf("From: %s <%s>\r\n", encodedName, from)
|
||||
} else {
|
||||
msg += fmt.Sprintf("From: %s\r\n", from)
|
||||
}
|
||||
|
||||
msg += fmt.Sprintf("To: %s\r\n", to)
|
||||
msg += fmt.Sprintf("Subject: %s\r\n", mime.QEncoding.Encode("UTF-8", subject))
|
||||
msg += "MIME-version: 1.0;\r\nContent-Type: text/html; charset=\"UTF-8\";\r\n\r\n"
|
||||
msg += body
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
func (s *EmailService) SendTestEmail(config EmailConfig, to, siteName string) error {
|
||||
subject := fmt.Sprintf("测试邮件 - %s", siteName)
|
||||
body := fmt.Sprintf(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body style="font-family: Arial, sans-serif; padding: 20px; background-color: #f5f5f5;">
|
||||
<div style="max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
||||
<h2 style="color: #333; margin-bottom: 20px;">邮件发送测试成功</h2>
|
||||
<p style="color: #666; line-height: 1.6;">这是一封测试邮件,如果您收到此邮件,说明您的SMTP配置正确。</p>
|
||||
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
|
||||
<p style="color: #999; font-size: 12px;">此邮件由 %s 系统自动发送,请勿回复。</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`, siteName)
|
||||
return s.SendEmail(config, to, subject, body)
|
||||
}
|
||||
|
||||
func ParseBool(value string) bool {
|
||||
return value == "true" || value == "1" || strings.ToLower(value) == "yes"
|
||||
}
|
||||
|
||||
func ParseInt(value string, defaultValue int) int {
|
||||
if value == "" {
|
||||
return defaultValue
|
||||
}
|
||||
val, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
return val
|
||||
}
|
||||
Reference in New Issue
Block a user