Ver Fonte

优化邮件监听功能和字符集处理

- 重构了邮件监听逻辑,提高效率并防止重复处理邮件
- 增加了韩文字符集支持
- 更新了邮件读取策略,从末尾开始读取,提高新邮件获取速度
- 优化了部分日志输出和错误处理
Roc há 7 meses atrás
pai
commit
7f5385b4d8
6 ficheiros alterados com 57 adições e 27 exclusões
  1. 2 1
      go.mod
  2. 5 0
      go.sum
  3. 1 0
      init_serve/task.go
  4. 5 4
      services/pcsg/mail.go
  5. 3 0
      utils/mail/charset_reader.go
  6. 41 22
      utils/mail/imap.go

+ 2 - 1
go.mod

@@ -6,7 +6,7 @@ require (
 	github.com/astaxie/beego v1.12.3
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/emersion/go-imap v1.2.1
-	github.com/emersion/go-message v0.15.0
+	github.com/emersion/go-message v0.18.1
 	github.com/fsnotify/fsnotify v1.6.0
 	github.com/gin-gonic/gin v1.9.1
 	github.com/go-playground/locales v0.14.1
@@ -67,6 +67,7 @@ require (
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/compress v1.17.9 // indirect
 	github.com/klauspost/cpuid/v2 v2.2.8 // indirect
+	github.com/knadh/go-pop3 v1.0.0 // indirect
 	github.com/leodido/go-urn v1.2.4 // indirect
 	github.com/lestrrat-go/strftime v1.0.6 // indirect
 	github.com/magiconair/properties v1.8.7 // indirect

+ 5 - 0
go.sum

@@ -113,6 +113,8 @@ github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjT
 github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
 github.com/emersion/go-message v0.15.0 h1:urgKGqt2JAc9NFJcgncQcohHdiYb803YTH9OQwHBHIY=
 github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
+github.com/emersion/go-message v0.18.1 h1:tfTxIoXFSFRwWaZsgnqS1DSZuGpYGzSmCZD8SK3QA2E=
+github.com/emersion/go-message v0.18.1/go.mod h1:XpJyL70LwRvq2a8rVbHXikPgKj8+aI0kGdHlg16ibYA=
 github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
 github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
 github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY=
@@ -291,6 +293,8 @@ github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZX
 github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
 github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
 github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/knadh/go-pop3 v1.0.0 h1:ICAINSl+uqwwCW6p7RjhY+AbPWC2KMLtdQCpuiSqe1g=
+github.com/knadh/go-pop3 v1.0.0/go.mod h1:a5kUJzrBB6kec+tNJl+3Z64ROgByKBdcyub+mhZMAfI=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -677,6 +681,7 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
 golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
 golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=

+ 1 - 0
init_serve/task.go

@@ -34,6 +34,7 @@ func InitTask() {
 			global.LOG.Error("pcsg.ListenMail err" + err.Error())
 		}
 	}
+	//pcsg.ListenMail()
 
 	c.Start()
 }

+ 5 - 4
services/pcsg/mail.go

@@ -11,6 +11,7 @@ import (
 	"github.com/google/uuid"
 	"html"
 	"io/fs"
+	"log"
 	"os"
 	"path"
 	"strings"
@@ -37,7 +38,7 @@ func ListenMail() {
 	mailMessageChan := make(chan mail.MailMessage, 5) // 创建一个通道,用于接收邮件消息
 	mailMessageDoneChan := make(chan bool, 1)         // 创建一个通道,用于接收邮件消息
 
-	fmt.Println(len(mailMessageChan))
+	//fmt.Println(len(mailMessageChan))
 
 	// 邮件监听后的处理函数
 	go afterByListen(mailMessageChan, mailMessageDoneChan)
@@ -61,7 +62,7 @@ func ListenMail() {
 
 func afterByListen(mailMessageChan chan mail.MailMessage, mailMessageDoneChan chan bool) {
 	defer func() {
-		fmt.Println("监听读取结束")
+		log.Println("监听读取结束")
 		lockListenEmail.Unlock()
 	}()
 	for {
@@ -74,12 +75,12 @@ func afterByListen(mailMessageChan chan mail.MailMessage, mailMessageDoneChan ch
 			//fmt.Println("监听超时了")
 			break
 		case <-mailMessageDoneChan:
-			fmt.Println("读取完成一轮了")
+			//fmt.Println("读取完成一轮了")
 			for len(mailMessageChan) > 0 {
 				emailMessage := <-mailMessageChan
 				handleMailMessage(emailMessage)
 			}
-			fmt.Println("结束了")
+			//fmt.Println("结束了")
 			return
 		}
 	}

+ 3 - 0
utils/mail/charset_reader.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"golang.org/x/text/encoding/charmap"
 	"golang.org/x/text/encoding/japanese"
+	"golang.org/x/text/encoding/korean"
 	"golang.org/x/text/encoding/simplifiedchinese"
 	"golang.org/x/text/transform"
 	"io"
@@ -57,6 +58,8 @@ var charsetMap = map[string]transform.Transformer{
 	"euc-jp":         japanese.EUCJP.NewDecoder(),
 	"iso-2022-jp":    japanese.ISO2022JP.NewDecoder(),
 	"shift_jis":      japanese.ShiftJIS.NewDecoder(),
+	"ks_c_5601-1987": korean.EUCKR.NewDecoder(),
+	"euc-kr":         korean.EUCKR.NewDecoder(),
 }
 
 // 定义一个自定义的 CharsetReader 函数,它能够处理 gb2312 和 gbk 字符集

+ 41 - 22
utils/mail/imap.go

@@ -101,32 +101,33 @@ func ListenMail(mailAddress, folder, userName, password string, readBatchSize, f
 
 	to := mbox.Messages // 此文件下的邮件总数
 
-	from := uint32(1)
-	// 假设需要获取最后4封邮件时
-	if fromEmailIndex > 0 {
-		from = uint32(fromEmailIndex)
-	} else {
-		var maxNum uint32
-		//该次监听获取的最大数量
-		maxNum = 20000
-		//获取开始的邮件编号
-		if to > maxNum {
-			from = to - maxNum + 1
-		}
-	}
+	//minIndex := uint32(5)
+	//// 假设需要获取最后4封邮件时
+	//if fromEmailIndex > 0 {
+	//	minIndex = uint32(fromEmailIndex)
+	//} else {
+	//	var maxNum uint32
+	//	//该次监听获取的最大数量
+	//	maxNum = 20000
+	//	//获取开始的邮件编号
+	//	if to > maxNum {
+	//		minIndex = to - maxNum + 1
+	//	}
+	//}
 	//from = 310
 
-	step := uint32(5)
-	for i := from; i <= to; {
-		end := i + step - 1
-		if end > to {
-			end = to
+	var isStopFor bool
+	step := uint32(1)
+	for i := to; i >= 1; {
+		start := i - step + 1
+		if start < 0 {
+			start = 1
 		}
 
-		fmt.Printf("当前剩余%d封邮件待处理\n", to-i+1)
+		//fmt.Printf("当前剩余%d封邮件待处理\n", i-minIndex+1)
 
 		seqSet.Clear()
-		seqSet.AddRange(i, end) // 添加指定范围内的邮件编号
+		seqSet.AddRange(start, i) // 添加指定范围内的邮件编号
 
 		// 获取整个消息正文
 		// imap.FetchEnvelope:请求获取邮件的信封数据(例如发件人、收件人、主题等元数据)。
@@ -150,6 +151,11 @@ func ListenMail(mailAddress, folder, userName, password string, readBatchSize, f
 
 		//log.Println("开始读取邮件内容")
 		for msg := range messages {
+			// 如果需要终止,那么就不处理了
+			if isStopFor {
+				continue
+			}
+
 			emailMessage, isRead, tmpErr := readEveryMsg(msg)
 			if tmpErr != nil {
 				// 移除本地文件
@@ -168,14 +174,24 @@ func ListenMail(mailAddress, folder, userName, password string, readBatchSize, f
 			if !isRead {
 				continue
 			}
+
+			// 判断当前邮件id是否小于等于已经监听到的最小id,如果是,那么就不处理了
+			if emailMessage.Uid <= uint32(fromEmailIndex) {
+				isStopFor = true
+				continue
+			}
 			// 如果取到了,那么写入待处理chan
 			// 写入邮件处理chan
 			mailMessageChan <- emailMessage
+
 		}
 
+		if isStopFor {
+			// 已经找到了最小的邮件id,那么就退出循环了
+		}
 		//time.Sleep(time.Second * 5) // 休眠10秒
 
-		i = i + step
+		i = i - step
 	}
 
 	log.Println("读取了所有邮件,完毕!")
@@ -228,7 +244,7 @@ func readEveryMsg(msg *imap.Message) (emailMessage MailMessage, ok bool, err err
 	// 发件人
 	{
 		fromStr := mr.Header.Get("From")
-		fmt.Println(fromStr)
+		//fmt.Println(fromStr)
 		// 处理无效地址的情况
 		if !strings.Contains(fromStr, "@") {
 			emailMessage.FromAddress = fromStr
@@ -266,6 +282,9 @@ func readEveryMsg(msg *imap.Message) (emailMessage MailMessage, ok bool, err err
 		ok = false
 		return
 	}
+	//fmt.Println("当前邮件Uid:", emailMessage.Uid)
+	//ok = false
+	//return
 
 	for {
 		p, tmpErr := mr.NextPart()