117 lines
2.5 KiB
Go
117 lines
2.5 KiB
Go
package mail
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/emersion/go-imap"
|
|
"github.com/emersion/go-imap/client"
|
|
"golang.org/x/net/proxy"
|
|
)
|
|
|
|
type Mail struct {
|
|
Client *client.Client
|
|
}
|
|
|
|
type Conn struct {
|
|
Addr string
|
|
Username string
|
|
Password string
|
|
}
|
|
|
|
func login(conn Conn, client *client.Client) (mail *Mail, err error) {
|
|
fmt.Fprintf(os.Stdout, "\x1b[32mConnecting to %s\n\x1b[0m", conn.Addr)
|
|
if err = client.Login(conn.Username, conn.Password); err != nil {
|
|
return nil, err
|
|
}
|
|
log.Println("Logged in as", conn.Username)
|
|
return &Mail{
|
|
Client: client,
|
|
}, nil
|
|
}
|
|
|
|
func LoginWithProxy(conn Conn, network string, proxyAddress string, auth *proxy.Auth) (mail *Mail, err error) {
|
|
proxy, err := proxy.SOCKS5("tcp", proxyAddress, auth, proxy.Direct)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
client, err := client.DialWithDialerTLS(proxy, conn.Addr, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return login(conn, client)
|
|
}
|
|
|
|
func Login(conn Conn) (mail *Mail, err error) {
|
|
client, err := client.DialTLS(conn.Addr, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return login(conn, client)
|
|
}
|
|
|
|
func (mail *Mail) ListMailboxes() {
|
|
mailboxes := make(chan *imap.MailboxInfo, 10)
|
|
done := make(chan error, 1)
|
|
|
|
go func() {
|
|
done <- mail.Client.List("", "*", mailboxes)
|
|
}()
|
|
|
|
log.Println("Mailboxes:")
|
|
for m := range mailboxes {
|
|
log.Println("* " + m.Name)
|
|
}
|
|
|
|
if err := <-done; err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func (mail *Mail) GetMessages(mailbox string, path string) error {
|
|
mbox, err := mail.Client.Select(mailbox, true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if mbox.Messages == 0 {
|
|
return errors.New("no messages in mailbox")
|
|
}
|
|
seqSet := new(imap.SeqSet)
|
|
seqSet.AddRange(1, mbox.Messages)
|
|
var section imap.BodySectionName
|
|
|
|
imapMessages := make(chan *imap.Message, mbox.Messages)
|
|
done := make(chan error, 1)
|
|
go func() {
|
|
done <- mail.Client.Fetch(seqSet, []imap.FetchItem{imap.FetchEnvelope, section.FetchItem()}, imapMessages)
|
|
}()
|
|
|
|
for msg := range imapMessages {
|
|
body := msg.GetBody(§ion)
|
|
if body == nil {
|
|
return errors.New("server didn't returned message body")
|
|
}
|
|
fmt.Println(msg.Envelope.Subject)
|
|
if err := Write(path, msg, body); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return <-done
|
|
}
|
|
|
|
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
|
|
}
|