imaptool.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. package tools
  2. import (
  3. "bufio"
  4. "flag"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "log"
  9. "os"
  10. "strconv"
  11. "strings"
  12. "github.com/emersion/go-imap"
  13. "github.com/emersion/go-imap/client"
  14. "github.com/emersion/go-message/mail"
  15. )
  16. //全局变量
  17. //imap服务地址,邮箱,密码
  18. var (
  19. server, email, password string
  20. folders map[int]string
  21. )
  22. func testmain() {
  23. //获取参数中的数据
  24. flag.StringVar(&server, "server", "", "imap服务地址(包含端口)")
  25. flag.StringVar(&email, "email", "", "邮箱名")
  26. flag.StringVar(&password, "password", "", "密码")
  27. flag.Parse()
  28. if flag.NFlag() < 3 {
  29. flag.PrintDefaults()
  30. os.Exit(1)
  31. }
  32. if server == "" || email == "" || password == "" {
  33. log.Fatal("服务器地址,用户名,密码,参数必填")
  34. }
  35. log.Println("正在连接服务器...")
  36. //支持加密和非加密端口
  37. if !strings.Contains(server, ":") {
  38. log.Fatal("服务器地址端口号错误:", server)
  39. }
  40. serverSlice := strings.Split(server, ":")
  41. uri := serverSlice[0]
  42. port, _ := strconv.Atoi(serverSlice[1])
  43. if port != 993 && port != 143 {
  44. log.Fatal("服务器地址端口号错误:", port)
  45. }
  46. // 连接到服务器
  47. var c *client.Client
  48. var err error
  49. if port == 993 {
  50. c, err = client.DialTLS(fmt.Sprintf("%s:%d", uri, port), nil)
  51. } else {
  52. c, err = client.Dial(fmt.Sprintf("%s:%d", uri, port))
  53. }
  54. if err != nil {
  55. log.Fatal(err)
  56. }
  57. log.Println("连接成功")
  58. // 不要忘了退出
  59. defer c.Logout()
  60. // 登陆
  61. if err := c.Login(email, password); err != nil {
  62. log.Fatal(err)
  63. }
  64. log.Println("成功登陆")
  65. // 列邮箱
  66. mailboxes := make(chan *imap.MailboxInfo, 10)
  67. done := make(chan error, 1)
  68. go func() {
  69. done <- c.List("", "*", mailboxes)
  70. }()
  71. // 存储邮件夹
  72. folders = make(map[int]string)
  73. i := 1
  74. for m := range mailboxes {
  75. log.Println("* ", i, m.Name)
  76. folders[i] = m.Name
  77. i++
  78. }
  79. log.Println("输入邮件夹序号:")
  80. inLine := readLineFromInput()
  81. folderNum, _ := strconv.Atoi(inLine)
  82. currentFolder := folders[folderNum]
  83. if err := <-done; err != nil {
  84. log.Fatal(err)
  85. }
  86. // Select 邮件夹
  87. mbox, err := c.Select(currentFolder, false)
  88. if err != nil {
  89. log.Fatal(err)
  90. }
  91. log.Printf("%s的邮件个数:%d \r\n", currentFolder, mbox.Messages)
  92. // 获取最新的信
  93. log.Println("读取最新的几封信(all全部):")
  94. inLine = readLineFromInput()
  95. var maxNum uint32
  96. if inLine == "all" {
  97. maxNum = mbox.Messages
  98. } else {
  99. tempNum, _ := strconv.Atoi(inLine)
  100. maxNum = uint32(tempNum)
  101. }
  102. from := uint32(1)
  103. to := mbox.Messages
  104. if mbox.Messages >= maxNum {
  105. // 我们在这使用无符号整型, 这是再获取from的id
  106. from = mbox.Messages - maxNum + 1
  107. } else {
  108. log.Fatal("超出了邮件封数!")
  109. }
  110. seqset := new(imap.SeqSet)
  111. seqset.AddRange(from, to)
  112. messages := make(chan *imap.Message, 10)
  113. done = make(chan error, 1)
  114. go func() {
  115. done <- c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope}, messages)
  116. }()
  117. log.Printf("最新的 %d 封信:", maxNum)
  118. for msg := range messages {
  119. log.Printf("* %d:%s\n", to, msg.Envelope.Subject)
  120. to--
  121. }
  122. if err := <-done; err != nil {
  123. log.Fatal(err)
  124. }
  125. for {
  126. log.Println("读取第几封信信体:")
  127. inLine = readLineFromInput()
  128. mesIndex, _ := strconv.Atoi(inLine)
  129. mesSeqSet := new(imap.SeqSet)
  130. mesSeqSet.AddNum(uint32(mesIndex))
  131. //获取整封信体
  132. var section imap.BodySectionName
  133. items := []imap.FetchItem{section.FetchItem()}
  134. bodyMsg := make(chan *imap.Message, 1)
  135. go func() {
  136. if err := c.Fetch(mesSeqSet, items, bodyMsg); err != nil {
  137. log.Fatal(err)
  138. }
  139. }()
  140. msg := <-bodyMsg
  141. if msg == nil {
  142. log.Fatal("服务器没有返回信息")
  143. }
  144. r := msg.GetBody(&section)
  145. if r == nil {
  146. log.Fatal("服务器没有返回 message body")
  147. }
  148. mr, err := mail.CreateReader(r)
  149. if err != nil {
  150. log.Fatal(err)
  151. }
  152. //打印信息
  153. header := mr.Header
  154. if date, err := header.Date(); err == nil {
  155. log.Println("Date:", date)
  156. }
  157. if from, err := header.AddressList("From"); err == nil {
  158. log.Println("From:", from)
  159. }
  160. if to, err := header.AddressList("To"); err == nil {
  161. log.Println("To:", to)
  162. }
  163. if subject, err := header.Subject(); err == nil {
  164. log.Println("Subject:", subject)
  165. }
  166. // Process each message's part
  167. for {
  168. p, err := mr.NextPart()
  169. if err == io.EOF {
  170. break
  171. } else if err != nil {
  172. log.Fatal(err)
  173. }
  174. switch h := p.Header.(type) {
  175. case *mail.InlineHeader:
  176. // This is the message's text (can be plain-text or HTML)
  177. b, _ := ioutil.ReadAll(p.Body)
  178. log.Printf("Got text: %s\n", string(b))
  179. case *mail.AttachmentHeader:
  180. // This is an attachment
  181. filename, _ := h.Filename()
  182. log.Printf("Got attachment: %s\n", filename)
  183. }
  184. }
  185. log.Printf("读取第 %d 封信, 结束!\n", mesIndex)
  186. }
  187. }
  188. //从输入中读取一行
  189. func readLineFromInput() string {
  190. str := ""
  191. scanner := bufio.NewScanner(os.Stdin)
  192. for scanner.Scan() {
  193. str = scanner.Text() // Println will add back the final '\n'
  194. break
  195. }
  196. return str
  197. }