package contact import ( "crypto/tls" "fmt" "gitea.inhome.blapointe.com/local/system/sysconf" "log" "net" "net/smtp" "regexp" "strings" "time" pop3 "github.com/taknb2nch/go-pop3" ) // Emailer allows sending of emails (or better // texts with the right address) with TLS. type Emailer interface { Send(string, string) error Check() []Email } type emailer struct { to string from string smtpServer string pop3Server string pwd string } type Email struct { To string From string Date time.Time Subject string Body string } func (e Email) String() string { return fmt.Sprintf("To: %q\nFrom: %q\nSubj: %q\nDate: %q\nBody: %q", e.To, e.From, e.Subject, e.Date.String(), e.Body) } // NewEmailer returns a emailer capable of Send()ing // To the given address. func NewEmailer(To string) Emailer { config := sysconf.Get("email") return &emailer{ smtpServer: config.IP, pop3Server: config.IP2, to: To, from: config.Log, pwd: config.Port, } } // Send sends an email To the configured address with // the given Subject and message. func (e *emailer) Send(subj, msg string) error { // Setup headers headers := make(map[string]string) headers["From"] = e.from headers["To"] = e.to headers["Subject"] = subj Body := "" for k, v := range headers { Body += fmt.Sprintf("%s: %s\r\n", k, v) } Body += "\r\n" + msg // Connect To the SMTP Server c := e.newSmtpClient() defer c.Quit() // To && From if err := c.Mail(e.from); err != nil { log.Panic(err) } if err := c.Rcpt(e.to); err != nil { log.Panic(err) } // Data w, err := c.Data() if err != nil { log.Panic(err) } _, err = w.Write([]byte(Body)) if err != nil { log.Panic(err) } err = w.Close() if err != nil { log.Panic(err) } return nil } func (e *emailer) newSmtpClient() *smtp.Client { host, _, _ := net.SplitHostPort(e.smtpServer) auth := smtp.PlainAuth("", e.from, e.pwd, host) conn := e.getConn(e.smtpServer) c, err := smtp.NewClient(conn, host) if err != nil { log.Panic(err) } // Auth if err = c.Auth(auth); err != nil { log.Panic(err) } return c } func (e *emailer) getConn(remote string) net.Conn { host, _, _ := net.SplitHostPort(remote) tlsconfig := &tls.Config{ InsecureSkipVerify: true, ServerName: host, } // Here is the key, you need To call tls.Dial instead of smtp.Dial // for smtp servers running on 465 that require an ssl connection // From the very beginning (no starttls) conn, err := tls.Dial("tcp", remote, tlsconfig) if err != nil { log.Panic(err) } return conn } func (e *emailer) newPop3Client() *pop3.Client { conn := e.getConn(e.pop3Server) client, err := pop3.NewClient(conn) if err != nil { log.Fatalf("Dial Error: %v\n", err) } if err = client.User(e.from); err != nil { log.Panicf("User Error: %v\n", err) } if err = client.Pass(e.pwd); err != nil { log.Panicf("Pass Error: %v\n", err) } return client } func (e *emailer) Check() []Email { client := e.newPop3Client() defer func() { client.Quit() client.Close() }() var count int var err error if count, _, err = client.Stat(); err != nil { log.Printf("Stat Error: %v\n", err) return nil } var content string emails := make([]Email, count) for i := 1; i <= count; i++ { if content, err = client.Retr(i); err != nil { log.Printf("Retr Error: %v\n", err) return nil } emails[i-1] = parseEmail(content) } return emails } func (e *emailer) pop3all() []Email { conn := e.getConn(e.pop3Server) client, err := pop3.NewClient(conn) if err != nil { log.Fatalf("Dial Error: %v\n", err) } defer func() { client.Quit() client.Close() }() if err = client.User(e.from); err != nil { log.Printf("User Error: %v\n", err) return nil } if err = client.Pass(e.pwd); err != nil { log.Printf("Pass Error: %v\n", err) return nil } var count int var size uint64 if count, size, err = client.Stat(); err != nil { log.Printf("Stat Error: %v\n", err) return nil } log.Printf("Count: %d, Size: %d\n", count, size) if count, size, err = client.List(6); err != nil { log.Printf("List Error: %v\n", err) return nil } log.Printf("Number: %d, Size: %d\n", count, size) var mis []pop3.MessageInfo if mis, err = client.ListAll(); err != nil { log.Printf("LAll Error: %v\n", err) return nil } for _, mi := range mis { log.Printf("Number: %d, Size: %d\n", mi.Number, mi.Size) } var number int var uid string if number, uid, err = client.Uidl(6); err != nil { log.Printf("Uidl Error: %v\n", err) return nil } log.Printf("Number: %d, Uid: %s\n", number, uid) if mis, err = client.UidlAll(); err != nil { log.Printf("UAll Error: %v\n", err) return nil } for _, mi := range mis { log.Printf("Number: %d, Uid: %s\n", mi.Number, mi.Uid) } var content string if content, err = client.Retr(8); err != nil { log.Printf("Retr Error: %v\n", err) return nil } log.Printf("Content:\n%s\n", content) /* if err = client.Dele(6); err != nil { log.Printf("Dele Error: %v\n", err) return nil } */ if err = client.Noop(); err != nil { log.Printf("Noop Error: %v\n", err) return nil } if err = client.Rset(); err != nil { log.Printf("Rset Error: %v\n", err) return nil } return nil } /* type Email struct { To string From string Date time.Time Subject string Body string } */ func parseEmail(content string) Email { To := regexp.MustCompile("\n[Tt]o: .*\n").FindString(content) To = strings.TrimSpace(To) To = strings.Trim(To, "TTo") To = strings.Trim(To, ": {}<>") Subject := regexp.MustCompile("\n[Ss]ubject: .*\n").FindString(content) Subject = strings.TrimSpace(Subject) Subject = strings.Trim(Subject, "SSubject") Subject = strings.Trim(Subject, ": ") when := regexp.MustCompile("[Dd]ate: .*\n").FindString(content) when = strings.Trim(when, "DDate") when = strings.Trim(when, ":") when = strings.TrimSpace(when) Date, err := time.Parse("Mon, 2 Jan 2006 15:04:05 -0700 (MST)", when) if err != nil { log.Println(err) } parseFrom := regexp.MustCompile("[^ ]*@[^ ]*") From := regexp.MustCompile("\n[Ff]rom: .*\n").FindString(content) From = strings.TrimSpace(From) From = parseFrom.FindString(From) From = strings.Trim(From, "<>{}") Body := "" Bodyarr := strings.Split(content, "\n") Body = Bodyarr[len(Bodyarr)-1] return Email{ To: To, From: From, Date: Date, Subject: Subject, Body: Body, } }