diff --git a/docs/config.md b/docs/config.md
index f7cfe6b74eaaca2ffe58db66ef5a24751960a375..3544784bd15488e08ebe62f817770e4c1d21c89d 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -35,19 +35,34 @@ the message to the subscribers.
 Subscribers can retrieve cached messaging using the [`poll=1` parameter](subscribe/api.md#poll-for-messages), as well as the
 [`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, 
+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`).
+
+As of today, only SMTP servers with PLAIN auth and STARTLS are supported. To enable e-mail sending, you must set the 
+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
+
+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.
+
 ## 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
     [rate limited](#rate-limiting) as if they are one.
 
-It may be desirable to run ntfy behind a proxy, e.g. so you can provide TLS certificates using Let's Encrypt using certbot,
-or simply because you'd like to share the ports (80/443) with other services. Whatever your reasons may be, there are a 
-few things to consider. 
+It may be desirable to run ntfy behind a proxy (e.g. nginx, HAproxy or Apache), so you can provide TLS certificates 
+using Let's Encrypt using certbot, or simply because you'd like to share the ports (80/443) with other services. 
+Whatever your reasons may be, there are a few things to consider. 
 
-### Rate limiting
-If you are running ntfy behind a proxy (e.g. nginx, HAproxy or Apache), you should set the `behind-proxy` 
-flag. This will instruct the [rate limiting](#rate-limiting) logic to use the `X-Forwarded-For` header as the primary 
-identifier for a visitor, as opposed to the remote IP address. If the `behind-proxy` flag is not set, all visitors will
+If you are running ntfy behind a proxy, you should set the `behind-proxy` flag. This will instruct the 
+[rate limiting](#rate-limiting) logic to use the `X-Forwarded-For` header as the primary identifier for a visitor, 
+as opposed to the remote IP address. If the `behind-proxy` flag is not set, all visitors will
 be counted as one, because from the perspective of the ntfy server, they all share the proxy's IP address.
 
 === "/etc/ntfy/server.yml"
@@ -214,7 +229,7 @@ firebase-key-file: "/etc/ntfy/ntfy-sh-firebase-adminsdk-ahnce-9f4d6f14b5.json"
 ## Rate limiting
 !!! info
     Be aware that if you are running ntfy behind a proxy, you must set the `behind-proxy` flag. 
-    Otherwise all visitors are rate limited as if they are one.
+    Otherwise, all visitors are rate limited as if they are one.
 
 By default, ntfy runs without authentication, so it is vitally important that we protect the server from abuse or overload.
 There are various limits and rate limits in place that you can use to configure the server. Let's do the easy ones first:
@@ -235,9 +250,14 @@ request every 10s (defined by `visitor-request-limit-replenish`)
 * `visitor-request-limit-burst` is the initial bucket of requests each visitor has. This defaults to 60.
 * `visitor-request-limit-replenish` is the rate at which the bucket is refilled (one request per x). Defaults to 10s.
 
-During normal usage, you shouldn't encounter this limit at all, and even if you burst a few requests shortly (e.g. when you 
-reconnect after a connection drop), it shouldn't have any effect.
+Similarly to the request limit, there is also an e-mail limit (only relevant if [e-mail notifications](#e-mail-notifications) 
+are enabled):
+
+* `visitor-email-limit-burst` is the initial bucket of emails each visitor has. This defaults to 16.
+* `visitor-email-limit-replenish` is the rate at which the bucket is refilled (one email per x). Defaults to 1h.
 
+During normal usage, you shouldn't encounter these limits at all, and even if you burst a few requests or emails
+(e.g. when you reconnect after a connection drop), it shouldn't have any effect.
 
 ## Tuning for scale
 If you're running ntfy for your home server, you probably don't need to worry about scale at all. In its default config,
diff --git a/server/mailer_test.go b/server/mailer_test.go
index 91d6790c5057f63958144365baeed7cc8bbd2a72..70575dd39828cda5cd61e99ffa9eb4fb81b8e536 100644
--- a/server/mailer_test.go
+++ b/server/mailer_test.go
@@ -133,7 +133,7 @@ A message that contains monkeys 🙉
 No really, though. Monkeys!
 
 Tags: tag123, other
-Priority: urgent
+Priority: max
 
 --
 This message was sent by 1.2.3.4 at Fri, 24 Dec 2021 21:43:24 UTC via https://ntfy.sh/alerts`
diff --git a/test/server.go b/test/server.go
index a0f65a1105860c50d57878e01e161f86520511f7..07382c50143c14faaa22d5ce49ae87e58c5af6e2 100644
--- a/test/server.go
+++ b/test/server.go
@@ -10,7 +10,7 @@ import (
 )
 
 func init() {
-	rand.Seed(time.Now().Unix())
+	rand.Seed(time.Now().UnixMilli())
 }
 
 // StartServer starts a server.Server with a random port and waits for the server to be up
diff --git a/util/util_test.go b/util/util_test.go
index c70e45c9fac1a05c78eb23b5cf22f8c30c1f8b1a..1a74dcdb1a1f9512c52bb9811b348db6d3477170 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -102,7 +102,7 @@ func TestParsePriority_Invalid(t *testing.T) {
 }
 
 func TestPriorityString(t *testing.T) {
-	priorities := []int{0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 5}
+	priorities := []int{0, 1, 2, 3, 4, 5}
 	expected := []string{"default", "min", "low", "default", "high", "max"}
 	for i, priority := range priorities {
 		actual, err := PriorityString(priority)