[Go] 并发imap收信

2024-03-17 19:58
文章标签 go 并发 imap 收信

本文主要是介绍[Go] 并发imap收信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

package mainimport ("flag""fmt""io/ioutil""log""math""os""sync""github.com/emersion/go-imap""github.com/emersion/go-imap/client"
)var (server, email, password stringworkernum               intimapClient              *client.ClientmailDirs                []stringmailSumNums             uint32pagesize                int = 50start                   intstop                    int
)type Pool struct {workerNum introad      chan *Carwg        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.Messageslog.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 * pagesizeif 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 intmailDir     stringimapClient  *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
}

 

这篇关于[Go] 并发imap收信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/819990

相关文章

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

go中的时间处理过程

《go中的时间处理过程》:本文主要介绍go中的时间处理过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 获取当前时间2 获取当前时间戳3 获取当前时间的字符串格式4 相互转化4.1 时间戳转时间字符串 (int64 > string)4.2 时间字符串转时间

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中