mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
Mailgun: Add MAILGUN_SENDER_DOMAIN setting
Allow custom MAILGUN_SENDER_DOMAIN in Anymail settings. (Replaces need to use global esp_extra.) Improve docs to cover cases where this is needed. (esp_extra sender_domain is still supported for overriding individual messages.) Fixes #26.
This commit is contained in:
@@ -100,7 +100,9 @@ or SparkPost or any other supported ESP where you see "mailgun":
|
||||
)
|
||||
|
||||
ANYMAIL = {
|
||||
# (exact settings here depend on your ESP...)
|
||||
"MAILGUN_API_KEY": "<your Mailgun key>",
|
||||
"MAILGUN_SENDER_DOMAIN": 'mg.example.com', # your Mailgun domain, if needed
|
||||
}
|
||||
EMAIL_BACKEND = "anymail.backends.mailgun.MailgunBackend" # or sendgrid.SendGridBackend, or...
|
||||
DEFAULT_FROM_EMAIL = "you@example.com" # if you don't already have this in settings
|
||||
|
||||
@@ -16,6 +16,8 @@ class MailgunBackend(AnymailRequestsBackend):
|
||||
"""Init options from Django settings"""
|
||||
esp_name = self.esp_name
|
||||
self.api_key = get_anymail_setting('api_key', esp_name=esp_name, kwargs=kwargs, allow_bare=True)
|
||||
self.sender_domain = get_anymail_setting('sender_domain', esp_name=esp_name, kwargs=kwargs,
|
||||
allow_bare=True, default=None)
|
||||
api_url = get_anymail_setting('api_url', esp_name=esp_name, kwargs=kwargs,
|
||||
default="https://api.mailgun.net/v3")
|
||||
if not api_url.endswith("/"):
|
||||
@@ -54,7 +56,7 @@ class MailgunPayload(RequestsPayload):
|
||||
|
||||
def __init__(self, message, defaults, backend, *args, **kwargs):
|
||||
auth = ("api", backend.api_key)
|
||||
self.sender_domain = None
|
||||
self.sender_domain = backend.sender_domain
|
||||
self.all_recipients = [] # used for backend.parse_recipient_status
|
||||
|
||||
# late-binding of recipient-variables:
|
||||
|
||||
@@ -41,6 +41,20 @@ root of the settings file if neither ``ANYMAIL["MAILGUN_API_KEY"]``
|
||||
nor ``ANYMAIL_MAILGUN_API_KEY`` is set.
|
||||
|
||||
|
||||
.. setting:: ANYMAIL_MAILGUN_SENDER_DOMAIN
|
||||
|
||||
.. rubric:: MAILGUN_SENDER_DOMAIN
|
||||
|
||||
If you are using a specific `Mailgun sender domain`_
|
||||
that is *different* from your messages' `from_email` domains,
|
||||
set this to the domain you've configured in your Mailgun account.
|
||||
|
||||
If your messages' `from_email` domains always match a configured
|
||||
Mailgun sender domain, this setting is not needed.
|
||||
|
||||
See :ref:`mailgun-sender-domain` below for examples.
|
||||
|
||||
|
||||
.. setting:: ANYMAIL_MAILGUN_API_URL
|
||||
|
||||
.. rubric:: MAILGUN_API_URL
|
||||
@@ -58,32 +72,40 @@ The default is ``MAILGUN_API_URL = "https://api.mailgun.net/v3"``
|
||||
Email sender domain
|
||||
-------------------
|
||||
|
||||
Mailgun's API requires a sender domain `in the API url <base-url>`_.
|
||||
By default, Anymail will use the domain of each email's from address
|
||||
as the domain for the Mailgun API.
|
||||
Mailgun's API requires identifying the sender domain.
|
||||
By default, Anymail uses the domain of each messages's `from_email`
|
||||
(e.g., "example.com" for "from\@example.com").
|
||||
|
||||
If you need to override this default, you can use Anymail's
|
||||
:attr:`esp_extra` dict, either on an individual message:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
message = EmailMessage(from_email="sales@europe.example.com", ...)
|
||||
message.esp_extra = {"sender_domain": "example.com"}
|
||||
|
||||
|
||||
... or as a global :ref:`send default <send-defaults>` setting that applies
|
||||
to all messages:
|
||||
You will need to override this default if you are using
|
||||
a dedicated `Mailgun sender domain`_ that is different from
|
||||
a message's `from_email` domain.
|
||||
|
||||
For example, if you are sending from "orders\@example.com", but your
|
||||
Mailgun account is configured for "*mail1*.example.com", you should provide
|
||||
:setting:`MAILGUN_SENDER_DOMAIN <ANYMAIL_MAILGUN_SENDER_DOMAIN>` in your settings.py:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 4
|
||||
|
||||
ANYMAIL = {
|
||||
...
|
||||
"MAILGUN_SEND_DEFAULTS": {
|
||||
"esp_extra": {"sender_domain": "example.com"}
|
||||
}
|
||||
"MAILGUN_API_KEY": "<your API key>",
|
||||
"MAILGUN_SENDER_DOMAIN": "mail1.example.com"
|
||||
}
|
||||
|
||||
.. _base-url: https://documentation.mailgun.com/api-intro.html#base-url
|
||||
|
||||
If you need to override the sender domain for an individual message,
|
||||
include `sender_domain` in Anymail's :attr:`~anymail.message.AnymailMessage.esp_extra`
|
||||
for that message:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
message = EmailMessage(from_email="marketing@example.com", ...)
|
||||
message.esp_extra = {"sender_domain": "mail2.example.com"}
|
||||
|
||||
|
||||
.. _Mailgun sender domain:
|
||||
https://help.mailgun.com/hc/en-us/articles/202256730-How-do-I-pick-a-domain-name-for-my-Mailgun-account-
|
||||
|
||||
|
||||
.. _mailgun-esp-extra:
|
||||
|
||||
@@ -383,8 +383,8 @@ class MailgunBackendAnymailFeatureTests(MailgunBackendMockAPITestCase):
|
||||
|
||||
def test_sender_domain(self):
|
||||
"""Mailgun send domain can come from from_email or esp_extra"""
|
||||
# You could also use ANYMAIL_SEND_DEFAULTS={'esp_extra': {'sender_domain': 'your-domain.com'}}
|
||||
# (The mailgun_integration_tests do that.)
|
||||
# You could also use MAILGUN_SENDER_DOMAIN in your ANYMAIL settings, as in the next test.
|
||||
# (The mailgun_integration_tests also do that.)
|
||||
self.message.from_email = "Test From <from@from-email.example.com>"
|
||||
self.message.send()
|
||||
self.assert_esp_called('/from-email.example.com/messages') # API url includes the sender-domain
|
||||
@@ -393,6 +393,11 @@ class MailgunBackendAnymailFeatureTests(MailgunBackendMockAPITestCase):
|
||||
self.message.send()
|
||||
self.assert_esp_called('/esp-extra.example.com/messages') # overrides from_email
|
||||
|
||||
@override_settings(ANYMAIL_MAILGUN_SENDER_DOMAIN='mg.example.com')
|
||||
def test_sender_domain_setting(self):
|
||||
self.message.send()
|
||||
self.assert_esp_called('/mg.example.com/messages') # setting overrides from_email
|
||||
|
||||
def test_default_omits_options(self):
|
||||
"""Make sure by default we don't send any ESP-specific options.
|
||||
|
||||
|
||||
@@ -23,10 +23,9 @@ MAILGUN_TEST_DOMAIN = os.getenv('MAILGUN_TEST_DOMAIN')
|
||||
@unittest.skipUnless(MAILGUN_TEST_API_KEY and MAILGUN_TEST_DOMAIN,
|
||||
"Set MAILGUN_TEST_API_KEY and MAILGUN_TEST_DOMAIN environment variables "
|
||||
"to run Mailgun integration tests")
|
||||
@override_settings(ANYMAIL_MAILGUN_API_KEY=MAILGUN_TEST_API_KEY,
|
||||
ANYMAIL_MAILGUN_SEND_DEFAULTS={
|
||||
'esp_extra': {'o:testmode': 'yes',
|
||||
'sender_domain': MAILGUN_TEST_DOMAIN}},
|
||||
@override_settings(ANYMAIL={'MAILGUN_API_KEY': MAILGUN_TEST_API_KEY,
|
||||
'MAILGUN_SENDER_DOMAIN': MAILGUN_TEST_DOMAIN,
|
||||
'MAILGUN_SEND_DEFAULTS': {'esp_extra': {'o:testmode': 'yes'}}},
|
||||
EMAIL_BACKEND="anymail.backends.mailgun.MailgunBackend")
|
||||
class MailgunBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
||||
"""Mailgun API integration tests
|
||||
@@ -168,7 +167,9 @@ class MailgunBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
||||
self.assertEqual(err.status_code, 400)
|
||||
self.assertIn("'from' parameter is not a valid address", str(err))
|
||||
|
||||
@override_settings(ANYMAIL_MAILGUN_API_KEY="Hey, that's not an API key!")
|
||||
@override_settings(ANYMAIL={'MAILGUN_API_KEY': "Hey, that's not an API key",
|
||||
'MAILGUN_SENDER_DOMAIN': MAILGUN_TEST_DOMAIN,
|
||||
'MAILGUN_SEND_DEFAULTS': {'esp_extra': {'o:testmode': 'yes'}}})
|
||||
def test_invalid_api_key(self):
|
||||
with self.assertRaises(AnymailAPIError) as cm:
|
||||
self.message.send()
|
||||
|
||||
Reference in New Issue
Block a user