331 lines
6.4 KiB
Go
Executable File
331 lines
6.4 KiB
Go
Executable File
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,
|
|
}
|
|
}
|