diff --git a/README.md b/README.md
index c99d2d4f5b19a981a2cf5e7af8e638876576e6a9..487d5dea67ceecdd6d873619d2d09f8eda2df9c5 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 3da824fd900dc0bac46bc479a037c2eb86ef1209..5545206f6f8cd6b6a0ee4316d0912f329c1d94c7 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 e1d74e2750da02d2afb6ec517a82621122fe9b0c..93d41025988012c74e804af0e0f8d2dd1e7c4aee 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/)):
+
+<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.)
 !!! 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 85cfaf8621678c0fef33307b4ff1ea837f383ab7..c75ea94141d6dd91c6f6a898b9badd65fc5a98ce 100644
--- a/docs/publish.md
+++ b/docs/publish.md
@@ -691,6 +691,28 @@ Here's what that looks like in Google Mail:
   <figcaption>E-mail notification</figcaption>
 </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
 
 ### 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 0000000000000000000000000000000000000000..d67b057a7e92f224147b20b15dbb9fdad566fa08
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 0000000000000000000000000000000000000000..0d8a58e80dc48715f43fcd500034b01c0c0c472f
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 bc1bd5737b782d4d649cef5fb1fc6b94563bcdb0..847b7d638aa95f7d1bb8ba06edf3c2e546c415b1 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: