前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Go] 并发imap收信

[Go] 并发imap收信

作者头像
唯一Chat
发布2019-11-26 22:48:09
1.3K0
发布2019-11-26 22:48:09
举报
文章被收录于专栏:陶士涵的菜地

并发数太大会直接死,这里有时候需要多试几次

代码语言:javascript
复制
package main

import (
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "math"
    "os"
    "sync"

    "github.com/emersion/go-imap"
    "github.com/emersion/go-imap/client"
)

var (
    server, email, password string
    workernum               int
    imapClient              *client.Client
    mailDirs                []string
    mailSumNums             uint32
    pagesize                int = 50
    start                   int
    stop                    int
)

type Pool struct {
    workerNum int
    road      chan *Car
    wg        sync.WaitGroup
}

//初始化这个对象
func NewPool(wn int) *Pool {
    return &Pool{workerNum: wn, road: make(chan *Car)}
}

//往channel添加具体任务
func (p *Pool) AddCar(f *Car) {
    p.road <- f
}

//goroutine去工作
func (p *Pool) work(workId int) {
    for f := range p.road {
        log.Println("workId:", workId, "start")
        f.do()
        log.Println("workId:", workId, "done")
    }
    p.wg.Done()
}

//创建goroutine等着接工作
func (p *Pool) Run() {
    for i := 0; i < p.workerNum; i++ {
        go p.work(i)
        p.wg.Add(1)
    }
    p.wg.Wait()
}

func (p *Pool) colse() {
    close(p.road)
}

var pool = NewPool(5)

func main() {
    go handleMail()
    pool.Run()
}
func handleMail() {
    //获取命令行参数
    flag.StringVar(&server, "server", "", "imap服务地址(包含端口)")
    flag.StringVar(&email, "email", "", "邮箱名")
    flag.StringVar(&password, "password", "", "密码")
    flag.Parse()
    if flag.NFlag() < 3 {
        flag.PrintDefaults()
        os.Exit(1)
    }
    if server == "" || email == "" || password == "" {
        log.Fatal("服务器地址,用户名,密码,参数错误")
    }
    //连接imap服务
    imapClient, err := client.Dial(server)
    if err != nil {
        log.Fatal(err)
    }
    //登陆
    if err := imapClient.Login(email, password); err != nil {
        log.Fatal(err)
    }
    //创建邮件夹目录
    os.Mkdir(email, os.ModePerm)
    mailboxes := make(chan *imap.MailboxInfo, 20)
    go func() {
        imapClient.List("", "*", mailboxes)
    }()
    //列取邮件夹
    for m := range mailboxes {
        mailDirs = append(mailDirs, m.Name)
    }
    //循环邮件夹,创建邮件夹目录
    for _, mailDir := range mailDirs {
        //选中每个邮件夹
        mbox, err := imapClient.Select(mailDir, false)
        if err != nil {
            log.Fatal(err)
        }
        mailDirNums := mbox.Messages
        log.Printf("%s : %d", mailDir, mailDirNums)
        fileDir := fmt.Sprintf("%s/%s", email, mailDir)
        //创建邮件夹目录
        os.Mkdir(fileDir, os.ModePerm)
        mailSumNums += mailDirNums
    }
    log.Printf("总邮件数 : %d", mailSumNums)
    //循环邮件夹,读取每个邮件夹中的邮件

    for _, mailDir := range mailDirs {
        //选中每个邮件夹
        mbox, err := imapClient.Select(mailDir, false)
        if err != nil {
            log.Fatal(err)
        }
        if mbox.Messages == 0{
            continue
        }
        //循环该邮件夹中的邮件
        pagecount := int(math.Ceil(float64(mbox.Messages) / float64(pagesize)))
        for i := 1; i <= pagecount; i++ {
            if i == 1 {
                start = 1
            } else {
                start = (i-1)*pagesize + 1
            }
            stop = i * pagesize
            if stop > int(mbox.Messages) {
                stop = int(mbox.Messages)
            }
            car := Car{
                start:      start,
                stop:       stop,
                mailDir:    mailDir,
                imapClient: imapClient,
            }
            pool.AddCar(&car)
        }
    }
    pool.colse()
}

/*具体做的事通过这个来传递*/
type Car struct {
    start, stop int
    mailDir     string
    imapClient  *client.Client
}

//具体做事
func (c *Car) do() error {
    seqset := new(imap.SeqSet)
    seqset.AddRange(uint32(c.start), uint32(c.stop))
    section := &imap.BodySectionName{}
    items := []imap.FetchItem{section.FetchItem()}

    messages := make(chan *imap.Message, pagesize)
    go func() {
        c.imapClient.Fetch(seqset, items, messages)
    }()

    for msg := range messages {
        mailFile := fmt.Sprintf("%s/%s/%d.eml", email, c.mailDir, msg.SeqNum)
        r := msg.GetBody(section)
        if r != nil {
            body, _ := ioutil.ReadAll(r)
            f, _ := os.OpenFile(mailFile, os.O_RDWR|os.O_CREATE, 0766)
            f.Write(body)
            f.Close()
            log.Printf("%s :第 %d ", c.mailDir, msg.SeqNum)
        }
    }
    return nil
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-11-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档