go-imap包体使用指南

前言:

  • 需要分析邮件基本信息
  • 解析邮件正文
  • 下载附件文件

使用方式

  • 导入包体:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import (
    "github.com/emersion/go-imap"
    "github.com/emersion/go-imap/client"
    _ "github.com/emersion/go-message/charset"
    "github.com/emersion/go-message/mail"
    "io"
    "log"
    "os"
    )
  • 连接服务器,登录服务
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    	log.Println("Connecting to server...")

    //连接到服务器
    c, err := client.DialTLS("imap.feishu.cn:993", nil)
    if err != nil {
    log.Fatal(err)
    }
    log.Println("Connected")

    // 最后不要忘记登出
    defer c.Logout()

    // 登录服务器
    if err := c.Login("[email protected]", "00Bg9ve0yYEYrTJW"); err != nil {
    log.Fatal(err)
    }
    log.Println("Logged in")
  • 使用Search 方法去查找对应条件的邮件
  • 查找未读的邮箱为:&imap.SearchCriteria{Not: []*imap.SearchCriteria{{WithFlags: []string{imap.SeenFlag}}}}
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
       // 获取所有的邮箱文件夹
    mailboxes := make(chan *imap.MailboxInfo, 10)
    done := make(chan error, 1)
    go func() {
    done <- c.List("", "*", mailboxes)
    }()

    if err := <-done; err != nil {
    log.Fatal(err)
    }
  • 返回的是查找到对应的Uid区间,需要遍历才可以找出对应的邮件。
  • 读取邮件内容需要配合 github.com/emersion/go-message/mail 库进行
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    //选择对应的文件夹
    log.Println("* " + m.Name)
    mbox, err := c.Select(m.Name, false)
    if err != nil {
    log.Fatal(err)
    }
    log.Println("Flags for INBOX:", mbox.Flags)
    //获取文件夹中的未读邮件
    searchSeq, err := c.Search(&imap.SearchCriteria{Not: []*imap.SearchCriteria{{WithFlags: []string{imap.SeenFlag}}}})
    if err != nil {
    log.Printf("Error occured while searching: %s\n", err)
    return
    }
    if len(searchSeq) != 0 {
    log.Println("search:", searchSeq)
    //遍历未读取的邮件
    for _, u := range searchSeq {
    seqSet := new(imap.SeqSet)
    seqSet.AddRange(u, u)
    // Get the whole message body
    var section imap.BodySectionName
    items := []imap.FetchItem{section.FetchItem()}
    //读取邮件内容
    messages := make(chan *imap.Message, 1)
    go func() {
    if err := c.Fetch(seqSet, items, messages); err != nil {
    log.Fatal(err)
    }
    }()

    msg := <-messages
    if msg == nil {
    log.Fatal("Server didn't returned message")
    }

    r := msg.GetBody(&section)
    if r == nil {
    log.Fatal("Server didn't returned message body")
    }

    // Create a new mail reader
    mr, err := mail.CreateReader(r)
    if err != nil {
    log.Fatal(err)
    }

    // Print some info about the message
    header := mr.Header
    if date, err := header.Date(); err == nil {
    log.Println("Date:", date)
    }
    if from, err := header.AddressList("From"); err == nil {
    log.Println("From:", from)
    }
    if to, err := header.AddressList("To"); err == nil {
    log.Println("To:", to)
    }
    if subject, err := header.Subject(); err == nil {
    log.Println("Subject:", subject)
    }

    // 从mr中读取邮件信息
    for {
    //读取邮件内容
    p, err := mr.NextPart()
    if err == io.EOF {
    break
    } else if err != nil {
    log.Fatal(err)
    }

    mailDate, errs := header.Date()
    if errs == nil {
    log.Println("Date:", mailDate.Format("01-02-2006"))
    }
    switch h := p.Header.(type) {
    case *mail.InlineHeader:
    //获取邮件的主体信息(可能是纯文本也可能是html)
    b, _ := io.ReadAll(p.Body)
    log.Printf("Got text: %v", string(b))
    case *mail.AttachmentHeader:
    //获取邮件的附件
    filename, _ := h.Filename()
    log.Printf("Got attachment: %v \n", filename)
    dir := mkDir(mailDate.Format("01-02-2006"))
    filename = dir + "/" + filename
    content, _ := io.ReadAll(p.Body)
    writeToFile(filename, string(content))
    }
    }
    //标记邮件为已读
    flags := []interface{}{imap.SeenFlag}
    if err := c.Store(seqSet, imap.AddFlags, flags, nil); err != nil {
    log.Fatal(err)
    }
    }

    }
    }

坑:

  • 别用V2
  • Collect() 不适用于附件提取

引用


go-imap包体使用指南
https://blog.codefish.net/2023/07/13/package-demo-GoPackage-go-imap包体使用指南/
作者
CodeFish
发布于
2023年7月13日
许可协议