docs/production/email.md
Zulip needs to be able to send email so it can confirm new users' email addresses and send notifications.
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 in to
it. If your SMTP server does not require authentication, leave
EMAIL_HOST_USER empty.
You'll also want to fill out the noreply email section, taking into
account the inline documentation for the proper values for those
settings, e.g., NOREPLY_EMAIL_ADDRESS and TOKENIZED_NOREPLY_EMAIL_ADDRESS.
Note that you can also configure INSTALLATION_NAME to customize the
email sender display name for notification emails from your Zulip
server.
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.
Configure your SMTP server to allows your Zulip server to send
emails originating from the email addresses listed in
/etc/zulip/settings.py as ZULIP_ADMINISTRATOR,
NOREPLY_EMAIL_ADDRESS and if ADD_TOKENS_TO_NOREPLY_ADDRESS=True
(the default), TOKENIZED_NOREPLY_EMAIL_ADDRESS.
If you don't know how to do this, we recommend using a free transactional email service; they will guide you through everything you need to do, covering details like configuring DKIM/SPF authentication so your Zulip emails won't be spam filtered.
Use Zulip's email configuration test tool, documented in the Troubleshooting section, to verify that your configuration is working.
Once your configuration is working, restart the Zulip server with
su zulip -c '/home/zulip/deployments/current/scripts/restart-server'.
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:
EMAIL_HOST = 'smtp.mailgun.org' in /etc/zulip/settings.pyEMAIL_HOST_USER = '[email protected]' in
/etc/zulip/settings.py.EMAIL_USE_TLS = True in
/etc/zulip/settings.py, for most providersEMAIL_PORT = 587 in /etc/zulip/settings.py, for most
providersemail_password = abcd1234 in /etc/zulip/zulip-secrets.conf.If your SMTP provider uses implicit SSL/TLS on port 465 (and not STARTTLS on
port 587), you need to set EMAIL_PORT = 465, as well as replacing
EMAIL_USE_TLS = True
with EMAIL_USE_SSL = True.
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:
EMAIL_HOST = 'localhost'
EMAIL_PORT = 25
EMAIL_USE_TLS = False
EMAIL_HOST_USER = ""
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:
For prototyping, you might want to proceed without setting up an email provider. If you want to see the emails Zulip would have sent, you can log them to a file instead.
To do so, add these lines to /etc/zulip/settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/var/log/zulip/emails'
Then outgoing emails that Zulip would have sent will just be written
to files in /var/log/zulip/emails/.
Remember to delete this configuration (and restart the server) if you later set up a real SMTP provider!
You can quickly test your outgoing email configuration using:
su zulip -c '/home/zulip/deployments/current/manage.py send_test_email [email protected]'
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 the default From address for your Zulip server, and one sent by the "noreply" From address.
If it doesn't work, check these common failure causes:
Your hosting provider may block outgoing SMTP traffic in its default
firewall rules. Check whether the port EMAIL_PORT is blocked in
your hosting provider's firewall.
Your SMTP server's permissions might not allow the email account
you're using to send email from the noreply email addresses used
by Zulip when sending confirmation emails.
For security reasons, Zulip sends confirmation emails (used for
account creation, etc.) with randomly generated from addresses
starting with noreply-.
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.
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.