This commit is contained in:
Philipp Heckel 2021-12-25 00:57:02 +01:00
parent 11b5ac49c0
commit 3bc8ff0104
8 changed files with 146 additions and 49 deletions

View File

@ -37,6 +37,8 @@ func TestClient_Publish_Subscribe(t *testing.T) {
require.Equal(t, "some delayed message", msg.Message)
require.True(t, time.Now().Add(24*time.Hour).Unix() < msg.Time)
time.Sleep(200 * time.Millisecond)
msg = nextMessage(c)
require.NotNil(t, msg)
require.Equal(t, "some message", msg.Message)

View File

@ -22,7 +22,7 @@ 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-addr", EnvVars: []string{"NTFY_SMTP_ADDR"}, Usage: "SMTP address (host:port) to allow email sending"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-addr", EnvVars: []string{"NTFY_SMTP_ADDR"}, Usage: "SMTP server address (host:port) to allow email sending"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-user", EnvVars: []string{"NTFY_SMTP_USER"}, Usage: "SMTP user (if e-mail sending is enabled)"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-pass", EnvVars: []string{"NTFY_SMTP_PASS"}, Usage: "SMTP password (if e-mail sending is enabled)"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-from", EnvVars: []string{"NTFY_SMTP_FROM"}, Usage: "SMTP sender address (if e-mail sending is enabled)"}),

View File

@ -300,6 +300,7 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
| Config option | Env variable | Format | Default | Description |
|---|---|---|---|---|
| `base-url` | `NTFY_BASE_URL` | *URL* | - | Public facing base URL of the service (e.g. `https://ntfy.sh`) |
| `listen-http` | `NTFY_LISTEN_HTTP` | `[host]:port` | `:80` | Listen address for the HTTP web server |
| `listen-https` | `NTFY_LISTEN_HTTPS` | `[host]:port` | - | Listen address for the HTTPS web server. If set, you also need to set `key-file` and `cert-file`. |
| `key-file` | `NTFY_KEY_FILE` | *filename* | - | HTTPS/TLS private key file, only used if `listen-https` is set. |
@ -307,42 +308,64 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
| `firebase-key-file` | `NTFY_FIREBASE_KEY_FILE` | *filename* | - | If set, also publish messages to a Firebase Cloud Messaging (FCM) topic for your app. This is optional and only required to save battery when using the Android app. See [Firebase (FCM](#firebase-fcm). |
| `cache-file` | `NTFY_CACHE_FILE` | *filename* | - | If set, messages are cached in a local SQLite database instead of only in-memory. This allows for service restarts without losing messages in support of the since= parameter. See [message cache](#message-cache). |
| `cache-duration` | `NTFY_CACHE_DURATION` | *duration* | 12h | Duration for which messages will be buffered before they are deleted. This is required to support the `since=...` and `poll=1` parameter. Set this to `0` to disable the cache entirely. |
| `behind-proxy` | `NTFY_BEHIND_PROXY` | *bool* | false | If set, the X-Forwarded-For header is used to determine the visitor IP address instead of the remote address of the connection. |
| `smtp-addr` | `NTFY_SMTP_ADDR` | `host:port` | - | SMTP server address to allow email sending |
| `smtp-user` | `NTFY_SMTP_USER` | *string* | - | SMTP user; only used if e-mail sending is enabled |
| `smtp-pass` | `NTFY_SMTP_PASS` | *string* | - | SMTP password; only used if e-mail sending is enabled |
| `smtp-from` | `NTFY_SMTP_FROM` | *e-mail address* | - | SMTP sender e-mail address; only used if e-mail sending is enabled |
| `keepalive-interval` | `NTFY_KEEPALIVE_INTERVAL` | *duration* | 30s | Interval in which keepalive messages are sent to the client. This is to prevent intermediaries closing the connection for inactivity. Note that the Android app has a hardcoded timeout at 77s, so it should be less than that. |
| `manager-interval` | `$NTFY_MANAGER_INTERVAL` | *duration* | 1m | Interval in which the manager prunes old messages, deletes topics and prints the stats. |
| `global-topic-limit` | `NTFY_GLOBAL_TOPIC_LIMIT` | *number* | 5000 | Rate limiting: Total number of topics before the server rejects new topics. |
| `visitor-subscription-limit` | `NTFY_VISITOR_SUBSCRIPTION_LIMIT` | *number* | 30 | Rate limiting: Number of subscriptions per visitor (IP address) |
| `visitor-request-limit-burst` | `NTFY_VISITOR_REQUEST_LIMIT_BURST` | *number* | 60 | Allowed GET/PUT/POST requests per second, per visitor. This setting is the initial bucket of requests each visitor has |
| `visitor-request-limit-replenish` | `NTFY_VISITOR_REQUEST_LIMIT_REPLENISH` | *duration* | 10s | Strongly related to `visitor-request-limit-burst`: The rate at which the bucket is refilled |
| `behind-proxy` | `NTFY_BEHIND_PROXY` | *bool* | false | If set, the X-Forwarded-For header is used to determine the visitor IP address instead of the remote address of the connection. |
| `visitor-email-limit-burst` | `NTFY_VISITOR_EMAIL_LIMIT_BURST` | *number* | 16 |Initial limit of e-mails per visitor |
| `visitor-email-limit-replenish` | `NTFY_VISITOR_EMAIL_LIMIT_REPLENISH` | *duration* | 1h | Strongly related to `visitor-email-limit-burst`: The rate at which the bucket is refilled |
The format for a *duration* is: `<number>(smh)`, e.g. 30s, 20m or 1h.
## Command line options
```
$ ntfy --help
$ ntfy serve --help
NAME:
ntfy - Simple pub-sub notification service
main serve - Run the ntfy server
USAGE:
ntfy [OPTION..]
ntfy serve [OPTIONS..]
GLOBAL OPTIONS:
--config value, -c value config file (default: /etc/ntfy/server.yml) [$NTFY_CONFIG_FILE]
--listen-http value, -l value ip:port used to as listen address (default: ":80") [$NTFY_LISTEN_HTTP]
--firebase-key-file value, -F value Firebase credentials file; if set additionally publish to FCM topic [$NTFY_FIREBASE_KEY_FILE]
--cache-file value, -C value cache file used for message caching [$NTFY_CACHE_FILE]
--cache-duration since, -b since buffer messages for this time to allow since requests (default: 12h0m0s) [$NTFY_CACHE_DURATION]
--keepalive-interval value, -k value interval of keepalive messages (default: 30s) [$NTFY_KEEPALIVE_INTERVAL]
--manager-interval value, -m value interval of for message pruning and stats printing (default: 1m0s) [$NTFY_MANAGER_INTERVAL]
--global-topic-limit value, -T value total number of topics allowed (default: 5000) [$NTFY_GLOBAL_TOPIC_LIMIT]
--visitor-subscription-limit value, -V value number of subscriptions per visitor (default: 30) [$NTFY_VISITOR_SUBSCRIPTION_LIMIT]
--visitor-request-limit-burst value, -B value initial limit of requests per visitor (default: 60) [$NTFY_VISITOR_REQUEST_LIMIT_BURST]
--visitor-request-limit-replenish value, -R value interval at which burst limit is replenished (one per x) (default: 10s) [$NTFY_VISITOR_REQUEST_LIMIT_REPLENISH]
--behind-proxy, -P if set, use X-Forwarded-For header to determine visitor IP address (for rate limiting) (default: false) [$NTFY_BEHIND_PROXY]
DESCRIPTION:
Run the ntfy server and listen for incoming requests
The command will load the configuration from /etc/ntfy/server.yml. Config options can
be overridden using the command line options.
Examples:
ntfy serve # Starts server in the foreground (on port 80)
ntfy serve --listen-http :8080 # Starts server with alternate port
Try 'ntfy COMMAND --help' for more information.
ntfy v1.4.8 (7b8185c), runtime go1.17, built at 1637872539
Copyright (C) 2021 Philipp C. Heckel, distributed under the Apache License 2.0
OPTIONS:
--config value, -c value config file (default: /etc/ntfy/server.yml) [$NTFY_CONFIG_FILE]
--base-url value, -B value externally visible base URL for this host (e.g. https://ntfy.sh) [$NTFY_BASE_URL]
--listen-http value, -l value ip:port used to as HTTP listen address (default: ":80") [$NTFY_LISTEN_HTTP]
--listen-https value, -L value ip:port used to as HTTPS listen address [$NTFY_LISTEN_HTTPS]
--key-file value, -K value private key file, if listen-https is set [$NTFY_KEY_FILE]
--cert-file value, -E value certificate file, if listen-https is set [$NTFY_CERT_FILE]
--firebase-key-file value, -F value Firebase credentials file; if set additionally publish to FCM topic [$NTFY_FIREBASE_KEY_FILE]
--cache-file value, -C value cache file used for message caching [$NTFY_CACHE_FILE]
--cache-duration since, -b since buffer messages for this time to allow since requests (default: 12h0m0s) [$NTFY_CACHE_DURATION]
--keepalive-interval value, -k value interval of keepalive messages (default: 30s) [$NTFY_KEEPALIVE_INTERVAL]
--manager-interval value, -m value interval of for message pruning and stats printing (default: 1m0s) [$NTFY_MANAGER_INTERVAL]
--smtp-addr value SMTP server address (host:port) to allow email sending [$NTFY_SMTP_ADDR]
--smtp-user value SMTP user (if e-mail sending is enabled) [$NTFY_SMTP_USER]
--smtp-pass value SMTP password (if e-mail sending is enabled) [$NTFY_SMTP_PASS]
--smtp-from value SMTP sender address (if e-mail sending is enabled) [$NTFY_SMTP_FROM]
--global-topic-limit value, -T value total number of topics allowed (default: 5000) [$NTFY_GLOBAL_TOPIC_LIMIT]
--visitor-subscription-limit value number of subscriptions per visitor (default: 30) [$NTFY_VISITOR_SUBSCRIPTION_LIMIT]
--visitor-request-limit-burst value initial limit of requests per visitor (default: 60) [$NTFY_VISITOR_REQUEST_LIMIT_BURST]
--visitor-request-limit-replenish value interval at which burst limit is replenished (one per x) (default: 10s) [$NTFY_VISITOR_REQUEST_LIMIT_REPLENISH]
--visitor-email-limit-burst value initial limit of e-mails per visitor (default: 16) [$NTFY_VISITOR_EMAIL_LIMIT_BURST]
--visitor-email-limit-replenish value interval at which burst limit is replenished (one per x) (default: 1h0m0s) [$NTFY_VISITOR_EMAIL_LIMIT_REPLENISH]
--behind-proxy, -P if set, use X-Forwarded-For header to determine visitor IP address (for rate limiting) (default: false) [$NTFY_BEHIND_PROXY]
--help, -h show help (default: false)
```

View File

@ -592,16 +592,26 @@ Here's an example with a custom message, tags and a priority:
file_get_contents('https://ntfy.sh/mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull');
```
## Publish as e-mail
## E-mail notifications
You can forward messages to e-mail by specifying an address in the header. This can be useful for messages that
you'd like to persist longer, or to blast-notify yourself on all possible channels. Since ntfy does not provide auth,
the [rate limiting](#limitations) is pretty strict (see below). In the default configuration, you get 16 e-mails per
visitor (IP address) and then after that one per hour. On top of that, your IP address appears in the e-mail body. This
is to prevent abuse.
you'd like to persist longer, or to blast-notify yourself on all possible channels.
Usage is easy: Simply pass the `X-Email` header (or any of its aliases: `X-E-mail`, `Email`, `E-mail`, `Mail`, or `e`).
Only one e-mail address is supported.
Since ntfy does not provide auth (yet), the rate limiting is pretty strict (see [limitations](#limitations)). In the
default configuration, you get **16 e-mails per visitor** (IP address) and then after that one per hour. On top of
that, your IP address appears in the e-mail body. This is to prevent abuse.
=== "Command line (curl)"
```
curl -H "Email: phil@example.com" -d "You've Got Mail" ntfy.sh/alerts
curl \
-H "Email: phil@example.com" \
-H "Tags: warning,skull,backup-host,ssh-login" \
-H "Priority: high" \
-d "Unknown login from 5.31.23.83 to backups.example.com" \
ntfy.sh/alerts
curl -H "Email: phil@example.com" -d "You've Got Mail"
curl -d "You've Got Mail" "ntfy.sh/alerts?email=phil@example.com"
```
@ -609,7 +619,9 @@ is to prevent abuse.
```
ntfy publish \
--email=phil@example.com \
alerts "You've Got Mail"
--tags=warning,skull,backup-host,ssh-login \
--priority=high \
alerts "Unknown login from 5.31.23.83 to backups.example.com"
```
=== "HTTP"
@ -617,31 +629,44 @@ is to prevent abuse.
POST /alerts HTTP/1.1
Host: ntfy.sh
Email: phil@example.com
Tags: warning,skull,backup-host,ssh-login
Priority: high
You've Got Mail
Unknown login from 5.31.23.83 to backups.example.com
```
=== "JavaScript"
``` javascript
fetch('https://ntfy.sh/alerts', {
method: 'POST',
body: "You've Got Mail",
headers: { 'Email': 'phil@example.com' }
body: "Unknown login from 5.31.23.83 to backups.example.com",
headers: {
'Email': 'phil@example.com',
'Tags': 'warning,skull,backup-host,ssh-login',
'Priority': 'high'
}
})
```
=== "Go"
``` go
req, _ := http.NewRequest("POST", "https://ntfy.sh/alerts", strings.NewReader("You've Got Mail"))
req, _ := http.NewRequest("POST", "https://ntfy.sh/alerts",
strings.NewReader("Unknown login from 5.31.23.83 to backups.example.com"))
req.Header.Set("Email", "phil@example.com")
req.Header.Set("Tags", "warning,skull,backup-host,ssh-login")
req.Header.Set("Priority", "high")
http.DefaultClient.Do(req)
```
=== "Python"
``` python
requests.post("https://ntfy.sh/alerts",
data="You've Got Mail",
headers={ "Email": "phil@example.com" })
data="Unknown login from 5.31.23.83 to backups.example.com",
headers={
"Email": "phil@example.com",
"Tags": "warning,skull,backup-host,ssh-login",
"Priority": "high"
})
```
=== "PHP"
@ -651,12 +676,21 @@ is to prevent abuse.
'method' => 'POST',
'header' =>
"Content-Type: text/plain\r\n" .
"Email: phil@example.com",
'content' => 'You've Got Mail'
"Email: phil@example.com\r\n" .
"Tags: warning,skull,backup-host,ssh-login\r\n" .
"Priority: high",
'content' => 'Unknown login from 5.31.23.83 to backups.example.com'
]
]));
```
Here's what that looks like in Google Mail:
<figure markdown>
![e-mail notification](static/img/screenshot-email.png){ width=600 }
<figcaption>E-mail notification</figcaption>
</figure>
## Advanced features
### Message caching
@ -827,6 +861,6 @@ and can be passed as **HTTP headers** or **query parameters in the URL**. They a
| `X-Priority` | `Priority`, `prio`, `p` | [Message priority](#message-priority) |
| `X-Tags` | `Tags`, `Tag`, `ta` | [Tags and emojis](#tags-emojis) |
| `X-Delay` | `Delay`, `X-At`, `At`, `X-In`, `In` | Timestamp or duration for [delayed delivery](#scheduled-delivery) |
| `X-Email` | `X-E-Mail`, `Email`, `E-Mail`, `mail`, `e` | E-mail address for [e-mail delivery](#publish-as-e-mail) |
| `X-Email` | `X-E-Mail`, `Email`, `E-Mail`, `mail`, `e` | E-mail address for [e-mail notifications](#e-mail-notifications) |
| `X-Cache` | `Cache` | Allows disabling [message caching](#message-caching) |
| `X-Firebase` | `Firebase` | Allows disabling [sending to Firebase](#disable-firebase) |

BIN
docs/static/img/screenshot-email.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -1,8 +1,12 @@
# ntfy server config file
# Public facing base URL of the service (e.g. https://ntfy.sh or https://ntfy.example.com)
# This setting is currently only used by the e-mail feature.
#
# base-url:
# Listen address for the HTTP & HTTPS web server. If "listen-https" is set, you must also
# set "key-file" and "cert-file".
# Format: <hostname>:<port>
# set "key-file" and "cert-file". Format: <hostname>:<port>
#
# listen-http: ":80"
# listen-https:
@ -34,6 +38,27 @@
#
# cache-duration: 12h
# If set, the X-Forwarded-For header is used to determine the visitor IP address
# instead of the remote address of the connection.
#
# WARNING: If you are behind a proxy, you must set this, otherwise all visitors are rate limited
# as if they are one.
#
# behind-proxy: false
# If enabled, allow e-mail notifications via the 'X-Email' header. As of today, only SMTP servers
# with plain text auth and STARTLS are supported. Please also refer to the rate limiting settings
# below (visitor-email-limit-burst & visitor-email-limit-burst).
#
# - smtp-addr is the hostname:port of the SMTP server
# - smtp-user/smtp-pass are the username and password of the SMTP user
# - smtp-from is the e-mail address of the sender
#
# smtp-addr:
# smtp-user:
# smtp-pass:
# smtp-from:
# Interval in which keepalive messages are sent to the client. This is to prevent
# intermediaries closing the connection for inactivity.
#
@ -67,11 +92,3 @@
#
# visitor-email-limit-burst: 16
# visitor-email-limit-replenish: 1h
# If set, the X-Forwarded-For header is used to determine the visitor IP address
# instead of the remote address of the connection.
#
# WARNING: If you are behind a proxy, you must set this, otherwise all visitors are rate limited
# as if they are one.
#
# behind-proxy: false

View File

@ -148,7 +148,7 @@ func PriorityString(priority int) (string, error) {
case 4:
return "high", nil
case 5:
return "urgent", nil
return "max", nil
default:
return "", errInvalidPriority
}

View File

@ -100,3 +100,24 @@ func TestParsePriority_Invalid(t *testing.T) {
require.Equal(t, errInvalidPriority, err)
}
}
func TestPriorityString(t *testing.T) {
priorities := []int{0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 5}
expected := []string{"default", "min", "low", "default", "high", "max"}
for i, priority := range priorities {
actual, err := PriorityString(priority)
require.Nil(t, err)
require.Equal(t, expected[i], actual)
}
}
func TestPriorityString_Invalid(t *testing.T) {
_, err := PriorityString(99)
require.Equal(t, err, errInvalidPriority)
}
func TestShortTopicURL(t *testing.T) {
require.Equal(t, "ntfy.sh/mytopic", ShortTopicURL("https://ntfy.sh/mytopic"))
require.Equal(t, "ntfy.sh/mytopic", ShortTopicURL("http://ntfy.sh/mytopic"))
require.Equal(t, "lalala", ShortTopicURL("lalala"))
}