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 } mail, err = login(conn, client) if err != nil { return nil, err } return mail, nil } func Login(conn Conn) (mail *Mail, err error) { client, err := client.DialTLS(conn.Addr, nil) if err != nil { return nil, err } mail, err = login(conn, client) if err != nil { return nil, err } return mail, nil } 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 } } if err := <-done; err != nil { return err } return nil } 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 }