Identify an outgoing email (SMTP) account where you can have Zulip
send mail. If you don’t already have one you want to use, see
Email services below.

Fill out the section of /etc/zulip/settings.py headed “Outgoing
email (SMTP) settings”. This includes the hostname and typically
the port to reach your SMTP provider, and the username to log into
it as.

Put the password for the SMTP user account in
/etc/zulip/zulip-secrets.conf by setting email_password. For
example: email_password=abcd1234.

Like any other change to the Zulip configuration, be sure to
restart the server to make your changes take
effect.

Test that your configuration is working. See the test command in
the Troubleshooting section below. If it’s not
working, see the suggestions in that section.

For sending outgoing email from your Zulip server, we highly recommend
using a “transactional email” service like
Mailgun,
SendGrid,
or, for AWS users,
Amazon SES.
These services are designed to send email from servers, and are by far
the easiest way to get outgoing email working reliably (Mailgun has
the best documentation).

If you don’t have an existing outgoing SMTP provider, don’t worry!
Each of the options we recommend above (as well as dozens of other
services) have free options. Once you’ve signed up, you’ll want to
find the service’s provided “SMTP credentials”, and configure Zulip as
follows:

The hostname like EMAIL_HOST='smtp.mailgun.org' in /etc/zulip/settings.py

The username like EMAIL_HOST_USER='username@example.com in
/etc/zulip/settings.py.

The TLS setting as EMAIL_USE_TLS=True in
/etc/zulip/settings.py, for most providers

The port as EMAIL_PORT=587 in /etc/zulip/settings.py, for most
providers

The password like email_password=abcd1234 in /etc/zulip/zulip-secrets.conf.

If you’d like to send outgoing email using the local operating
system’s email delivery configuration (e.g. you have postfix
configuration on the system that forwards email sent locally into your
corporate email system), you will likely need to use something like
these setting values:

We should emphasize that because modern spam filtering is very
aggressive, you should make sure your downstream email system is
configured to properly sign outgoing email sent by your Zulip server
(or check your spam folder) when using this configuration. See
documentation on using Django with a local postfix server
for additional advice.

We don’t recommend using an inbox product like Gmail for outgoing
email, because Gmail’s anti-spam measures make this annoying. But if
you want to use a Gmail account to send outgoing email anyway, here’s
how to make it work:

If you’re using 2-factor authentication on the Gmail account, you’ll
need to use an
app-specific password.

If you’re not using 2-factor authentication, read this Google
support answer and configure that account as
“less secure”;
Gmail doesn’t allow servers to send outgoing email by default.

Note also that the rate limits for Gmail are also quite low
(e.g. 100 / day), so it’s easy to get rate-limited if your server
has significant traffic. For more active servers, we recommend
moving to a free account on a transactional email service.

If it doesn’t throw an error, it probably worked; you can confirm by
checking your email. You should get two emails: One sent by a the
default From address for your Zulip server, and one sent by the
“noreply” From address.

If necessary, you can set ADD_TOKENS_TO_NOREPLY_ADDRESS to False
in /etc/zulip/settings.py (which will cause these confirmation
emails to be sent from a consistent noreply@ address). Disabling
ADD_TOKENS_TO_NOREPLY_ADDRESS is generally safe if you are not
using Zulip’s feature that allows anyone to create an account in
your Zulip organization if they have access to an email address in a
certain domain. See this article for details on
the security issue with helpdesk software that
ADD_TOKENS_TO_NOREPLY_ADDRESS helps protect against.

Make sure you set the password in /etc/zulip/zulip-secrets.conf.

Check the username and password for typos.

Be sure to restart your Zulip server after editing either
settings.py or zulip-secrets.conf, using
/home/zulip/deployments/current/scripts/restart-server .
Note that the manage.py command above will read the latest
configuration from the config files, even if the server is still
running with an old configuration.

Here are a few final notes on what to look at when debugging why you
aren’t receiving emails from Zulip:

Most transactional email services have an “outgoing email” log where
you can inspect the emails that reached the service, whether an
email was flagged as spam, etc.

Starting with Zulip 1.7, Zulip logs an entry in
/var/log/zulip/send_email.log whenever it attempts to send an
email. The log entry includes whether the request succeeded or failed.

If attempting to send an email throws an exception, a traceback
should be in /var/log/zulip/errors.log, along with any other
exceptions Zulip encounters.

Zulip’s email sending configuration is based on the standard Django
SMTP backend
configuration. So if you’re having trouble getting your email
provider working, you may want to search for documentation related
to using your email provider with Django.

The one thing we’ve changed from the Django defaults is that we read
the email password from the email_password entry in the Zulip
secrets file, as part of our policy of not having any secret
information in the /etc/zulip/settings.py file. In other words,
if Django documentation references setting EMAIL_HOST_PASSWORD,
you should instead set email_password in
/etc/zulip/zulip-secrets.conf.