Golang Gmail IMAP搜索冻结了。

huangapple go评论117阅读模式
英文:

Golang Gmail imap search is freezing

问题

我正在尝试搜索特定发件人或特定标记。当我选择收件箱并在特定字符串上进行搜索时,搜索 API 会冻结。我不确定我做错了什么。我也找不到太多的示例。

  1. criteria := imap.NewSearchCriteria()
  2. criteria.WithoutFlags = []string{"\\Seen"}
  3. uids, err := c.Search(criteria)
  4. if err != nil {
  5. log.Println(err)
  6. }
  7. seqset := new(imap.SeqSet)
  8. seqset.AddNum(uids...)
  9. section := &imap.BodySectionName{}
  10. items := []imap.FetchItem{imap.FetchEnvelope, imap.FetchFlags, imap.FetchInternalDate, section.FetchItem()}
  11. messages := make(chan *imap.Message)
  12. go func() {
  13. done <- c.Fetch(seqset, items, messages)
  14. }()
  15. msg := <-messages // 它在这一点上被卡住了。什么都不会发生,我收不到消息。

请注意,这是一段代码,我只翻译了其中的注释部分。

英文:

I am trying to do a search for specific sender or specific flag. When I select Inbox and do a search on specific string the search api freezes. I am not sure what am I doing wrong. I am not able to find much examples too.

  1. criteria := imap.NewSearchCriteria()
  2. criteria.WithoutFlags = []string{&quot;\\Seen&quot;}
  3. uids, err := c.Search(criteria)
  4. if err != nil {
  5. log.Println(err)
  6. }
  7. seqset := new(imap.SeqSet)
  8. seqset.AddNum(uids...)
  9. section := &amp;imap.BodySectionName{}
  10. items := []imap.FetchItem{imap.FetchEnvelope, imap.FetchFlags, imap.FetchInternalDate, section.FetchItem()}
  11. messages := make(chan *imap.Message)
  12. go func() {
  13. done &lt;- c.Fetch(seqset, items, messages)
  14. }()
  15. msg := &lt;-messages //its getting stuck at this point. Nothing happens i dont get messages.

答案1

得分: 2

当你的搜索可能返回多条消息时,你需要确保从messages通道中读取所有内容,否则程序将会挂起。所以,不要使用以下方式:

  1. msg := <-messages

而是使用以下方式循环遍历通道:

  1. for msg := range messages {
  2. // 处理消息
  3. }

这是一个可以工作的示例,它从环境中获取连接详细信息。这是从emersion的imap库修改的示例:

  1. package main
  2. import (
  3. "crypto/tls"
  4. "flag"
  5. "fmt"
  6. "log"
  7. "os"
  8. "time"
  9. "github.com/emersion/go-imap"
  10. "github.com/emersion/go-imap/client"
  11. )
  12. func main() {
  13. hours := flag.Int("hours", 24, "look this many hours in the past for messages")
  14. flag.Parse()
  15. if *hours > 0 {
  16. *hours = *hours * -1
  17. }
  18. host := os.Getenv("IMAP_HOST")
  19. port := os.Getenv("IMAP_PORT")
  20. user := os.Getenv("IMAP_USER")
  21. pass := os.Getenv("IMAP_PASS")
  22. tlsn := os.Getenv("IMAP_TLS_SERVERNAME")
  23. if port == "" {
  24. port = "993"
  25. }
  26. connStr := fmt.Sprintf("%s:%s", host, port)
  27. tlsc := &tls.Config{}
  28. if tlsn != "" {
  29. tlsc.ServerName = tlsn
  30. }
  31. c, err := client.DialTLS(connStr, tlsc)
  32. if err != nil {
  33. log.Fatal(err)
  34. }
  35. log.Println("Connected")
  36. defer c.Logout()
  37. if err := c.Login(user, pass); err != nil {
  38. log.Fatal(err)
  39. }
  40. log.Println("Authenticated")
  41. mbox, err := c.Select("INBOX", false)
  42. if err != nil {
  43. log.Fatal(err)
  44. }
  45. log.Println("Flags for INBOX:", mbox.Flags)
  46. criteria := imap.NewSearchCriteria()
  47. //criteria.WithFlags = []string{imap.SeenFlag}
  48. criteria.Since = time.Now().Add(time.Duration(*hours) * time.Hour)
  49. uids, err := c.Search(criteria)
  50. if err != nil {
  51. log.Println(err)
  52. }
  53. seqset := new(imap.SeqSet)
  54. seqset.AddNum(uids...)
  55. log.Printf("Search complete, found %d messages", len(uids))
  56. section := &imap.BodySectionName{}
  57. items := []imap.FetchItem{imap.FetchEnvelope, imap.FetchFlags, imap.FetchInternalDate, section.FetchItem()}
  58. messages := make(chan *imap.Message)
  59. done := make(chan error, 1)
  60. go func() {
  61. done <- c.Fetch(seqset, items, messages)
  62. log.Println("Fetch complete")
  63. }()
  64. for msg := range messages {
  65. if msg != nil {
  66. log.Printf("got message with address %p\n", msg)
  67. } else {
  68. log.Println("no messages matched criteria")
  69. }
  70. }
  71. if err := <-done; err != nil {
  72. log.Fatal(err)
  73. }
  74. }
英文:

When your search can return more than one message, you need to make sure to read everything from the messages channel, otherwise the program will hang. So instead of:

  1. msg := &lt;-messages

loop over the channel like so:

  1. for msg := range messages {
  2. // process msg
  3. }

Here's my working sample, which pulls connection details from the environment. It's a modified version of the example from emersion's imap lib:

  1. package main
  2. import (
  3. &quot;crypto/tls&quot;
  4. &quot;flag&quot;
  5. &quot;fmt&quot;
  6. &quot;log&quot;
  7. &quot;os&quot;
  8. &quot;time&quot;
  9. &quot;github.com/emersion/go-imap&quot;
  10. &quot;github.com/emersion/go-imap/client&quot;
  11. )
  12. func main() {
  13. hours := flag.Int(&quot;hours&quot;, 24, &quot;look this many hours in the past for messages&quot;)
  14. flag.Parse()
  15. if *hours &gt; 0 {
  16. *hours = *hours * -1
  17. }
  18. host := os.Getenv(&quot;IMAP_HOST&quot;)
  19. port := os.Getenv(&quot;IMAP_PORT&quot;)
  20. user := os.Getenv(&quot;IMAP_USER&quot;)
  21. pass := os.Getenv(&quot;IMAP_PASS&quot;)
  22. tlsn := os.Getenv(&quot;IMAP_TLS_SERVERNAME&quot;)
  23. if port == &quot;&quot; {
  24. port = &quot;993&quot;
  25. }
  26. connStr := fmt.Sprintf(&quot;%s:%s&quot;, host, port)
  27. tlsc := &amp;tls.Config{}
  28. if tlsn != &quot;&quot; {
  29. tlsc.ServerName = tlsn
  30. }
  31. c, err := client.DialTLS(connStr, tlsc)
  32. if err != nil {
  33. log.Fatal(err)
  34. }
  35. log.Println(&quot;Connected&quot;)
  36. defer c.Logout()
  37. if err := c.Login(user, pass); err != nil {
  38. log.Fatal(err)
  39. }
  40. log.Println(&quot;Authenticated&quot;)
  41. mbox, err := c.Select(&quot;INBOX&quot;, false)
  42. if err != nil {
  43. log.Fatal(err)
  44. }
  45. log.Println(&quot;Flags for INBOX:&quot;, mbox.Flags)
  46. criteria := imap.NewSearchCriteria()
  47. //criteria.WithFlags = []string{imap.SeenFlag}
  48. criteria.Since = time.Now().Add(time.Duration(*hours) * time.Hour)
  49. uids, err := c.Search(criteria)
  50. if err != nil {
  51. log.Println(err)
  52. }
  53. seqset := new(imap.SeqSet)
  54. seqset.AddNum(uids...)
  55. log.Printf(&quot;Search complete, found %d messages&quot;, len(uids))
  56. section := &amp;imap.BodySectionName{}
  57. items := []imap.FetchItem{imap.FetchEnvelope, imap.FetchFlags, imap.FetchInternalDate, section.FetchItem()}
  58. messages := make(chan *imap.Message)
  59. done := make(chan error, 1)
  60. go func() {
  61. done &lt;- c.Fetch(seqset, items, messages)
  62. log.Println(&quot;Fetch complete&quot;)
  63. }()
  64. for msg := range messages {
  65. if msg != nil {
  66. log.Printf(&quot;got message with address %p\n&quot;, msg)
  67. } else {
  68. log.Println(&quot;no messages matched criteria&quot;)
  69. }
  70. }
  71. if err := &lt;-done; err != nil {
  72. log.Fatal(err)
  73. }
  74. }

huangapple
  • 本文由 发表于 2018年6月15日 01:27:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/50862938.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定