imap.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. package tools
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/axgle/mahonia"
  6. "github.com/emersion/go-imap"
  7. "github.com/emersion/go-imap/client"
  8. "github.com/emersion/go-message/mail"
  9. "io"
  10. "io/ioutil"
  11. "log"
  12. "mime"
  13. "strconv"
  14. "strings"
  15. )
  16. //验证邮箱密码
  17. func CheckEmailPassword(server string, email string, password string) bool {
  18. if !strings.Contains(server, ":") {
  19. return false
  20. }
  21. var c *client.Client
  22. serverSlice := strings.Split(server, ":")
  23. port, _ := strconv.Atoi(serverSlice[1])
  24. if port != 993 && port != 143 {
  25. return false
  26. }
  27. // 不要忘了退出
  28. //defer c.Logout()
  29. // 登陆
  30. c = connect(server, email, password)
  31. if c == nil {
  32. return false
  33. }
  34. return true
  35. }
  36. //获取连接
  37. func connect(server string, email string, password string) *client.Client {
  38. var c *client.Client
  39. var err error
  40. serverSlice := strings.Split(server, ":")
  41. uri := serverSlice[0]
  42. port, _ := strconv.Atoi(serverSlice[1])
  43. if port != 993 && port != 143 {
  44. return nil
  45. }
  46. if port == 993 {
  47. c, err = client.DialTLS(fmt.Sprintf("%s:%d", uri, port), nil)
  48. } else {
  49. c, err = client.Dial(fmt.Sprintf("%s:%d", uri, port))
  50. }
  51. if err != nil {
  52. return nil
  53. }
  54. // 登陆
  55. if err := c.Login(email, password); err != nil {
  56. return nil
  57. }
  58. return c
  59. }
  60. //获取邮件总数
  61. func GetMailNum(server string, email string, password string) map[string]int {
  62. var c *client.Client
  63. //defer c.Logout()
  64. c = connect(server, email, password)
  65. if c == nil {
  66. return nil
  67. }
  68. // 列邮箱
  69. mailboxes := make(chan *imap.MailboxInfo, 10)
  70. done := make(chan error, 1)
  71. go func() {
  72. done <- c.List("", "*", mailboxes)
  73. }()
  74. //// 存储邮件夹
  75. var folders = make(map[string]int)
  76. for m := range mailboxes {
  77. folders[m.Name] = 0
  78. }
  79. for m, _ := range folders {
  80. mbox, _ := c.Select(m, true)
  81. if mbox != nil {
  82. folders[m] = int(mbox.Messages)
  83. }
  84. }
  85. return folders
  86. }
  87. //获取邮件夹
  88. func GetFolders(server string, email string, password string, folder string) map[string]int {
  89. var c *client.Client
  90. //defer c.Logout()
  91. c = connect(server, email, password)
  92. if c == nil {
  93. return nil
  94. }
  95. // 列邮箱
  96. mailboxes := make(chan *imap.MailboxInfo, 10)
  97. done := make(chan error, 1)
  98. go func() {
  99. done <- c.List("", "*", mailboxes)
  100. }()
  101. // 存储邮件夹
  102. var folders = make(map[string]int)
  103. for m := range mailboxes {
  104. folders[m.Name] = 0
  105. }
  106. for m, _ := range folders {
  107. if m == folder {
  108. mbox, _ := c.Select(m, true)
  109. if mbox != nil {
  110. folders[m] = int(mbox.Messages)
  111. }
  112. break
  113. }
  114. }
  115. //log.Println(folders)
  116. return folders
  117. }
  118. //获取邮件夹邮件
  119. func GetFolderMail(server string, email string, password string, folder string, currentPage int, pagesize int) []*MailItem {
  120. var c *client.Client
  121. //defer c.Logout()
  122. c = connect(server, email, password)
  123. if c == nil {
  124. return nil
  125. }
  126. mbox, _ := c.Select(folder, true)
  127. to := mbox.Messages - uint32((currentPage-1)*pagesize)
  128. from := to - uint32(pagesize)
  129. if to <= uint32(pagesize) {
  130. from = 1
  131. }
  132. seqset := new(imap.SeqSet)
  133. seqset.AddRange(from, to)
  134. messages := make(chan *imap.Message, pagesize)
  135. done := make(chan error, 1)
  136. fetchItem := imap.FetchItem(imap.FetchEnvelope)
  137. items := make([]imap.FetchItem, 0)
  138. items = append(items, fetchItem)
  139. go func() {
  140. done <- c.Fetch(seqset, items, messages)
  141. }()
  142. var mailPagelist = new(MailPageList)
  143. dec := GetDecoder()
  144. for msg := range messages {
  145. log.Println(msg.Envelope.Date)
  146. ret, err := dec.Decode(msg.Envelope.Subject)
  147. if err != nil {
  148. ret, _ = dec.DecodeHeader(msg.Envelope.Subject)
  149. }
  150. var mailitem = new(MailItem)
  151. mailitem.Subject = ret
  152. mailitem.Id = msg.SeqNum
  153. mailitem.Fid = folder
  154. mailitem.Date = msg.Envelope.Date.String()
  155. from := ""
  156. for _, s := range msg.Envelope.Sender {
  157. from += s.Address()
  158. }
  159. mailitem.From = from
  160. mailPagelist.MailItems = append(mailPagelist.MailItems, mailitem)
  161. }
  162. return mailPagelist.MailItems
  163. }
  164. func GetMessage(server string, email string, password string, folder string, id uint32) *MailItem {
  165. var c *client.Client
  166. //defer c.Logout()
  167. c = connect(server, email, password)
  168. if c == nil {
  169. //return nil
  170. }
  171. // Select INBOX
  172. mbox, err := c.Select(folder, false)
  173. if err != nil {
  174. log.Fatal(err)
  175. }
  176. // Get the last message
  177. if mbox.Messages == 0 {
  178. log.Fatal("No message in mailbox")
  179. }
  180. seqSet := new(imap.SeqSet)
  181. seqSet.AddNum(id)
  182. // Get the whole message body
  183. section := &imap.BodySectionName{}
  184. items := []imap.FetchItem{section.FetchItem()}
  185. messages := make(chan *imap.Message, 1)
  186. go func() {
  187. if err := c.Fetch(seqSet, items, messages); err != nil {
  188. log.Fatal(err)
  189. }
  190. }()
  191. msg := <-messages
  192. if msg == nil {
  193. log.Fatal("Server didn't returned message")
  194. }
  195. r := msg.GetBody(section)
  196. if r == nil {
  197. log.Fatal("Server didn't returned message body")
  198. }
  199. var mailitem = new(MailItem)
  200. // Create a new mail reader
  201. mr, _ := mail.CreateReader(r)
  202. // Print some info about the message
  203. header := mr.Header
  204. date, _ := header.Date()
  205. mailitem.Date = date.String()
  206. var f string
  207. dec := GetDecoder()
  208. if from, err := header.AddressList("From"); err == nil {
  209. for _, address := range from {
  210. fromStr := address.String()
  211. temp, _ := dec.DecodeHeader(fromStr)
  212. f += " " + temp
  213. }
  214. }
  215. mailitem.From = f
  216. log.Println("From:", mailitem.From)
  217. var t string
  218. if to, err := header.AddressList("To"); err == nil {
  219. log.Println("To:", to)
  220. for _, address := range to {
  221. toStr := address.String()
  222. temp, _ := dec.DecodeHeader(toStr)
  223. t += " " + temp
  224. }
  225. }
  226. mailitem.To = t
  227. subject, _ := header.Subject()
  228. s, err := dec.Decode(subject)
  229. if err != nil {
  230. s, _ = dec.DecodeHeader(subject)
  231. }
  232. log.Println("Subject:", s)
  233. mailitem.Subject = s
  234. // Process each message's part
  235. var bodyMap = make(map[string]string)
  236. bodyMap["text/plain"] = ""
  237. bodyMap["text/html"] = ""
  238. for {
  239. p, err := mr.NextPart()
  240. if err == io.EOF {
  241. break
  242. } else if err != nil {
  243. //log.Fatal(err)
  244. }
  245. switch h := p.Header.(type) {
  246. case *mail.InlineHeader:
  247. // This is the message's text (can be plain-text or HTML)
  248. b, _ := ioutil.ReadAll(p.Body)
  249. ct := p.Header.Get("Content-Type")
  250. if strings.Contains(ct, "text/plain") {
  251. bodyMap["text/plain"] += Encoding(string(b), ct)
  252. } else {
  253. bodyMap["text/html"] += Encoding(string(b), ct)
  254. }
  255. //body,_:=dec.Decode(string(b))
  256. case *mail.AttachmentHeader:
  257. // This is an attachment
  258. filename, _ := h.Filename()
  259. log.Println("Got attachment: ", filename)
  260. }
  261. }
  262. if bodyMap["text/html"] != "" {
  263. mailitem.Body = bodyMap["text/html"]
  264. } else {
  265. mailitem.Body = bodyMap["text/plain"]
  266. }
  267. //log.Println(mailitem.Body)
  268. return mailitem
  269. }
  270. func GetDecoder() *mime.WordDecoder {
  271. dec := new(mime.WordDecoder)
  272. dec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
  273. charset = strings.ToLower(charset)
  274. switch charset {
  275. case "gb2312":
  276. content, err := ioutil.ReadAll(input)
  277. if err != nil {
  278. return nil, err
  279. }
  280. //ret:=bytes.NewReader(content)
  281. //ret:=transform.NewReader(bytes.NewReader(content), simplifiedchinese.HZGB2312.NewEncoder())
  282. utf8str := ConvertToStr(string(content), "gbk", "utf-8")
  283. t := bytes.NewReader([]byte(utf8str))
  284. //ret:=utf8.DecodeRune(t)
  285. //log.Println(ret)
  286. return t, nil
  287. case "gbk":
  288. content, err := ioutil.ReadAll(input)
  289. if err != nil {
  290. return nil, err
  291. }
  292. //ret:=bytes.NewReader(content)
  293. //ret:=transform.NewReader(bytes.NewReader(content), simplifiedchinese.HZGB2312.NewEncoder())
  294. utf8str := ConvertToStr(string(content), "gbk", "utf-8")
  295. t := bytes.NewReader([]byte(utf8str))
  296. //ret:=utf8.DecodeRune(t)
  297. //log.Println(ret)
  298. return t, nil
  299. case "gb18030":
  300. content, err := ioutil.ReadAll(input)
  301. if err != nil {
  302. return nil, err
  303. }
  304. //ret:=bytes.NewReader(content)
  305. //ret:=transform.NewReader(bytes.NewReader(content), simplifiedchinese.HZGB2312.NewEncoder())
  306. utf8str := ConvertToStr(string(content), "gbk", "utf-8")
  307. t := bytes.NewReader([]byte(utf8str))
  308. //ret:=utf8.DecodeRune(t)
  309. //log.Println(ret)
  310. return t, nil
  311. default:
  312. return nil, fmt.Errorf("unhandle charset:%s", charset)
  313. }
  314. }
  315. return dec
  316. }
  317. // 任意编码转特定编码
  318. func ConvertToStr(src string, srcCode string, tagCode string) string {
  319. result := mahonia.NewDecoder(srcCode).ConvertString(src)
  320. //srcCoder := mahonia.NewDecoder(srcCode)
  321. //srcResult := srcCoder.ConvertString(src)
  322. //tagCoder := mahonia.NewDecoder(tagCode)
  323. //_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
  324. //result := string(cdata)
  325. return result
  326. }