1
0
Fork 0
mirror of https://github.com/binwiederhier/ntfy.git synced 2025-05-03 23:41:30 +02:00

Send emails

This commit is contained in:
Philipp Heckel 2021-12-23 21:04:17 +01:00
parent c8c53eed07
commit 873c57b3d8
6 changed files with 46 additions and 14 deletions

View file

@ -7,7 +7,6 @@ import (
"github.com/urfave/cli/v2/altsrc" "github.com/urfave/cli/v2/altsrc"
"heckel.io/ntfy/util" "heckel.io/ntfy/util"
"os" "os"
"strings"
) )
var ( var (
@ -60,7 +59,3 @@ func initConfigFileInputSource(configFlag string, flags []cli.Flag) cli.BeforeFu
return altsrc.ApplyInputSourceValues(context, inputSource, flags) return altsrc.ApplyInputSourceValues(context, inputSource, flags)
} }
} }
func collapseTopicURL(s string) string {
return strings.TrimPrefix(strings.TrimPrefix(s, "https://"), "http://")
}

View file

@ -95,6 +95,7 @@ func execServe(c *cli.Context) error {
conf.CacheDuration = cacheDuration conf.CacheDuration = cacheDuration
conf.KeepaliveInterval = keepaliveInterval conf.KeepaliveInterval = keepaliveInterval
conf.ManagerInterval = managerInterval conf.ManagerInterval = managerInterval
//XXXXXXXXX
conf.GlobalTopicLimit = globalTopicLimit conf.GlobalTopicLimit = globalTopicLimit
conf.VisitorSubscriptionLimit = visitorSubscriptionLimit conf.VisitorSubscriptionLimit = visitorSubscriptionLimit
conf.VisitorRequestLimitBurst = visitorRequestLimitBurst conf.VisitorRequestLimitBurst = visitorRequestLimitBurst

View file

@ -180,7 +180,7 @@ func runCommandInternal(c *cli.Context, command string, m *client.Message) error
defer os.Remove(scriptFile) defer os.Remove(scriptFile)
verbose := c.Bool("verbose") verbose := c.Bool("verbose")
if verbose { if verbose {
log.Printf("[%s] Executing: %s (for message: %s)", collapseTopicURL(m.TopicURL), command, m.Raw) log.Printf("[%s] Executing: %s (for message: %s)", util.ShortTopicURL(m.TopicURL), command, m.Raw)
} }
cmd := exec.Command("sh", "-c", scriptFile) cmd := exec.Command("sh", "-c", scriptFile)
cmd.Stdin = c.App.Reader cmd.Stdin = c.App.Reader

View file

@ -41,6 +41,10 @@ type Config struct {
ManagerInterval time.Duration ManagerInterval time.Duration
AtSenderInterval time.Duration AtSenderInterval time.Duration
FirebaseKeepaliveInterval time.Duration FirebaseKeepaliveInterval time.Duration
SMTPAddr string
SMTPUser string
SMTPPass string
SMTPFrom string
MessageLimit int MessageLimit int
MinDelay time.Duration MinDelay time.Duration
MaxDelay time.Duration MaxDelay time.Duration

View file

@ -15,6 +15,7 @@ import (
"log" "log"
"net" "net"
"net/http" "net/http"
"net/smtp"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -188,6 +189,23 @@ func createFirebaseSubscriber(conf *Config) (subscriber, error) {
}, nil }, nil
} }
func (s *Server) sendMail(to string, m *message) error {
host, _, err := net.SplitHostPort(s.config.SMTPAddr)
if err != nil {
return err
}
subject := m.Title
if subject == "" {
subject = m.Message
}
msg := []byte(fmt.Sprintf("From: %s\r\n"+
"To: %s\r\n"+
"Subject: %s\r\n\r\n"+
"%s\r\n", s.config.SMTPFrom, to, subject, m.Message))
auth := smtp.PlainAuth("", s.config.SMTPUser, s.config.SMTPPass, host)
return smtp.SendMail(s.config.SMTPAddr, auth, s.config.SMTPFrom, []string{to}, msg)
}
// Run executes the main server. It listens on HTTP (+ HTTPS, if configured), and starts // Run executes the main server. It listens on HTTP (+ HTTPS, if configured), and starts
// a manager go routine to print stats and prune messages. // a manager go routine to print stats and prune messages.
func (s *Server) Run() error { func (s *Server) Run() error {
@ -307,7 +325,7 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
return err return err
} }
m := newDefaultMessage(t.ID, strings.TrimSpace(string(b))) m := newDefaultMessage(t.ID, strings.TrimSpace(string(b)))
cache, firebase, err := s.parseParams(r, m) cache, firebase, email, err := s.parseParams(r, m)
if err != nil { if err != nil {
return err return err
} }
@ -327,6 +345,13 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
} }
}() }()
} }
if s.config.SMTPAddr != "" && email != "" && !delayed {
go func() {
if err := s.sendMail(email, m); err != nil {
log.Printf("Unable to send email: %v", err.Error())
}
}()
}
if cache { if cache {
if err := s.cache.AddMessage(m); err != nil { if err := s.cache.AddMessage(m); err != nil {
return err return err
@ -341,9 +366,10 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
return nil return nil
} }
func (s *Server) parseParams(r *http.Request, m *message) (cache bool, firebase bool, err error) { func (s *Server) parseParams(r *http.Request, m *message) (cache bool, firebase bool, email string, err error) {
cache = readParam(r, "x-cache", "cache") != "no" cache = readParam(r, "x-cache", "cache") != "no"
firebase = readParam(r, "x-firebase", "firebase") != "no" firebase = readParam(r, "x-firebase", "firebase") != "no"
email = readParam(r, "x-email", "email", "mail", "e")
m.Title = readParam(r, "x-title", "title", "t") m.Title = readParam(r, "x-title", "title", "t")
messageStr := readParam(r, "x-message", "message", "m") messageStr := readParam(r, "x-message", "message", "m")
if messageStr != "" { if messageStr != "" {
@ -351,7 +377,7 @@ func (s *Server) parseParams(r *http.Request, m *message) (cache bool, firebase
} }
m.Priority, err = util.ParsePriority(readParam(r, "x-priority", "priority", "prio", "p")) m.Priority, err = util.ParsePriority(readParam(r, "x-priority", "priority", "prio", "p"))
if err != nil { if err != nil {
return false, false, errHTTPBadRequest return false, false, "", errHTTPBadRequest
} }
tagsStr := readParam(r, "x-tags", "tags", "tag", "ta") tagsStr := readParam(r, "x-tags", "tags", "tag", "ta")
if tagsStr != "" { if tagsStr != "" {
@ -363,19 +389,19 @@ func (s *Server) parseParams(r *http.Request, m *message) (cache bool, firebase
delayStr := readParam(r, "x-delay", "delay", "x-at", "at", "x-in", "in") delayStr := readParam(r, "x-delay", "delay", "x-at", "at", "x-in", "in")
if delayStr != "" { if delayStr != "" {
if !cache { if !cache {
return false, false, errHTTPBadRequest return false, false, "", errHTTPBadRequest
} }
delay, err := util.ParseFutureTime(delayStr, time.Now()) delay, err := util.ParseFutureTime(delayStr, time.Now())
if err != nil { if err != nil {
return false, false, errHTTPBadRequest return false, false, "", errHTTPBadRequest
} else if delay.Unix() < time.Now().Add(s.config.MinDelay).Unix() { } else if delay.Unix() < time.Now().Add(s.config.MinDelay).Unix() {
return false, false, errHTTPBadRequest return false, false, "", errHTTPBadRequest
} else if delay.Unix() > time.Now().Add(s.config.MaxDelay).Unix() { } else if delay.Unix() > time.Now().Add(s.config.MaxDelay).Unix() {
return false, false, errHTTPBadRequest return false, false, "", errHTTPBadRequest
} }
m.Time = delay.Unix() m.Time = delay.Unix()
} }
return cache, firebase, nil return cache, firebase, email, nil
} }
func readParam(r *http.Request, names ...string) string { func readParam(r *http.Request, names ...string) string {
@ -714,6 +740,7 @@ func (s *Server) sendDelayedMessages() error {
log.Printf("unable to publish to Firebase: %v", err.Error()) log.Printf("unable to publish to Firebase: %v", err.Error())
} }
} }
// FIXME delayed email
} }
if err := s.cache.MarkPublished(m); err != nil { if err := s.cache.MarkPublished(m); err != nil {
return err return err

View file

@ -138,3 +138,8 @@ func ParsePriority(priority string) (int, error) {
func ExpandHome(path string) string { func ExpandHome(path string) string {
return os.ExpandEnv(strings.ReplaceAll(path, "~", "$HOME")) return os.ExpandEnv(strings.ReplaceAll(path, "~", "$HOME"))
} }
// ShortTopicURL shortens the topic URL to be human-friendly, removing the http:// or https://
func ShortTopicURL(s string) string {
return strings.TrimPrefix(strings.TrimPrefix(s, "https://"), "http://")
}