diff --git a/README.md b/README.md index c99d2d4f..487d5dea 100644 --- a/README.md +++ b/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 * [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 +* [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 * [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) diff --git a/cmd/serve.go b/cmd/serve.go index 3da824fd..5545206f 100644 --- a/cmd/serve.go +++ b/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: "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.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-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-')"}), @@ -102,7 +102,9 @@ func execServe(c *cli.Context) error { } else if listenHTTPS != "" && (keyFile == "" || certFile == "") { return errors.New("if listen-https is set, both key-file and cert-file must be set") } 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 diff --git a/docs/config.md b/docs/config.md index e1d74e27..93d41025 100644 --- a/docs/config.md +++ b/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). ## 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. `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: * `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` 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/)): + +
+ ![DNS records for incoming mail](static/img/screenshot-email-publishing-dns.png){ width=600 } +
DNS records for incoming mail
+
+ ## Behind a proxy (TLS, etc.) !!! warning 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. === "/etc/ntfy/server.yml" - ``` + ``` yaml # Tell ntfy to use "X-Forwarded-For" to identify visitors behind-proxy: true ``` diff --git a/docs/publish.md b/docs/publish.md index 85cfaf86..c75ea941 100644 --- a/docs/publish.md +++ b/docs/publish.md @@ -691,6 +691,28 @@ Here's what that looks like in Google Mail:
E-mail notification
+## 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)): + +
+ ![e-mail publishing](static/img/screenshot-email-publishing-gmail.png){ width=500 } +
Publishing a message via e-mail
+
+ ## Advanced features ### 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. | | **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. | | **Total number of topics** | By default, the server is configured to allow 5,000 topics. The ntfy.sh server has higher limits though. | diff --git a/docs/static/img/screenshot-email-publishing-dns.png b/docs/static/img/screenshot-email-publishing-dns.png new file mode 100644 index 00000000..d67b057a Binary files /dev/null and b/docs/static/img/screenshot-email-publishing-dns.png differ diff --git a/docs/static/img/screenshot-email-publishing-gmail.png b/docs/static/img/screenshot-email-publishing-gmail.png new file mode 100644 index 00000000..0d8a58e8 Binary files /dev/null and b/docs/static/img/screenshot-email-publishing-gmail.png differ diff --git a/server/server.yml b/server/server.yml index bc1bd573..847b7d63 100644 --- a/server/server.yml +++ b/server/server.yml @@ -60,7 +60,15 @@ # smtp-sender-pass: # 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-domain: # smtp-server-addr-prefix: