fixed some performance issues when pulling a large amount of messages
Signed-off-by: Michael <michael.lindman@gmail.com>
This commit is contained in:
parent
f12e865042
commit
6d4d7e3459
2
go.mod
2
go.mod
@ -5,6 +5,6 @@ go 1.16
|
|||||||
require (
|
require (
|
||||||
github.com/emersion/go-imap v1.2.0
|
github.com/emersion/go-imap v1.2.0
|
||||||
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac // indirect
|
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac // indirect
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63
|
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
)
|
)
|
||||||
|
61
mail/mail.go
61
mail/mail.go
@ -3,11 +3,11 @@ package mail
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
"github.com/emersion/go-imap/client"
|
"github.com/emersion/go-imap/client"
|
||||||
@ -18,19 +18,6 @@ type Mail struct {
|
|||||||
Client *client.Client
|
Client *client.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type Message struct {
|
|
||||||
SeqNum uint32
|
|
||||||
Subject string
|
|
||||||
To []*imap.Address
|
|
||||||
From []*imap.Address
|
|
||||||
Date time.Time
|
|
||||||
Body imap.Literal
|
|
||||||
}
|
|
||||||
|
|
||||||
type Messages struct {
|
|
||||||
Message []Message
|
|
||||||
}
|
|
||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
Addr string
|
Addr string
|
||||||
Username string
|
Username string
|
||||||
@ -76,20 +63,19 @@ func Login(conn Conn) (mail *Mail, err error) {
|
|||||||
return mail, nil
|
return mail, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mail *Mail) GetMessages(mailbox string, msgs int32) (*Messages, error) {
|
func (mail *Mail) GetMessages(mailbox string, path string) error {
|
||||||
var messages Messages
|
|
||||||
mbox, err := mail.Client.Select(mailbox, true)
|
mbox, err := mail.Client.Select(mailbox, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if mbox.Messages == 0 {
|
if mbox.Messages == 0 {
|
||||||
return nil, errors.New("no messages in mailbox")
|
return errors.New("no messages in mailbox")
|
||||||
}
|
}
|
||||||
seqSet := new(imap.SeqSet)
|
seqSet := new(imap.SeqSet)
|
||||||
seqSet.AddRange(1, mbox.Messages)
|
seqSet.AddRange(1, mbox.Messages)
|
||||||
var section imap.BodySectionName
|
var section imap.BodySectionName
|
||||||
|
|
||||||
imapMessages := make(chan *imap.Message, msgs)
|
imapMessages := make(chan *imap.Message, mbox.Messages)
|
||||||
done := make(chan error, 1)
|
done := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
done <- mail.Client.Fetch(seqSet, []imap.FetchItem{imap.FetchEnvelope, section.FetchItem()}, imapMessages)
|
done <- mail.Client.Fetch(seqSet, []imap.FetchItem{imap.FetchEnvelope, section.FetchItem()}, imapMessages)
|
||||||
@ -98,33 +84,26 @@ func (mail *Mail) GetMessages(mailbox string, msgs int32) (*Messages, error) {
|
|||||||
for msg := range imapMessages {
|
for msg := range imapMessages {
|
||||||
body := msg.GetBody(§ion)
|
body := msg.GetBody(§ion)
|
||||||
if body == nil {
|
if body == nil {
|
||||||
return nil, errors.New("server didn't returned message body")
|
return errors.New("server didn't returned message body")
|
||||||
}
|
}
|
||||||
message := Message{
|
fmt.Println(msg.Envelope.Subject)
|
||||||
SeqNum: msg.SeqNum,
|
if err := Write(path, msg, body); err != nil {
|
||||||
Subject: msg.Envelope.Subject,
|
return err
|
||||||
To: msg.Envelope.To,
|
|
||||||
From: msg.Envelope.From,
|
|
||||||
Date: msg.Envelope.Date,
|
|
||||||
Body: body,
|
|
||||||
}
|
}
|
||||||
messages.Message = append(messages.Message, message)
|
|
||||||
}
|
}
|
||||||
if err := <-done; err != nil {
|
if err := <-done; err != nil {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &messages, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteMessages(path string, messages *Messages) error {
|
|
||||||
for _, msg := range messages.Message {
|
|
||||||
body, err := ioutil.ReadAll(msg.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(path+"/"+strconv.Itoa(int(msg.SeqNum))+"_"+msg.Date.String()+".eml", body, 0644); err != nil {
|
return nil
|
||||||
return err
|
}
|
||||||
}
|
|
||||||
}
|
func Write(path string, msg *imap.Message, literal imap.Literal) error {
|
||||||
|
body, err := io.ReadAll(literal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile(path+"/"+strconv.Itoa(int(msg.SeqNum))+"_"+msg.Envelope.Date.String()+".eml", body, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
13
main.go
13
main.go
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfgFile, mailbox, msgs := ui()
|
cfgFile, mailbox := ui()
|
||||||
cfg := NewConfig(*cfgFile)
|
cfg := NewConfig(*cfgFile)
|
||||||
chErr, chDone := make(chan error), make(chan bool)
|
chErr, chDone := make(chan error), make(chan bool)
|
||||||
for _, account := range cfg.Account {
|
for _, account := range cfg.Account {
|
||||||
@ -34,17 +34,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer conn.Client.Logout()
|
defer conn.Client.Logout()
|
||||||
messages, err := conn.GetMessages(*mailbox, int32(*msgs))
|
|
||||||
if err != nil {
|
|
||||||
chErr <- err
|
|
||||||
}
|
|
||||||
path := cfg.Path + username + "/" + time.Now().Format("2006-01-02-15:04:05")
|
path := cfg.Path + username + "/" + time.Now().Format("2006-01-02-15:04:05")
|
||||||
for _, p := range []string{cfg.Path + username, path} {
|
for _, p := range []string{cfg.Path + username, path} {
|
||||||
if _, err := os.Stat(p); os.IsNotExist(err) {
|
if _, err := os.Stat(p); os.IsNotExist(err) {
|
||||||
os.Mkdir(p, 0775)
|
os.Mkdir(p, 0775)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := mail.WriteMessages(path, messages); err != nil {
|
if err = conn.GetMessages(*mailbox, path); err != nil {
|
||||||
chErr <- err
|
chErr <- err
|
||||||
}
|
}
|
||||||
}(account.Addr, account.Username, account.Password, chErr, chDone)
|
}(account.Addr, account.Username, account.Password, chErr, chDone)
|
||||||
@ -59,7 +55,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ui() (cfgFile, mailbox *string, msgs *int) {
|
func ui() (cfgFile, mailbox *string) {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Printf("Usage of %s:\n", os.Args[0])
|
fmt.Printf("Usage of %s:\n", os.Args[0])
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
@ -70,8 +66,7 @@ func ui() (cfgFile, mailbox *string, msgs *int) {
|
|||||||
}
|
}
|
||||||
cfgFile = flag.String("cfgFile", home+"/.config/gomail/config.yaml", "path to config file")
|
cfgFile = flag.String("cfgFile", home+"/.config/gomail/config.yaml", "path to config file")
|
||||||
mailbox = flag.String("mailbox", "inbox", "mailbox to scan messages")
|
mailbox = flag.String("mailbox", "inbox", "mailbox to scan messages")
|
||||||
msgs = flag.Int("msgs", 100, "Number of messages to pull")
|
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
return cfgFile, mailbox, msgs
|
return cfgFile, mailbox
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user