package utils import ( "crypto/tls" "fmt" "io" "log" "strings" "github.com/PuerkitoBio/goquery" "github.com/emersion/go-imap" "github.com/emersion/go-imap/client" "github.com/emersion/go-message/mail" ) type EmailImap struct { } // 获取最新一封邮件的正文内容 func (*EmailImap) GetLatestMailContent(server, username, password string) (string, error) { // 1. 连接 IMAP 服务器 (SSL/TLS, 端口 993) tlsConfig := &tls.Config{InsecureSkipVerify: true} c, err := client.DialTLS(server, tlsConfig) if err != nil { return "", fmt.Errorf("连接失败: %v", err) } defer c.Logout() // 2. 登录 if err := c.Login(username, password); err != nil { return "", fmt.Errorf("登录失败: %v", err) } // 3. 选择收件箱 mbox, err := c.Select("INBOX", false) if err != nil { return "", fmt.Errorf("选择收件箱失败: %v", err) } if mbox.Messages == 0 { return "", nil // 没有邮件 } // 4. 获取最新一封邮件 seqset := new(imap.SeqSet) seqset.AddNum(mbox.Messages) section := &imap.BodySectionName{} messages := make(chan *imap.Message, 1) go func() { if err := c.Fetch(seqset, []imap.FetchItem{section.FetchItem()}, messages); err != nil { log.Println("获取邮件失败:", err) } }() msg := <-messages if msg == nil { return "", nil } r := msg.GetBody(section) if r == nil { return "", nil } // 5. 解析邮件正文 mr, err := mail.CreateReader(r) if err != nil { return "", fmt.Errorf("解析邮件失败: %v", err) } var htmlContent, textContent string for { p, err := mr.NextPart() if err == io.EOF { break } if err != nil { return "", fmt.Errorf("读取邮件失败: %v", err) } switch h := p.Header.(type) { case *mail.InlineHeader: mediaType, _, _ := h.ContentType() b, _ := io.ReadAll(p.Body) if strings.HasPrefix(mediaType, "text/html") { htmlContent = string(b) } else if strings.HasPrefix(mediaType, "text/plain") { textContent = string(b) } } } // 优先返回 HTML,没有就退回纯文本 if htmlContent != "" { return htmlContent, nil } return textContent, nil } func (e *EmailImap) GetMailCode(server, username, password string) string { res, err := e.GetLatestMailContent(server, username, password) if err != nil { return "0" } htmlStr := res doc, err := goquery.NewDocumentFromReader(strings.NewReader(htmlStr)) if err != nil { return "0" } code := "" doc.Find("td.h1.black").Each(func(i int, s *goquery.Selection) { if code == "" { code = strings.TrimSpace(s.Text()) } }) if code == "" { return "0" } return strings.TrimSpace(code) } func test() { var emailImap EmailImap content, err := emailImap.GetLatestMailContent("pop.dragonsmail.com:993", "CamilleMathews1u8K@dragonsmail.com", "vDgADn`zga.") if err != nil { log.Fatal(err) } fmt.Println("最新邮件内容:\n", content) }