Philipp Heckel 4 лет назад
Родитель
Сommit
dac88391c1

+ 2 - 0
README.md

@@ -48,6 +48,8 @@ Third party libraries and resources:
 * [Mixkit sound](https://mixkit.co/free-sound-effects/notification/) (Mixkit Free License) used as notification sound
 * [Mixkit sound](https://mixkit.co/free-sound-effects/notification/) (Mixkit Free License) used as notification sound
 * [Lato Font](https://www.latofonts.com/) (OFL) is used as a font in the Web UI
 * [Lato Font](https://www.latofonts.com/) (OFL) is used as a font in the Web UI
 * [GoReleaser](https://goreleaser.com/) (MIT) is used to create releases
 * [GoReleaser](https://goreleaser.com/) (MIT) is used to create releases
+* [go-smtp](https://github.com/emersion/go-smtp) (MIT) is used to receive e-mails
+* [stretchr/testify](https://github.com/stretchr/testify) (MIT) is used for unit and integration tests
 * [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) (MIT) is used to provide the persistent message cache
 * [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) (MIT) is used to provide the persistent message cache
 * [Firebase Admin SDK](https://github.com/firebase/firebase-admin-go) (Apache 2.0) is used to send FCM messages
 * [Firebase Admin SDK](https://github.com/firebase/firebase-admin-go) (Apache 2.0) is used to send FCM messages
 * [github/gemoji](https://github.com/github/gemoji) (MIT) is used for emoji support (specifically the [emoji.json](https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json) file)
 * [github/gemoji](https://github.com/github/gemoji) (MIT) is used for emoji support (specifically the [emoji.json](https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json) file)

+ 7 - 5
cmd/serve.go

@@ -22,10 +22,10 @@ var flagsServe = []cli.Flag{
 	altsrc.NewDurationFlag(&cli.DurationFlag{Name: "cache-duration", Aliases: []string{"b"}, EnvVars: []string{"NTFY_CACHE_DURATION"}, Value: server.DefaultCacheDuration, Usage: "buffer messages for this time to allow `since` requests"}),
 	altsrc.NewDurationFlag(&cli.DurationFlag{Name: "cache-duration", Aliases: []string{"b"}, EnvVars: []string{"NTFY_CACHE_DURATION"}, Value: server.DefaultCacheDuration, Usage: "buffer messages for this time to allow `since` requests"}),
 	altsrc.NewDurationFlag(&cli.DurationFlag{Name: "keepalive-interval", Aliases: []string{"k"}, EnvVars: []string{"NTFY_KEEPALIVE_INTERVAL"}, Value: server.DefaultKeepaliveInterval, Usage: "interval of keepalive messages"}),
 	altsrc.NewDurationFlag(&cli.DurationFlag{Name: "keepalive-interval", Aliases: []string{"k"}, EnvVars: []string{"NTFY_KEEPALIVE_INTERVAL"}, Value: server.DefaultKeepaliveInterval, Usage: "interval of keepalive messages"}),
 	altsrc.NewDurationFlag(&cli.DurationFlag{Name: "manager-interval", Aliases: []string{"m"}, EnvVars: []string{"NTFY_MANAGER_INTERVAL"}, Value: server.DefaultManagerInterval, Usage: "interval of for message pruning and stats printing"}),
 	altsrc.NewDurationFlag(&cli.DurationFlag{Name: "manager-interval", Aliases: []string{"m"}, EnvVars: []string{"NTFY_MANAGER_INTERVAL"}, Value: server.DefaultManagerInterval, Usage: "interval of for message pruning and stats printing"}),
-	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-addr", Aliases: []string{"smtp-addr"}, EnvVars: []string{"NTFY_SMTP_SENDER_ADDR"}, Usage: "SMTP server address (host:port) for outgoing emails"}),
-	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-user", Aliases: []string{"smtp-user"}, EnvVars: []string{"NTFY_SMTP_SENDER_USER"}, Usage: "SMTP user (if e-mail sending is enabled)"}),
-	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-pass", Aliases: []string{"smtp-pass"}, EnvVars: []string{"NTFY_SMTP_SENDER_PASS"}, Usage: "SMTP password (if e-mail sending is enabled)"}),
-	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-from", Aliases: []string{"smtp-from"}, EnvVars: []string{"NTFY_SMTP_SENDER_FROM"}, Usage: "SMTP sender address (if e-mail sending is enabled)"}),
+	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-addr", EnvVars: []string{"NTFY_SMTP_SENDER_ADDR"}, Usage: "SMTP server address (host:port) for outgoing emails"}),
+	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-user", EnvVars: []string{"NTFY_SMTP_SENDER_USER"}, Usage: "SMTP user (if e-mail sending is enabled)"}),
+	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-pass", EnvVars: []string{"NTFY_SMTP_SENDER_PASS"}, Usage: "SMTP password (if e-mail sending is enabled)"}),
+	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-from", EnvVars: []string{"NTFY_SMTP_SENDER_FROM"}, Usage: "SMTP sender address (if e-mail sending is enabled)"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-server-listen", EnvVars: []string{"NTFY_SMTP_SERVER_LISTEN"}, Usage: "SMTP server address (ip:port) for incoming emails, e.g. :25"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-server-listen", EnvVars: []string{"NTFY_SMTP_SERVER_LISTEN"}, Usage: "SMTP server address (ip:port) for incoming emails, e.g. :25"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-server-domain", EnvVars: []string{"NTFY_SMTP_SERVER_DOMAIN"}, Usage: "SMTP domain for incoming e-mail, e.g. ntfy.sh"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-server-domain", EnvVars: []string{"NTFY_SMTP_SERVER_DOMAIN"}, Usage: "SMTP domain for incoming e-mail, e.g. ntfy.sh"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-server-addr-prefix", EnvVars: []string{"NTFY_SMTP_SERVER_ADDR_PREFIX"}, Usage: "SMTP email address prefix for topics to prevent spam (e.g. 'ntfy-')"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-server-addr-prefix", EnvVars: []string{"NTFY_SMTP_SERVER_ADDR_PREFIX"}, Usage: "SMTP email address prefix for topics to prevent spam (e.g. 'ntfy-')"}),
@@ -102,7 +102,9 @@ func execServe(c *cli.Context) error {
 	} else if listenHTTPS != "" && (keyFile == "" || certFile == "") {
 	} else if listenHTTPS != "" && (keyFile == "" || certFile == "") {
 		return errors.New("if listen-https is set, both key-file and cert-file must be set")
 		return errors.New("if listen-https is set, both key-file and cert-file must be set")
 	} else if smtpSenderAddr != "" && (baseURL == "" || smtpSenderUser == "" || smtpSenderPass == "" || smtpSenderFrom == "") {
 	} else if smtpSenderAddr != "" && (baseURL == "" || smtpSenderUser == "" || smtpSenderPass == "" || smtpSenderFrom == "") {
-		return errors.New("if smtp-addr is set, base-url, smtp-user, smtp-pass and smtp-from must also be set")
+		return errors.New("if smtp-sender-addr is set, base-url, smtp-sender-user, smtp-sender-pass and smtp-sender-from must also be set")
+	} else if smtpServerListen != "" && smtpServerDomain == "" {
+		return errors.New("if smtp-server-listen is set, smtp-server-domain must also be set")
 	}
 	}
 
 
 	// Run server
 	// Run server

+ 49 - 5
docs/config.md

@@ -36,7 +36,7 @@ Subscribers can retrieve cached messaging using the [`poll=1` parameter](subscri
 [`since=` parameter](subscribe/api.md#fetch-cached-messages).
 [`since=` parameter](subscribe/api.md#fetch-cached-messages).
 
 
 ## E-mail notifications
 ## E-mail notifications
-To allow forwarding messages via e-mail, you can configure an SMTP server for outgoing messages. Once configured, 
+To allow forwarding messages via e-mail, you can configure an **SMTP server for outgoing messages**. Once configured, 
 you can set the `X-Email` header to [send messages via e-mail](publish.md#e-mail-notifications) (e.g. 
 you can set the `X-Email` header to [send messages via e-mail](publish.md#e-mail-notifications) (e.g. 
 `curl -d "hi there" -H "X-Email: phil@example.com" ntfy.sh/mytopic`).
 `curl -d "hi there" -H "X-Email: phil@example.com" ntfy.sh/mytopic`).
 
 
@@ -44,13 +44,57 @@ As of today, only SMTP servers with PLAIN auth and STARTLS are supported. To ena
 following settings:
 following settings:
 
 
 * `base-url` is the root URL for the ntfy server; this is needed for e-mail footer
 * `base-url` is the root URL for the ntfy server; this is needed for e-mail footer
-* `smtp-addr` is the hostname:port of the SMTP server
-* `smtp-user` and `smtp-pass` are the username and password of the SMTP user
-* `smtp-from` is the e-mail address of the sender
+* `smtp-sender-addr` is the hostname:port of the SMTP server
+* `smtp-sender-user` and `smtp-sender-pass` are the username and password of the SMTP user
+* `smtp-sender-from` is the e-mail address of the sender
+
+Here's an example config using [Amazon SES](https://aws.amazon.com/ses/) for outgoing mail (this is how it is 
+configured for `ntfy.sh`):
+
+=== "/etc/ntfy/server.yml"
+    ``` yaml
+    base-url: "https://ntfy.sh"
+    smtp-sender-addr: "email-smtp.us-east-2.amazonaws.com:587"
+    smtp-sender-user: "AKIDEADBEEFAFFE12345"
+    smtp-sender-pass: "Abd13Kf+sfAk2DzifjafldkThisIsNotARealKeyOMG."
+    smtp-sender-from: "ntfy@ntfy.sh"
+    ```
 
 
 Please also refer to the [rate limiting](#rate-limiting) settings below, specifically `visitor-email-limit-burst` 
 Please also refer to the [rate limiting](#rate-limiting) settings below, specifically `visitor-email-limit-burst` 
 and `visitor-email-limit-burst`. Setting these conservatively is necessary to avoid abuse.
 and `visitor-email-limit-burst`. Setting these conservatively is necessary to avoid abuse.
 
 
+## E-mail publishing
+To allow publishing messages via e-mail, ntfy can run a lightweight **SMTP server for incoming messages**. Once configured, 
+users can [send emails to a topic e-mail address](publish.md#e-mail-publishing) (e.g. `mytopic@ntfy.sh` or 
+`myprefix-mytopic@ntfy.sh`) to publish messages to a topic. This is useful for e-mail based integrations such as for 
+statuspage.io (though these days most services also support webhooks and HTTP calls).
+
+To configure the SMTP server, you must at least set `smtp-server-listen` and `smtp-server-domain`:
+
+* `smtp-server-listen` defines the IP address and port the SMTP server will listen on, e.g. `:25` or `1.2.3.4:25`
+* `smtp-server-domain` is the e-mail domain, e.g. `ntfy.sh`
+* `smtp-server-addr-prefix` is an optional prefix for the e-mail addresses to prevent spam. If set to `ntfy-`, for instance,
+  only e-mails to `ntfy-$topic@ntfy.sh` will be accepted. If this is not set, all emails to `$topic@ntfy.sh` will be
+  accepted (which may obviously be a spam problem).
+
+Here's an example config (this is how it is configured for `ntfy.sh`):
+
+=== "/etc/ntfy/server.yml"
+    ``` yaml
+    smtp-server-listen: ":25"
+    smtp-server-domain: "ntfy.sh"
+    smtp-server-addr-prefix: "ntfy-"
+    ```
+
+In addition to configuring the ntfy server, you have to create two DNS records (an [MX record](https://en.wikipedia.org/wiki/MX_record) 
+and a corresponding A record), so incoming mail will find its way to your server. Here's an example of how `ntfy.sh` is 
+configured (in [Amazon Route 53](https://aws.amazon.com/route53/)):
+
+<figure markdown>
+  ![DNS records for incoming mail](static/img/screenshot-email-publishing-dns.png){ width=600 }
+  <figcaption>DNS records for incoming mail</figcaption>
+</figure>
+
 ## Behind a proxy (TLS, etc.)
 ## Behind a proxy (TLS, etc.)
 !!! warning
 !!! warning
     If you are running ntfy behind a proxy, you must set the `behind-proxy` flag. Otherwise, all visitors are
     If you are running ntfy behind a proxy, you must set the `behind-proxy` flag. Otherwise, all visitors are
@@ -66,7 +110,7 @@ as opposed to the remote IP address. If the `behind-proxy` flag is not set, all
 be counted as one, because from the perspective of the ntfy server, they all share the proxy's IP address.
 be counted as one, because from the perspective of the ntfy server, they all share the proxy's IP address.
 
 
 === "/etc/ntfy/server.yml"
 === "/etc/ntfy/server.yml"
-    ```
+    ``` yaml
     # Tell ntfy to use "X-Forwarded-For" to identify visitors
     # Tell ntfy to use "X-Forwarded-For" to identify visitors
     behind-proxy: true
     behind-proxy: true
     ```
     ```

+ 23 - 1
docs/publish.md

@@ -691,6 +691,28 @@ Here's what that looks like in Google Mail:
   <figcaption>E-mail notification</figcaption>
   <figcaption>E-mail notification</figcaption>
 </figure>
 </figure>
 
 
+## E-mail publishing
+You can publish messages to a topic via e-mail, i.e. by sending an email to a specific address. For instance, you can
+publish a message to the topic `sometopic` by sending an e-mail to `ntfy-sometopic@ntfy.sh`. This is useful for e-mail 
+based integrations such as for statuspage.io (though these days most services also support webhooks and HTTP calls).
+
+Depending on the [server configuration](config.md#e-mail-publishing), the e-mail address format can have a prefix to 
+prevent spam on topics. For ntfy.sh, the prefix is configured to `ntfy-`, meaning that the general e-mail address 
+format is:
+
+```
+ntfy-$topic@ntfy.sh
+```
+
+As of today, e-mail publishing only supports adding a [message title](#message-title) (the e-mail subject). Tags, priority,
+delay and other features are not supported (yet). Here's an example that will publish a message with the 
+title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://ntfy.sh/sometopic)):
+
+<figure markdown>
+  ![e-mail publishing](static/img/screenshot-email-publishing-gmail.png){ width=500 }
+  <figcaption>Publishing a message via e-mail</figcaption>
+</figure>
+
 ## Advanced features
 ## Advanced features
 
 
 ### Message caching
 ### Message caching
@@ -846,7 +868,7 @@ but just in case, let's list them all:
 |---|---|
 |---|---|
 | **Message length** | Each message can be up to 512 bytes long. Longer messages are truncated. |
 | **Message length** | Each message can be up to 512 bytes long. Longer messages are truncated. |
 | **Requests** | By default, the server is configured to allow 60 requests at once, and then refills the your allowed requests bucket at a rate of one request per 10 seconds. You can read more about this in the [rate limiting](config.md#rate-limiting) section. |
 | **Requests** | By default, the server is configured to allow 60 requests at once, and then refills the your allowed requests bucket at a rate of one request per 10 seconds. You can read more about this in the [rate limiting](config.md#rate-limiting) section. |
-| **E-mails** | By default, the server is configured to allow 16 e-mails at once, and then refills the your allowed e-mail bucket at a rate of one per hour. You can read more about this in the [rate limiting](config.md#rate-limiting) section. |
+| **E-mails** | By default, the server is configured to allow sending 16 e-mails at once, and then refills the your allowed e-mail bucket at a rate of one per hour. You can read more about this in the [rate limiting](config.md#rate-limiting) section. |
 | **Subscription limits** | By default, the server allows each visitor to keep 30 connections to the server open. |
 | **Subscription limits** | By default, the server allows each visitor to keep 30 connections to the server open. |
 | **Total number of topics** | By default, the server is configured to allow 5,000 topics. The ntfy.sh server has higher limits though. |
 | **Total number of topics** | By default, the server is configured to allow 5,000 topics. The ntfy.sh server has higher limits though. |
 
 

BIN
docs/static/img/screenshot-email-publishing-dns.png


BIN
docs/static/img/screenshot-email-publishing-gmail.png


+ 9 - 1
server/server.yml

@@ -60,7 +60,15 @@
 # smtp-sender-pass:
 # smtp-sender-pass:
 # smtp-sender-from:
 # smtp-sender-from:
 
 
-# XXXXXXXXXXXXXXXXXXXXxx
+# If enabled, ntfy will launch a lightweight SMTP server for incoming messages. Once configured, users can send
+# emails to a topic e-mail address to publish messages to a topic.
+#
+# - smtp-server-listen defines the IP address and port the SMTP server will listen on, e.g. :25 or 1.2.3.4:25
+# - smtp-server-domain is the e-mail domain, e.g. ntfy.sh
+# - smtp-server-addr-prefix is an optional prefix for the e-mail addresses to prevent spam. If set to "ntfy-",
+#   for instance, only e-mails to ntfy-$topic@ntfy.sh will be accepted. If this is not set, all emails to
+#   $topic@ntfy.sh will be accepted (which may obviously be a spam problem).
+#
 # smtp-server-listen:
 # smtp-server-listen:
 # smtp-server-domain:
 # smtp-server-domain:
 # smtp-server-addr-prefix:
 # smtp-server-addr-prefix: