If your Discourse does not have incoming email set up, here's how:
if you already have basic reply via email set up (which is common on hosting plans), and you want to add the ability to start a new topic via email, see this topic.
You have two options for enabling incoming emails to your Discourse: polling via POP3 or pushing to the API
1. Polling emails via POP3
If you want to poll emails using POP3 you must first setup email polling. For that, I recommend that you follow the tutorial @codinghorror wrote about how to setup reply via email.
Since Discourse only supports polling from one POP3 account, you will have to setup forwarding rules between your accounts to make sure all the emails end up in the account you are polling emails from. Discourse is clever enough to deliver the emails to the appropriate destination.
Let's say that you are polling emails from the "
firstname.lastname@example.org" account and you want to setup incoming emails for "
email@example.com" and "
You will need to forward all the emails sent to "
firstname.lastname@example.org" and "
email@example.com" to "
firstname.lastname@example.org". If you are using GMail, they have a great tutorial on how to automatically forward incoming emails to another account.
Then, Discourse will periodically poll emails from the "
email@example.com" account and deliver the emails to the corresponding
If you don't have a SMTP server, you can set one up using our direct-delivery incoming mail Docker image.
2. Pushing emails via the Discourse API
Alternatively, you can push emails to Discourse via the API. For that, you will need
- To check the
manual_polling_enabled site setting.
- A master API key or an API key associated to a staff member.
Then, to push an email to Discourse, you need to pass the raw email content as the "email" parameter when POSTing to "
/admin/email/handle_mail". The endpoint accepts
application/x-www-urlencoded request bodies (with an appropriate request
Content-Type header, naturally).
Logging and Errors
All incoming emails are logged and are visible in your admin panel at
/admin/email/received. You can filter the list using the
Subject field of the emails.
rejected list (
/admin/email/rejected) is much more useful when it comes to understand things. You can filter the list using the
Subject field of the emails as well as the
At any time, you can click the
Error message and a modal will show up with more details. If it's a known error, you will find a small description explaining why that email was rejected. Then you will find all the headers of the email, the subject and the first 100 words of the raw version of the body. Finally, you will find the rejection email that was sent back to the user.
Among all the known errors, two are more common:
reply_user_not_matching_error: a reply came in from a different email address the notification was sent to.
This happens when someone uses more than one email addresses (using email aliases for example) but only reply using one email address. Let's say that the user registered an account with
auto_generated_email_error: happens when at least one of the following criteria is matched
- the '
precedence' header is set to:
- the email is from
- any of the headers contain:
auto-generated (non exhaustive list).
Since there is no standard to identify automatic emails we have to use regular expressions to match the most commonly used words and headers. These errors are usually safe to ignore but if you find a genuine email that was mis-classified, then be sure to report it here.
Here are the other known errors you might encounter:
empty_email_error: the raw mail we received was blank.
user_not_found_error: when staged users is disabled and the sender is not an existing user.
no_body_detected_error: we couldn't extract a body and there was no attachments.
inactive_user_error: the sender is not active.
blocked_user_error: the sender has been blocked.
bad_destination_address: none of the email addresses in the
Bcc fields matched a configured incoming email address.
strangers_not_allowed_error: a user tried to create a new topic in a category they're not a member of.
insufficient_trust_level_error: a user tried to create a new topic in a category they don't have the required trust level for.
topic_not_found_error: a reply came in but the related topic has been deleted.
topic_closed_error: a reply came in but the related topic has been closed.