package main import ( "crypto/tls" "flag" "fmt" "io" "log" "os" "github.com/DusanKasan/parsemail" "github.com/emersion/go-imap" "github.com/emersion/go-imap/client" "github.com/emersion/go-message/mail" "gopkg.in/ini.v1" ) var imapconfig ImapConfig var searchconfig SearchConfig var outputconfig OutputConfig var err error type ImapConfig struct { Hostname string Port int Username string Password string Path string } type SearchConfig struct { From string } type OutputConfig struct { Path string } func usage() { fmt.Fprintf(os.Stderr, "usage: imap [inputfile]\n") flag.PrintDefaults() os.Exit(0) } func GetConfig() { flag.Usage = usage flag.Parse() var configfile string if len(os.Args) > 1 { configfile = os.Args[1] } else { usage() os.Exit(2) } HandleError(err) config, err := ini.Load(configfile) HandleError(err) imapconfig_section := config.Section("imap") imapconfig.Hostname = imapconfig_section.Key("hostname").String() imapconfig.Port, err = imapconfig_section.Key("port").Int() imapconfig.Username = imapconfig_section.Key("username").String() imapconfig.Password = imapconfig_section.Key("password").String() imapconfig.Path = imapconfig_section.Key("path").String() searchconfig_section := config.Section("search") searchconfig.From = searchconfig_section.Key("from").String() outputconfig_section := config.Section("output") outputconfig.Path = outputconfig_section.Key("path").String() HandleError(err) } func Connect() *client.Client { tr := &tls.Config{InsecureSkipVerify: true} c, err := client.DialTLS(fmt.Sprintf("%s:%d", imapconfig.Hostname, imapconfig.Port), tr) if err != nil { log.Fatal(err) } if err := c.Login(imapconfig.Username, imapconfig.Password); err != nil { log.Fatal(err) } return c } func ListMailboxes(c *client.Client) bool { mailboxes := make(chan *imap.MailboxInfo, 10) done := make(chan error, 1) go func() { done <- c.List("", "*", mailboxes) }() log.Println("Mailboxes:") for m := range mailboxes { log.Println("* " + m.Name) } if err := <-done; err != nil { log.Fatal(err) } return true } func GetInboxMessages() []*imap.Message { var e []*imap.Message return e } func GetMessage(id uint32) bool { return true } func Search() { /* criteria := new(imap.SearchCriteria) criteria.WithoutFlags = []string{imap.UnSeenFlag} criteria.Header = textproto.MIMEHeader{"From": {"si-france@logarius.com"}} fromcrit := make(textproto.MIMEHeader) fromcrit.Get("From") criteria.Header = fromcrit log.Println("ids : ") ids, err := c.Search(criteria) log.Println(ids) */ } func main() { GetConfig() var c = Connect() defer c.Logout() //ListMailboxes(c) mbox, err := c.Select(imapconfig.Path, false) if err != nil { log.Fatal(err) } seqset := new(imap.SeqSet) seqset.AddRange(1, mbox.Messages) //seqSet.Add("1:*") messages := make(chan *imap.Message, 1) done := make(chan error, 1) go func() { done <- c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope}, messages) }() var id uint32 for msg := range messages { from_addr_struct := msg.Envelope.From[0] from_addr := fmt.Sprintf("%s@%s", from_addr_struct.MailboxName, from_addr_struct.HostName) //log.Println(from_addr) if from_addr == searchconfig.From { //log.Println(msg.SeqNum) id = msg.SeqNum //log.Println(fmt.Sprint(msg.SeqNum)) } //log.Println("*** " + from_addr + ", " + msg.Envelope.Subject + " " + fmt.Sprint(msg.SeqNum)) } msgseqset := new(imap.SeqSet) msgseqset.AddRange(id, id) section := &imap.BodySectionName{} items := []imap.FetchItem{section.FetchItem()} message := make(chan *imap.Message, 1) go func() { done <- c.Fetch(msgseqset, items, message) }() msg := <-message if msg == nil { log.Fatal("Server didn't returned message") } r := msg.GetBody(section) if r == nil { log.Fatal("Server didn't returned message body") } email, err := parsemail.Parse(r) for _, a := range email.Attachments { /*log.Println("aaaa",a.Filename) log.Println("aaaa",a.ContentType)*/ var destpath = fmt.Sprintf("%s/%s", outputconfig.Path, a.Filename) log.Println(fmt.Sprintf("Writing attachement : %s", destpath)) WriteFile(destpath, a.Data) //and read a.Data } mr, err := mail.CreateReader(r) if err != nil { log.Fatal(err) } header := mr.Header if date, err := header.Date(); err == nil { log.Println("Date:", date) } if err := <-done; err != nil { log.Fatal(err) } /* for { p, err := mr.NextPart() if err == io.EOF { break } else if err != nil { log.Fatal(err) } switch h := p.Header.(type) { case mail.AttachmentHeader: // This is an attachment filename, _ := h.Filename() log.Println(fmt.Sprintf("Got attachment: %v", filename)) } } */ os.Exit(0) } func WriteFile(destpath string, data io.Reader) { fo, err := os.Create(destpath) HandleError(err) defer func() { if err := fo.Close(); err != nil { panic(err) } }() buf := make([]byte, 1024) for { n, err := data.Read(buf) if err != nil && err != io.EOF { panic(err) } if n == 0 { break } if _, err := fo.Write(buf[:n]); err != nil { panic(err) } } } func HandleError(err error) { if err != nil { log.Fatal(err) } }