完善多个通道

This commit is contained in:
Yun
2024-11-20 19:42:07 +08:00
parent 868a5106e6
commit dc49e97912
33 changed files with 1861 additions and 191 deletions
+1
View File
@@ -0,0 +1 @@
hhhhhhhhhhh
Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

+77
View File
@@ -0,0 +1,77 @@
package mailx
import (
"bytes"
"github.com/PuerkitoBio/goquery"
)
// 解析HTML资源,响应资源链接
func ParseHtmlResource(html string) ([]string, error) {
resp := []string{}
b := bytes.NewBufferString(html)
doc, err := goquery.NewDocumentFromReader(b)
if err != nil {
return nil, err
}
// 找到所有的 css 标签,并且打印它们的 href 属性
doc.Find("link").Each(func(i int, s *goquery.Selection) {
// 忽略dns预请求
r, ok := s.Attr("rel")
if ok && r == "dns-prefetch" {
return
}
href, ok := s.Attr("href")
if ok && href != "" {
resp = append(resp, href)
}
})
// 找到所有的 script 标签,并且打印它们的 src 属性
doc.Find("script").Each(func(i int, s *goquery.Selection) {
src, ok := s.Attr("src")
if ok && src != "" {
resp = append(resp, src)
}
})
// 找到所有的 img 标签,并且打印它们的 src 属性
doc.Find("img").Each(func(i int, s *goquery.Selection) {
src, ok := s.Attr("src")
if ok && src != "" {
resp = append(resp, src)
}
data_src, ok := s.Attr("data-src")
if ok && data_src != "" {
resp = append(resp, data_src)
}
})
// 找到所有的 video 标签,并且打印它们的 src 属性
doc.Find("video").Each(func(i int, s *goquery.Selection) {
src, ok := s.Attr("src")
if ok && src != "" {
resp = append(resp, src)
}
data_src, ok := s.Attr("data-src")
if ok && data_src != "" {
resp = append(resp, data_src)
}
})
// 找到所有的 audio 标签,并且打印它们的 src 属性
doc.Find("audio").Each(func(i int, s *goquery.Selection) {
src, ok := s.Attr("src")
if ok && src != "" {
resp = append(resp, src)
}
})
return resp, nil
}
+60
View File
@@ -0,0 +1,60 @@
package mailx_test
import (
"testing"
"code.yun.ink/pkg/mailx"
)
func TestParseHtmlResource(t *testing.T) {
html := `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./assets/css/index.css" />
</head>
<body>
<header class="header flex-center">
<img src="./assets/img/ab-pay-logo.png" alt="" class="logo" />
</header>
<main class="code-main">
<div class="exception-title">您的收款方式审核失败</div>
<div class="exception-content">
尊敬的ABpay用户,您好!
您的收款方式审核失败,失败原因人脸识别失败,请检查您的面部是否被遮挡或处于模糊状态,并再次尝试。
如非本人操作,请立即修改密码或联系客服。
</div>
<div class="exception-ignore">这是一条自动发送的消息,请勿回复</div>
<li class="exception-team-tips">ABpay开发者团队服务</li>
<section class="contact-us">
<div class="contact-us-info">
本邮件由系统自动发出请勿回复,如需要了解更多服务,欢迎访问ABpay官方网
还可以通以下方式联系我们
</div>
<img src="./assets/img/contact-us-qrcode.png" alt="" class="qr-code" />
<div class="contact-tel">
客服电话:<span class="contact-tel-number">400-278-2890</span>
</div>
<div class="contact-created-version">2024 ABpay.com.cn . All rightes reserved</div>
</section>
</main>
</body>
</html>
`
res, err := mailx.ParseHtmlResource(html)
if err != nil {
t.Fatal(err)
}
t.Log(res)
}
+202
View File
@@ -0,0 +1,202 @@
package mailx
import (
"bytes"
"encoding/base64"
"fmt"
"net/smtp"
"os"
"path"
"strings"
"time"
)
// 邮件发送的封装
// 1. 支持文本
// 2. 支持文件
type Mailx struct {
user string
password string
host string
port string
auth smtp.Auth
}
type Attachment struct {
Name string
ContentType string
WithFile bool
}
type Message struct {
Form string
To []string
Cc []string
Bcc []string
Subject string
Body string
// ContentType string
ReplyTo string
Attachment []Attachment
}
func NewMailx(user, password, host, port string) *Mailx {
m := &Mailx{
user: user,
password: password,
host: host,
port: port,
}
m.auth = smtp.PlainAuth("", user, password, host)
return m
}
func (m *Mailx) Send(message Message) error {
// .Auth()
buffer := bytes.NewBuffer(nil)
boundary := "YunBoundaryYun"
Header := make(map[string]string)
// Header["From"] = "BOP<" + message.Form + ">"
Header["From"] = m.user
if len(message.To) > 0 {
str := ""
for _, val := range message.To {
name := ""
s := strings.Split(val, "@")
if len(s) > 0 {
name = s[0]
}
str = str + "," + name + "<" + val + ">"
}
Header["To"] = strings.Trim(str, ",")
// Header["To"] = strings.Join(message.To, ",")
}
if len(message.Cc) > 0 {
str := ""
for _, val := range message.Cc {
name := ""
s := strings.Split(val, "@")
if len(s) > 0 {
name = s[0]
}
str = str + "," + name + "<" + val + ">"
}
Header["Cc"] = strings.Trim(str, ",")
// Header["Cc"] = strings.Join(message.Cc, ",")
}
if len(message.Bcc) > 0 {
str := ""
for _, val := range message.Bcc {
name := ""
s := strings.Split(val, "@")
if len(s) > 0 {
name = s[0]
}
str = str + "," + name + "<" + val + ">"
}
Header["Bcc"] = strings.Trim(str, ",")
// Header["Bcc"] = strings.Join(message.Bcc, ",")
}
Header["Subject"] = message.Subject
Header["Content-Type"] = "multipart/mixed; charset=UTF-8; boundary=" + boundary
Header["Date"] = time.Now().String()
Header["Reply-To"] = message.ReplyTo
Header["X-Priority"] = "3"
m.writeHeader(buffer, Header)
body := "--" + boundary + "\r\n"
// body += "Content-Type: text/plain; charset=UTF-8 \r\n"
body += "Content-Type: text/html;charset=utf-8\r\n"
body += "Content-Transfer-Encoding:quoted-printable\r\n\r\n"
// body += "<html><body><h1>huang</h1><h2>xin</h2></body></html>\r\n"
body += "<html><body>" + message.Body + "</body></html>\r\n"
// body += "--" + boundary + "--\r\n\r\n"
buffer.WriteString(body)
for _, value := range message.Attachment {
newBuf := bytes.NewBuffer(nil)
err := m.writeFile(newBuf, value.Name)
if err != nil {
fmt.Println("file err:", err)
continue
}
f_name := path.Base(value.Name)
attachment := "--" + boundary + "\r\n"
attachment += "Content-Transfer-Encoding:base64\r\n"
attachment += "Content-Disposition:attachment;filename=" + f_name + "\r\n"
attachment += "Content-Type: application/octet-stream;charset=utf-8;name=" + f_name + "\r\n"
// attachment += "Contment-Type:" + message.attachment.contentType + ";name=\"" + message.attachment.name + "\"\r\n"
buffer.WriteString(attachment)
buffer.WriteString(newBuf.String())
buffer.WriteString("\r\n")
}
if message.Form == "" {
message.Form = m.user
}
imgBuf := bytes.NewBuffer(nil)
err := m.writeFile(imgBuf, "./asset/余额宝.png")
if err != nil {
return fmt.Errorf("file err: %w", err)
}
f_name:= "f_name"
attachment := "--" + boundary + "\r\n"
attachment += "Content-Transfer-Encoding:base64\r\n"
attachment += "Content-ID:myimage \r\n"
attachment += "Content-Disposition:inline;filename=" + f_name + ".png \r\n"
attachment += "Content-Type:image/png \r\n"
buffer.WriteString(attachment)
buffer.WriteString(imgBuf.String())
buffer.WriteString("\r\n--" + boundary + "--\r\n")
b := buffer.Bytes()
err = smtp.SendMail(m.host+":"+m.port, m.auth, message.Form, message.To, b)
fmt.Println("发送结束:", err)
fmt.Println(string(b))
return err
}
// 格式化header
func (m *Mailx) writeHeader(buffer *bytes.Buffer, Header map[string]string) string {
header := ""
// header := "Content-Type: multipart/mixed;charset=UTF-8;boundary=\"YunBoundaryYun\" \r\n"
for key, value := range Header {
if value != "" {
header += key + ": " + value + "\r\n"
}
}
header += "\r\n"
buffer.WriteString(header)
return header
}
// 格式化文件
func (m *Mailx) writeFile(buffer *bytes.Buffer, fileName string) error {
file, err := os.ReadFile(fileName)
if err != nil {
return err
}
payload := make([]byte, base64.StdEncoding.EncodedLen(len(file)))
base64.StdEncoding.Encode(payload, file)
buffer.WriteString("\r\n")
for index, line := 0, len(payload); index < line; index++ {
buffer.WriteByte(payload[index])
if (index+1)%76 == 0 {
buffer.WriteString("\r\n")
}
}
return nil
}
+64
View File
@@ -0,0 +1,64 @@
package mailx_test
import (
"fmt"
"testing"
mailx "code.yun.ink/pkg/mailx/old"
)
func TestMail(t *testing.T) {
mail := mailx.NewMailx("support@email.blueoceanpay.com", "SupporT2017", "smtpdm-ap-southeast-1.aliyun.com", "80")
msg := mailx.Message{
// Form: "support@email.blueoceanpay.com",
To: []string{"huangxinyun520@gmail.com", "995116474@qq.com"},
// Cc: []string{"287852692@qq.com"},
// Bcc: []string{"1362716835@qq.com"},
Subject: "test mail",
Body: "<img src=\"cid:myimage\">dasdsadsasda<br>dasdsadsadsa",
Attachment: []mailx.Attachment{
{
Name: "asset/hhh.txt",
ContentType: "",
WithFile: true,
},
// {
// Name: "/code/statistic/origin.xlsx",
// ContentType: "",
// WithFile: true,
// },
// {
// Name: "/code/statistic/out2.xlsx",
// ContentType: "",
// WithFile: true,
// },
},
}
err := mail.Send(msg)
fmt.Println(err)
}
func TestQQ(t *testing.T) {
// 发件人邮箱
from := "995116474@qq.com"
// 授权码,而非密码
authCode := "xxxxxxxxxxxxxxxxxxxxxx"
// 收件人邮箱,可以是多个收件人
to := []string{"yun@yun.ink"}
// 邮件服务器信息
smtpHost := "smtp.qq.com"
smtpPort := "587" // 或使用465,根据你的SMTP服务器要求设置
mail := mailx.NewMailx(from, authCode, smtpHost, smtpPort)
msg := mailx.Message{
To: to,
Subject: "test mail",
Body: "测试",
}
err := mail.Send(msg)
fmt.Println(err)
}