Django + Anymail integration

Hello!

Have anyone managed to integrate Django with Anymail?

I have spent 2 days figuring out what I am doing wrong, with some food and gym pauses in between. But I am stuck in a big whole I believe.

I am trying to use Anymail to send emails via Mailgun in my project, but I get this error for some reason:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/app/.heroku/python/lib/python3.12/site-packages/django/core/mail/__init__.py", line 88, in send_mail
    return mail.send()
           ^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.12/site-packages/django/core/mail/message.py", line 301, in send
    return self.get_connection(fail_silently).send_messages([self])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.12/site-packages/anymail/backends/base.py", line 117, in send_messages
    sent = self._send(message)
           ^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.12/site-packages/anymail/backends/base_requests.py", line 51, in _send
    return super()._send(message)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.12/site-packages/anymail/backends/base.py", line 147, in _send
    response = self.post_to_esp(payload, message)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.12/site-packages/anymail/backends/base_requests.py", line 108, in post_to_esp
    self.raise_for_status(response, payload, message)
  File "/app/.heroku/python/lib/python3.12/site-packages/anymail/backends/mailgun.py", line 59, in raise_for_status
    super().raise_for_status(response, payload, message)
  File "/app/.heroku/python/lib/python3.12/site-packages/anymail/backends/base_requests.py", line 119, in raise_for_status
    raise AnymailRequestsAPIError(
anymail.exceptions.AnymailRequestsAPIError: Mailgun API response 401 (Unauthorized): 'Forbidden'

So the issue seem to be with the Mailgun API not responding.

What I have done so far is:

  1. Verified that the API key is correct (from Mailgun → Domain settings → Sending API keys).
  2. I have created a config variable in Heroku with the API key.
  3. Tested my email settings with python manage.py sendtestmail (everything was fine)
  4. I have configured my DNS settings. There are some green marks in Mailgun → DNS records
  5. I have a paid Mailgun plan. The free one does not allow emails from unverified emails.

And a lot more.

This is my production settings:

# Email back-end
EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend'

ANYMAIL = {
    'MAILGUN_API_KEY': os.environ.get("MAILGUN_API_KEY"),
    'MAILGUN_SENDER_DOMAIN': os.environ.get("MAILGUN_DOMAIN"),
}

# SMTP settings
# EMAIL_HOST = os.getenv("MAILGUN_SMTP_SERVER")
# EMAIL_PORT = os.getenv("MAILGUN_SMTP_PORT")
# EMAIL_HOST_USER = os.getenv("MAILGUN_SMTP_LOGIN") # Email user
# EMAIL_HOST_PASSWORD = os.getenv("MAILGUN_SMTP_PASSWORD") # Email password

EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL")
SERVER_EMAIL = os.environ.get("SERVER_EMAIL")

And I import the the variables from my .env file.

# Email settings
MAILGUN_API_KEY = "XXXXXXXXXXXXXXX-XXXXXXXXXXXXXXX"
MAILGUN_SENDER_DOMAIN = "XXXXX.com"
MAILGUN_PUBLIC_KEY = "pubkey-XXXXXXXXXXXXXXX"

# SMTP settings
MAILGUN_SMTP_LOGIN = "postmaster@XXXX.com"
MAILGUN_SMTP_PASSWORD = "XXXXXXXXXXXXXXX-XXXXXXXX-XXXXXXXX"
MAILGUN_SMTP_PORT = 587
MAILGUN_SMTP_SERVER = "smtp.eu.mailgun.org"
MAILGUN_API_URL  = "https://api.eu.mailgun.net/v3"

ADMIN_EMAIL_ADDRESS = "XXXXXXXX@outlook.com"
DEFAULT_FROM_EMAIL = "XXXXXXXX@outlook.com"
SERVER_EMAIL = "XXXXXXXX@outlook.com"

And finally, ‘anymail’ is included in my installed apps list.

Do anyone know what I am doing wrong or can suggest a possible solution I can try?

Are you in EU? You have MAILGUN_API_URL set to the EU domain, but you’re not including this in your ANYMAIL config. By default, it uses the US domain. You’d need to update the config as follows:

ANYMAIL = {
    'MAILGUN_API_KEY': os.environ.get("MAILGUN_API_KEY"),
    'MAILGUN_SENDER_DOMAIN': os.environ.get("MAILGUN_DOMAIN"),
    'MAILGUN_API_URL': os.environ.get("MAILGUN_API_URL"),
}
1 Like

In your .env file you have this:

And in your settings.py you have this:

Looks like you need to change that last MAILGUN_DOMAIN to MAILGUN_SENDER_DOMAIN.

2 Likes

Thanks to both of you!

My blind eye missed that, but now I managed to send my first email.

It ended up in the spam folder, but I’m celebrating anyway :smiley:

1 Like