完善多个通道
This commit is contained in:
@@ -0,0 +1 @@
|
||||
hhhhhhhhhhh
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
+77
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user