Philipp Heckel 4 лет назад
Родитель
Сommit
873c57b3d8
6 измененных файлов с 46 добавлено и 14 удалено
  1. 0 5
      cmd/app.go
  2. 1 0
      cmd/serve.go
  3. 1 1
      cmd/subscribe.go
  4. 4 0
      server/config.go
  5. 35 8
      server/server.go
  6. 5 0
      util/util.go

+ 0 - 5
cmd/app.go

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

+ 1 - 0
cmd/serve.go

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

+ 1 - 1
cmd/subscribe.go

@@ -180,7 +180,7 @@ func runCommandInternal(c *cli.Context, command string, m *client.Message) error
 	defer os.Remove(scriptFile)
 	verbose := c.Bool("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.Stdin = c.App.Reader

+ 4 - 0
server/config.go

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

+ 35 - 8
server/server.go

@@ -15,6 +15,7 @@ import (
 	"log"
 	"net"
 	"net/http"
+	"net/smtp"
 	"regexp"
 	"strconv"
 	"strings"
@@ -188,6 +189,23 @@ func createFirebaseSubscriber(conf *Config) (subscriber, error) {
 	}, 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
 // a manager go routine to print stats and prune messages.
 func (s *Server) Run() error {
@@ -307,7 +325,7 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
 		return err
 	}
 	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 {
 		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 err := s.cache.AddMessage(m); err != nil {
 			return err
@@ -341,9 +366,10 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
 	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"
 	firebase = readParam(r, "x-firebase", "firebase") != "no"
+	email = readParam(r, "x-email", "email", "mail", "e")
 	m.Title = readParam(r, "x-title", "title", "t")
 	messageStr := readParam(r, "x-message", "message", "m")
 	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"))
 	if err != nil {
-		return false, false, errHTTPBadRequest
+		return false, false, "", errHTTPBadRequest
 	}
 	tagsStr := readParam(r, "x-tags", "tags", "tag", "ta")
 	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")
 	if delayStr != "" {
 		if !cache {
-			return false, false, errHTTPBadRequest
+			return false, false, "", errHTTPBadRequest
 		}
 		delay, err := util.ParseFutureTime(delayStr, time.Now())
 		if err != nil {
-			return false, false, errHTTPBadRequest
+			return false, false, "", errHTTPBadRequest
 		} 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() {
-			return false, false, errHTTPBadRequest
+			return false, false, "", errHTTPBadRequest
 		}
 		m.Time = delay.Unix()
 	}
-	return cache, firebase, nil
+	return cache, firebase, email, nil
 }
 
 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())
 				}
 			}
+			// FIXME delayed email
 		}
 		if err := s.cache.MarkPublished(m); err != nil {
 			return err

+ 5 - 0
util/util.go

@@ -138,3 +138,8 @@ func ParsePriority(priority string) (int, error) {
 func ExpandHome(path string) string {
 	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://")
+}