Implement folder mail notifier

This commit is contained in:
2024-08-25 21:48:47 +02:00
commit 128fdc5f85
5 changed files with 193 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
test
main.log

13
go.mod Normal file
View File

@@ -0,0 +1,13 @@
module folder-mail-notifier
go 1.23.0
require (
github.com/joho/godotenv v1.5.1
gopkg.in/fsnotify.v1 v1.4.7
)
require (
github.com/fsnotify/fsnotify v1.7.0 // indirect
golang.org/x/sys v0.24.0 // indirect
)

8
go.sum Normal file
View File

@@ -0,0 +1,8 @@
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=

111
main.go Normal file
View File

@@ -0,0 +1,111 @@
package main
import (
_ "embed"
"fmt"
"io"
"log"
"net/smtp"
"os"
"strings"
"time"
"github.com/joho/godotenv"
"gopkg.in/fsnotify.v1"
)
var Error *log.Logger
var Warning *log.Logger
func init() {
log.SetFlags(log.Lmicroseconds | log.Lshortfile)
logFile, err := os.Create("main.log")
if err != nil {
log.Printf("Error creating log file: %v", err)
os.Exit(1)
}
logger := io.MultiWriter(os.Stdout, logFile)
log.SetOutput(logger)
Error = log.New(io.MultiWriter(logFile, os.Stderr, os.Stdout),
fmt.Sprintf("%sERROR:%s ", "\033[0;101m", "\033[0m"),
log.Lmicroseconds|log.Lshortfile)
Warning = log.New(io.MultiWriter(logFile, os.Stdout),
fmt.Sprintf("%sWarning:%s ", "\033[0;93m", "\033[0m"),
log.Lmicroseconds|log.Lshortfile)
}
//go:embed .env
var env string
var envvar map[string]string
var queued bool
var changes = []*fsnotify.Event{}
func main() {
var err error
envvar, err = godotenv.Parse(strings.NewReader(env))
if err != nil {
Error.Fatalf("Error parsing .env file: %v", err)
return
}
root, ok := envvar["ROOT"]
if !ok {
Error.Fatalf("Error parsing ROOT variable: %v", err)
return
}
WatchRecursively(root, func(event fsnotify.Event) {
if !queued {
// time.AfterFunc(5*time.Minute, func() { doNotify() })
delay := 5*time.Second
log.Printf("Mailing changes in %v seconds", delay.Seconds())
time.AfterFunc(delay, func() { doNotify() })
queued = true
}
changes = append(changes, &event)
})
}
func doNotify() error {
defer func() { queued = false }()
smtpHost, ok := envvar["SMTP_HOST"]
if !ok {
return fmt.Errorf("error getting env var SMTP_HOST")
}
smtpPort, ok := envvar["SMTP_PORT"]
if !ok {
return fmt.Errorf("error getting env var SMTP_PORT")
}
smtpUser, ok := envvar["SMTP_USER"]
if !ok {
return fmt.Errorf("error getting env var SMTP_USER")
}
smtpPass, ok := envvar["SMTP_PASSWORD"]
if !ok {
return fmt.Errorf("error getting env var SMTP_PASSWORD")
}
log.Printf("Mailing %v changes", len(changes))
strchanges := make([]string, 0, len(changes))
for _, change := range changes {
strchanges = append(strchanges, change.String())
}
from := "admin@quack-lab.dev"
to := []string{"david.majdandzic@hotmail.com"}
subject := "New files:"
body := strings.Join(strchanges, "\n")
msg := []byte(fmt.Sprintf("Subject: %s\nFrom: %s\nTo: %s\n\n%s", subject, from, strings.Join(to, ","), body))
auth := smtp.PlainAuth("", smtpUser, smtpPass, smtpHost)
err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, to, msg)
if err != nil {
return err
}
log.Println("Sent mail")
changes = []*fsnotify.Event{}
return nil
}

59
watcher.go Normal file
View File

@@ -0,0 +1,59 @@
package main
import (
"os"
"path/filepath"
"gopkg.in/fsnotify.v1"
)
func WatchRecursively(root string, changeHandler func(fsnotify.Event)) error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
changeHandler(event)
case err, ok := <-watcher.Errors:
if !ok {
return
}
Error.Printf("error with watcher: %v", err)
}
}
}()
dirs := 0
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.Name() == ".git" {
return filepath.SkipDir
}
if info.IsDir() {
err = watcher.Add(path)
dirs++
if err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}
<-done
return nil
}