mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 11:51:05 -05:00
Rename EmailBackends for Django consistency
* **Future breaking change:** Rename all Anymail backends to just `EmailBackend`, matching Django's naming convention. (E.g., switch to "anymail.backends.mailgun.EmailBackend" rather than "anymail.backends.mailgun.MailgunBackend".) The old names still work, but will issue a DeprecationWarning and will be removed in some future release. (Apologies for this change; the old naming convention was a holdover from Djrill, and I wanted consistency with other Django EmailBackends before hitting 1.0.) Fixes #49.
This commit is contained in:
@@ -101,7 +101,7 @@ or SparkPost or any other supported ESP where you see "mailgun":
|
|||||||
"MAILGUN_API_KEY": "<your Mailgun key>",
|
"MAILGUN_API_KEY": "<your Mailgun key>",
|
||||||
"MAILGUN_SENDER_DOMAIN": 'mg.example.com', # your Mailgun domain, if needed
|
"MAILGUN_SENDER_DOMAIN": 'mg.example.com', # your Mailgun domain, if needed
|
||||||
}
|
}
|
||||||
EMAIL_BACKEND = "anymail.backends.mailgun.MailgunBackend" # or sendgrid.SendGridBackend, or...
|
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend" # or sendgrid.EmailBackend, or...
|
||||||
DEFAULT_FROM_EMAIL = "you@example.com" # if you don't already have this in settings
|
DEFAULT_FROM_EMAIL = "you@example.com" # if you don't already have this in settings
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -190,9 +190,12 @@ class AnymailBaseBackend(BaseEmailBackend):
|
|||||||
"""
|
"""
|
||||||
Read-only name of the ESP for this backend.
|
Read-only name of the ESP for this backend.
|
||||||
|
|
||||||
(E.g., MailgunBackend will return "Mailgun")
|
Concrete backends must override with class attr. E.g.:
|
||||||
|
esp_name = "Postmark"
|
||||||
|
esp_name = "SendGrid" # (use ESP's preferred capitalization)
|
||||||
"""
|
"""
|
||||||
return self.__class__.__name__.replace("Backend", "")
|
raise NotImplementedError("%s.%s must declare esp_name class attr" %
|
||||||
|
(self.__class__.__module__, self.__class__.__name__))
|
||||||
|
|
||||||
|
|
||||||
class BasePayload(object):
|
class BasePayload(object):
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
|
import warnings
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from ..exceptions import AnymailRequestsAPIError, AnymailError
|
from ..exceptions import AnymailRequestsAPIError, AnymailError, AnymailDeprecationWarning
|
||||||
from ..message import AnymailRecipientStatus
|
from ..message import AnymailRecipientStatus
|
||||||
from ..utils import get_anymail_setting, rfc2822date
|
from ..utils import get_anymail_setting, rfc2822date
|
||||||
|
|
||||||
from .base_requests import AnymailRequestsBackend, RequestsPayload
|
from .base_requests import AnymailRequestsBackend, RequestsPayload
|
||||||
|
|
||||||
|
|
||||||
class MailgunBackend(AnymailRequestsBackend):
|
class EmailBackend(AnymailRequestsBackend):
|
||||||
"""
|
"""
|
||||||
Mailgun API Email Backend
|
Mailgun API Email Backend
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
esp_name = "Mailgun"
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
"""Init options from Django settings"""
|
"""Init options from Django settings"""
|
||||||
esp_name = self.esp_name
|
esp_name = self.esp_name
|
||||||
@@ -22,7 +25,7 @@ class MailgunBackend(AnymailRequestsBackend):
|
|||||||
default="https://api.mailgun.net/v3")
|
default="https://api.mailgun.net/v3")
|
||||||
if not api_url.endswith("/"):
|
if not api_url.endswith("/"):
|
||||||
api_url += "/"
|
api_url += "/"
|
||||||
super(MailgunBackend, self).__init__(api_url, **kwargs)
|
super(EmailBackend, self).__init__(api_url, **kwargs)
|
||||||
|
|
||||||
def build_message_payload(self, message, defaults):
|
def build_message_payload(self, message, defaults):
|
||||||
return MailgunPayload(message, defaults, self)
|
return MailgunPayload(message, defaults, self)
|
||||||
@@ -52,6 +55,15 @@ class MailgunBackend(AnymailRequestsBackend):
|
|||||||
return {recipient.email: status for recipient in payload.all_recipients}
|
return {recipient.email: status for recipient in payload.all_recipients}
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-v0.8 naming (deprecated)
|
||||||
|
class MailgunBackend(EmailBackend):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
warnings.warn(AnymailDeprecationWarning(
|
||||||
|
"Please update your EMAIL_BACKEND setting to "
|
||||||
|
"'anymail.backends.mailgun.EmailBackend'"))
|
||||||
|
super(MailgunBackend, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class MailgunPayload(RequestsPayload):
|
class MailgunPayload(RequestsPayload):
|
||||||
|
|
||||||
def __init__(self, message, defaults, backend, *args, **kwargs):
|
def __init__(self, message, defaults, backend, *args, **kwargs):
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
import warnings
|
import warnings
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from ..exceptions import AnymailRequestsAPIError, AnymailWarning
|
from ..exceptions import AnymailRequestsAPIError, AnymailWarning, AnymailDeprecationWarning
|
||||||
from ..message import AnymailRecipientStatus, ANYMAIL_STATUSES
|
from ..message import AnymailRecipientStatus, ANYMAIL_STATUSES
|
||||||
from ..utils import last, combine, get_anymail_setting
|
from ..utils import last, combine, get_anymail_setting
|
||||||
|
|
||||||
from .base_requests import AnymailRequestsBackend, RequestsPayload
|
from .base_requests import AnymailRequestsBackend, RequestsPayload
|
||||||
|
|
||||||
|
|
||||||
class MandrillBackend(AnymailRequestsBackend):
|
class EmailBackend(AnymailRequestsBackend):
|
||||||
"""
|
"""
|
||||||
Mandrill API Email Backend
|
Mandrill API Email Backend
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
esp_name = "Mandrill"
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
"""Init options from Django settings"""
|
"""Init options from Django settings"""
|
||||||
esp_name = self.esp_name
|
esp_name = self.esp_name
|
||||||
@@ -21,7 +23,7 @@ class MandrillBackend(AnymailRequestsBackend):
|
|||||||
default="https://mandrillapp.com/api/1.0")
|
default="https://mandrillapp.com/api/1.0")
|
||||||
if not api_url.endswith("/"):
|
if not api_url.endswith("/"):
|
||||||
api_url += "/"
|
api_url += "/"
|
||||||
super(MandrillBackend, self).__init__(api_url, **kwargs)
|
super(EmailBackend, self).__init__(api_url, **kwargs)
|
||||||
|
|
||||||
def build_message_payload(self, message, defaults):
|
def build_message_payload(self, message, defaults):
|
||||||
return MandrillPayload(message, defaults, self)
|
return MandrillPayload(message, defaults, self)
|
||||||
@@ -44,6 +46,15 @@ class MandrillBackend(AnymailRequestsBackend):
|
|||||||
return recipient_status
|
return recipient_status
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-v0.8 naming (deprecated)
|
||||||
|
class MandrillBackend(EmailBackend):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
warnings.warn(AnymailDeprecationWarning(
|
||||||
|
"Please update your EMAIL_BACKEND setting to "
|
||||||
|
"'anymail.backends.mandrill.EmailBackend'"))
|
||||||
|
super(MandrillBackend, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DjrillDeprecationWarning(AnymailWarning, DeprecationWarning):
|
class DjrillDeprecationWarning(AnymailWarning, DeprecationWarning):
|
||||||
"""Warning for features carried over from Djrill that will be removed soon"""
|
"""Warning for features carried over from Djrill that will be removed soon"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
import re
|
import re
|
||||||
|
import warnings
|
||||||
|
|
||||||
from requests.structures import CaseInsensitiveDict
|
from requests.structures import CaseInsensitiveDict
|
||||||
|
|
||||||
from ..exceptions import AnymailRequestsAPIError
|
from ..exceptions import AnymailRequestsAPIError, AnymailDeprecationWarning
|
||||||
from ..message import AnymailRecipientStatus
|
from ..message import AnymailRecipientStatus
|
||||||
from ..utils import get_anymail_setting
|
from ..utils import get_anymail_setting
|
||||||
|
|
||||||
from .base_requests import AnymailRequestsBackend, RequestsPayload
|
from .base_requests import AnymailRequestsBackend, RequestsPayload
|
||||||
|
|
||||||
|
|
||||||
class PostmarkBackend(AnymailRequestsBackend):
|
class EmailBackend(AnymailRequestsBackend):
|
||||||
"""
|
"""
|
||||||
Postmark API Email Backend
|
Postmark API Email Backend
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
esp_name = "Postmark"
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
"""Init options from Django settings"""
|
"""Init options from Django settings"""
|
||||||
esp_name = self.esp_name
|
esp_name = self.esp_name
|
||||||
@@ -22,7 +25,7 @@ class PostmarkBackend(AnymailRequestsBackend):
|
|||||||
default="https://api.postmarkapp.com/")
|
default="https://api.postmarkapp.com/")
|
||||||
if not api_url.endswith("/"):
|
if not api_url.endswith("/"):
|
||||||
api_url += "/"
|
api_url += "/"
|
||||||
super(PostmarkBackend, self).__init__(api_url, **kwargs)
|
super(EmailBackend, self).__init__(api_url, **kwargs)
|
||||||
|
|
||||||
def build_message_payload(self, message, defaults):
|
def build_message_payload(self, message, defaults):
|
||||||
return PostmarkPayload(message, defaults, self)
|
return PostmarkPayload(message, defaults, self)
|
||||||
@@ -30,7 +33,7 @@ class PostmarkBackend(AnymailRequestsBackend):
|
|||||||
def raise_for_status(self, response, payload, message):
|
def raise_for_status(self, response, payload, message):
|
||||||
# We need to handle 422 responses in parse_recipient_status
|
# We need to handle 422 responses in parse_recipient_status
|
||||||
if response.status_code != 422:
|
if response.status_code != 422:
|
||||||
super(PostmarkBackend, self).raise_for_status(response, payload, message)
|
super(EmailBackend, self).raise_for_status(response, payload, message)
|
||||||
|
|
||||||
def parse_recipient_status(self, response, payload, message):
|
def parse_recipient_status(self, response, payload, message):
|
||||||
parsed_response = self.deserialize_json_response(response, payload, message)
|
parsed_response = self.deserialize_json_response(response, payload, message)
|
||||||
@@ -89,6 +92,15 @@ class PostmarkBackend(AnymailRequestsBackend):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-v0.8 naming (deprecated)
|
||||||
|
class PostmarkBackend(EmailBackend):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
warnings.warn(AnymailDeprecationWarning(
|
||||||
|
"Please update your EMAIL_BACKEND setting to "
|
||||||
|
"'anymail.backends.postmark.EmailBackend'"))
|
||||||
|
super(PostmarkBackend, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class PostmarkPayload(RequestsPayload):
|
class PostmarkPayload(RequestsPayload):
|
||||||
|
|
||||||
def __init__(self, message, defaults, backend, *args, **kwargs):
|
def __init__(self, message, defaults, backend, *args, **kwargs):
|
||||||
|
|||||||
@@ -5,16 +5,18 @@ from django.core.mail import make_msgid
|
|||||||
from requests.structures import CaseInsensitiveDict
|
from requests.structures import CaseInsensitiveDict
|
||||||
|
|
||||||
from .base_requests import AnymailRequestsBackend, RequestsPayload
|
from .base_requests import AnymailRequestsBackend, RequestsPayload
|
||||||
from ..exceptions import AnymailConfigurationError, AnymailRequestsAPIError, AnymailWarning
|
from ..exceptions import AnymailConfigurationError, AnymailRequestsAPIError, AnymailWarning, AnymailDeprecationWarning
|
||||||
from ..message import AnymailRecipientStatus
|
from ..message import AnymailRecipientStatus
|
||||||
from ..utils import get_anymail_setting, timestamp, update_deep
|
from ..utils import get_anymail_setting, timestamp, update_deep
|
||||||
|
|
||||||
|
|
||||||
class SendGridBackend(AnymailRequestsBackend):
|
class EmailBackend(AnymailRequestsBackend):
|
||||||
"""
|
"""
|
||||||
SendGrid v3 API Email Backend
|
SendGrid v3 API Email Backend
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
esp_name = "SendGrid"
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
"""Init options from Django settings"""
|
"""Init options from Django settings"""
|
||||||
esp_name = self.esp_name
|
esp_name = self.esp_name
|
||||||
@@ -46,7 +48,7 @@ class SendGridBackend(AnymailRequestsBackend):
|
|||||||
default="https://api.sendgrid.com/v3/")
|
default="https://api.sendgrid.com/v3/")
|
||||||
if not api_url.endswith("/"):
|
if not api_url.endswith("/"):
|
||||||
api_url += "/"
|
api_url += "/"
|
||||||
super(SendGridBackend, self).__init__(api_url, **kwargs)
|
super(EmailBackend, self).__init__(api_url, **kwargs)
|
||||||
|
|
||||||
def build_message_payload(self, message, defaults):
|
def build_message_payload(self, message, defaults):
|
||||||
return SendGridPayload(message, defaults, self)
|
return SendGridPayload(message, defaults, self)
|
||||||
@@ -64,6 +66,15 @@ class SendGridBackend(AnymailRequestsBackend):
|
|||||||
return {recipient.email: status for recipient in payload.all_recipients}
|
return {recipient.email: status for recipient in payload.all_recipients}
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-v0.8 naming (deprecated)
|
||||||
|
class SendGridBackend(EmailBackend):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
warnings.warn(AnymailDeprecationWarning(
|
||||||
|
"Please update your EMAIL_BACKEND setting to "
|
||||||
|
"'anymail.backends.sendgrid.EmailBackend'"))
|
||||||
|
super(SendGridBackend, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SendGridPayload(RequestsPayload):
|
class SendGridPayload(RequestsPayload):
|
||||||
|
|
||||||
def __init__(self, message, defaults, backend, *args, **kwargs):
|
def __init__(self, message, defaults, backend, *args, **kwargs):
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ class SendGridPayload(RequestsPayload):
|
|||||||
if files_field in self.files:
|
if files_field in self.files:
|
||||||
# It's possible SendGrid could actually handle this case (needs testing),
|
# It's possible SendGrid could actually handle this case (needs testing),
|
||||||
# but requests doesn't seem to accept a list of tuples for a files field.
|
# but requests doesn't seem to accept a list of tuples for a files field.
|
||||||
# (See the MailgunBackend version for a different approach that might work.)
|
# (See the Mailgun EmailBackend version for a different approach that might work.)
|
||||||
self.unsupported_feature(
|
self.unsupported_feature(
|
||||||
"multiple attachments with the same filename ('%s')" % filename if filename
|
"multiple attachments with the same filename ('%s')" % filename if filename
|
||||||
else "multiple unnamed attachments")
|
else "multiple unnamed attachments")
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
from __future__ import absolute_import # we want the sparkpost package, not our own module
|
from __future__ import absolute_import # we want the sparkpost package, not our own module
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
from .base import AnymailBaseBackend, BasePayload
|
from .base import AnymailBaseBackend, BasePayload
|
||||||
from ..exceptions import AnymailAPIError, AnymailImproperlyInstalled, AnymailConfigurationError
|
from ..exceptions import (AnymailAPIError, AnymailImproperlyInstalled,
|
||||||
|
AnymailConfigurationError, AnymailDeprecationWarning)
|
||||||
from ..message import AnymailRecipientStatus
|
from ..message import AnymailRecipientStatus
|
||||||
from ..utils import get_anymail_setting
|
from ..utils import get_anymail_setting
|
||||||
|
|
||||||
@@ -11,14 +14,16 @@ except ImportError:
|
|||||||
raise AnymailImproperlyInstalled(missing_package='sparkpost', backend='sparkpost')
|
raise AnymailImproperlyInstalled(missing_package='sparkpost', backend='sparkpost')
|
||||||
|
|
||||||
|
|
||||||
class SparkPostBackend(AnymailBaseBackend):
|
class EmailBackend(AnymailBaseBackend):
|
||||||
"""
|
"""
|
||||||
SparkPost Email Backend (using python-sparkpost client)
|
SparkPost Email Backend (using python-sparkpost client)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
esp_name = "SparkPost"
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
"""Init options from Django settings"""
|
"""Init options from Django settings"""
|
||||||
super(SparkPostBackend, self).__init__(**kwargs)
|
super(EmailBackend, self).__init__(**kwargs)
|
||||||
# SPARKPOST_API_KEY is optional - library reads from env by default
|
# SPARKPOST_API_KEY is optional - library reads from env by default
|
||||||
self.api_key = get_anymail_setting('api_key', esp_name=self.esp_name,
|
self.api_key = get_anymail_setting('api_key', esp_name=self.esp_name,
|
||||||
kwargs=kwargs, allow_bare=True, default=None)
|
kwargs=kwargs, allow_bare=True, default=None)
|
||||||
@@ -77,6 +82,15 @@ class SparkPostBackend(AnymailBaseBackend):
|
|||||||
return {recipient.email: recipient_status for recipient in payload.all_recipients}
|
return {recipient.email: recipient_status for recipient in payload.all_recipients}
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-v0.8 naming (deprecated)
|
||||||
|
class SparkPostBackend(EmailBackend):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
warnings.warn(AnymailDeprecationWarning(
|
||||||
|
"Please update your EMAIL_BACKEND setting to "
|
||||||
|
"'anymail.backends.sparkpost.EmailBackend'"))
|
||||||
|
super(SparkPostBackend, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SparkPostPayload(BasePayload):
|
class SparkPostPayload(BasePayload):
|
||||||
def init_payload(self):
|
def init_payload(self):
|
||||||
self.params = {}
|
self.params = {}
|
||||||
|
|||||||
@@ -5,13 +5,15 @@ from .base import AnymailBaseBackend, BasePayload
|
|||||||
from ..utils import get_anymail_setting
|
from ..utils import get_anymail_setting
|
||||||
|
|
||||||
|
|
||||||
class TestBackend(AnymailBaseBackend):
|
class EmailBackend(AnymailBaseBackend):
|
||||||
"""
|
"""
|
||||||
Anymail backend that doesn't do anything.
|
Anymail backend that doesn't do anything.
|
||||||
|
|
||||||
Used for testing Anymail common backend functionality.
|
Used for testing Anymail common backend functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
esp_name = "Test"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# Init options from Django settings
|
# Init options from Django settings
|
||||||
esp_name = self.esp_name
|
esp_name = self.esp_name
|
||||||
@@ -19,7 +21,7 @@ class TestBackend(AnymailBaseBackend):
|
|||||||
kwargs=kwargs, allow_bare=True)
|
kwargs=kwargs, allow_bare=True)
|
||||||
self.recorded_send_params = get_anymail_setting('recorded_send_params', default=[],
|
self.recorded_send_params = get_anymail_setting('recorded_send_params', default=[],
|
||||||
esp_name=esp_name, kwargs=kwargs)
|
esp_name=esp_name, kwargs=kwargs)
|
||||||
super(TestBackend, self).__init__(*args, **kwargs)
|
super(EmailBackend, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def build_message_payload(self, message, defaults):
|
def build_message_payload(self, message, defaults):
|
||||||
return TestPayload(backend=self, message=message, defaults=defaults)
|
return TestPayload(backend=self, message=message, defaults=defaults)
|
||||||
@@ -47,6 +49,14 @@ class TestBackend(AnymailBaseBackend):
|
|||||||
raise AnymailAPIError('Unparsable test response')
|
raise AnymailAPIError('Unparsable test response')
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-v0.8 naming (immediately deprecated for this undocumented test feature)
|
||||||
|
class TestBackend(object):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
raise NotImplementedError(
|
||||||
|
"Anymail's (undocumented) TestBackend has been renamed to "
|
||||||
|
"'anymail.backends.test.EmailBackend'")
|
||||||
|
|
||||||
|
|
||||||
class TestPayload(BasePayload):
|
class TestPayload(BasePayload):
|
||||||
# For test purposes, just keep a dict of the params we've received.
|
# For test purposes, just keep a dict of the params we've received.
|
||||||
# (This approach is also useful for native API backends -- think of
|
# (This approach is also useful for native API backends -- think of
|
||||||
|
|||||||
@@ -175,3 +175,7 @@ class AnymailWarning(Warning):
|
|||||||
|
|
||||||
class AnymailInsecureWebhookWarning(AnymailWarning):
|
class AnymailInsecureWebhookWarning(AnymailWarning):
|
||||||
"""Warns when webhook configured without any validation"""
|
"""Warns when webhook configured without any validation"""
|
||||||
|
|
||||||
|
|
||||||
|
class AnymailDeprecationWarning(AnymailWarning, DeprecationWarning):
|
||||||
|
"""Warning for deprecated Anymail features"""
|
||||||
|
|||||||
@@ -17,10 +17,9 @@ To use Anymail's Mailgun backend, set:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
EMAIL_BACKEND = "anymail.backends.mailgun.MailgunBackend"
|
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend"
|
||||||
|
|
||||||
in your settings.py. (Watch your capitalization: Mailgun spells their name with a
|
in your settings.py.
|
||||||
lowercase "g", so Anymail does too.)
|
|
||||||
|
|
||||||
|
|
||||||
.. setting:: ANYMAIL_MAILGUN_API_KEY
|
.. setting:: ANYMAIL_MAILGUN_API_KEY
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ To use Anymail's Mandrill backend, set:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
EMAIL_BACKEND = "anymail.backends.mandrill.MandrillBackend"
|
EMAIL_BACKEND = "anymail.backends.mandrill.EmailBackend"
|
||||||
|
|
||||||
in your settings.py.
|
in your settings.py.
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,9 @@ To use Anymail's Postmark backend, set:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
EMAIL_BACKEND = "anymail.backends.postmark.PostmarkBackend"
|
EMAIL_BACKEND = "anymail.backends.postmark.EmailBackend"
|
||||||
|
|
||||||
in your settings.py. (Watch your capitalization: Postmark spells their name with a
|
in your settings.py.
|
||||||
lowercase "m", so Anymail does too.)
|
|
||||||
|
|
||||||
|
|
||||||
.. setting:: ANYMAIL_POSTMARK_SERVER_TOKEN
|
.. setting:: ANYMAIL_POSTMARK_SERVER_TOKEN
|
||||||
|
|||||||
@@ -34,10 +34,9 @@ To use Anymail's SendGrid backend, set:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
EMAIL_BACKEND = "anymail.backends.sendgrid.SendGridBackend"
|
EMAIL_BACKEND = "anymail.backends.sendgrid.EmailBackend"
|
||||||
|
|
||||||
in your settings.py. (Watch your capitalization: SendGrid spells
|
in your settings.py.
|
||||||
their name with an uppercase "G", so Anymail does too.)
|
|
||||||
|
|
||||||
|
|
||||||
.. setting:: ANYMAIL_SENDGRID_API_KEY
|
.. setting:: ANYMAIL_SENDGRID_API_KEY
|
||||||
|
|||||||
@@ -33,10 +33,9 @@ To use Anymail's SparkPost backend, set:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
EMAIL_BACKEND = "anymail.backends.sparkpost.SparkPostBackend"
|
EMAIL_BACKEND = "anymail.backends.sparkpost.EmailBackend"
|
||||||
|
|
||||||
in your settings.py. (Watch your capitalization: SparkPost spells
|
in your settings.py.
|
||||||
their name with an inner capital "P", so Anymail does too.)
|
|
||||||
|
|
||||||
|
|
||||||
.. setting:: ANYMAIL_SPARKPOST_API_KEY
|
.. setting:: ANYMAIL_SPARKPOST_API_KEY
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ To use Anymail for sending email, edit your Django project's :file:`settings.py`
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
EMAIL_BACKEND = "anymail.backends.mailgun.MailgunBackend"
|
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend"
|
||||||
|
|
||||||
(:setting:`EMAIL_BACKEND` sets Django's default for sending emails; you can also
|
(:setting:`EMAIL_BACKEND` sets Django's default for sending emails; you can also
|
||||||
use :ref:`multiple Anymail backends <multiple-backends>` to send particular
|
use :ref:`multiple Anymail backends <multiple-backends>` to send particular
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ but send admin emails directly through an SMTP server:
|
|||||||
from django.core.mail import send_mail, get_connection
|
from django.core.mail import send_mail, get_connection
|
||||||
|
|
||||||
# send_mail connection defaults to the settings EMAIL_BACKEND, which
|
# send_mail connection defaults to the settings EMAIL_BACKEND, which
|
||||||
# we've set to Anymail's MailgunBackend. This will be sent using Mailgun:
|
# we've set to Anymail's Mailgun EmailBackend. This will be sent using Mailgun:
|
||||||
send_mail("Thanks", "We sent your order", "sales@example.com", ["customer@example.com"])
|
send_mail("Thanks", "We sent your order", "sales@example.com", ["customer@example.com"])
|
||||||
|
|
||||||
# Get a connection to an SMTP backend, and send using that instead:
|
# Get a connection to an SMTP backend, and send using that instead:
|
||||||
@@ -27,13 +27,13 @@ but send admin emails directly through an SMTP server:
|
|||||||
connection=smtp_backend)
|
connection=smtp_backend)
|
||||||
|
|
||||||
# You can even use multiple Anymail backends in the same app:
|
# You can even use multiple Anymail backends in the same app:
|
||||||
sendgrid_backend = get_connection('anymail.backends.sendgrid.SendGridBackend')
|
sendgrid_backend = get_connection('anymail.backends.sendgrid.EmailBackend')
|
||||||
send_mail("Password reset", "Here you go", "noreply@example.com", ["user@example.com"],
|
send_mail("Password reset", "Here you go", "noreply@example.com", ["user@example.com"],
|
||||||
connection=sendgrid_backend)
|
connection=sendgrid_backend)
|
||||||
|
|
||||||
# You can override settings.py settings with kwargs to get_connection.
|
# You can override settings.py settings with kwargs to get_connection.
|
||||||
# This example supplies credentials to use a SendGrid subuser acccount:
|
# This example supplies credentials to use a SendGrid subuser acccount:
|
||||||
alt_sendgrid_backend = get_connection('anymail.backends.sendgrid.SendGridBackend',
|
alt_sendgrid_backend = get_connection('anymail.backends.sendgrid.EmailBackend',
|
||||||
username='marketing_subuser', password='abc123')
|
username='marketing_subuser', password='abc123')
|
||||||
send_mail("Here's that info", "you wanted", "marketing@example.com", ["prospect@example.com"],
|
send_mail("Here's that info", "you wanted", "marketing@example.com", ["prospect@example.com"],
|
||||||
connection=alt_sendgrid_backend)
|
connection=alt_sendgrid_backend)
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ from .utils import AnymailTestMixin
|
|||||||
recorded_send_params = []
|
recorded_send_params = []
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND='anymail.backends.test.TestBackend',
|
@override_settings(EMAIL_BACKEND='anymail.backends.test.EmailBackend',
|
||||||
ANYMAIL_TEST_SAMPLE_SETTING='sample', # required TestBackend setting
|
ANYMAIL_TEST_SAMPLE_SETTING='sample', # required test EmailBackend setting
|
||||||
ANYMAIL_TEST_RECORDED_SEND_PARAMS=recorded_send_params)
|
ANYMAIL_TEST_RECORDED_SEND_PARAMS=recorded_send_params)
|
||||||
class TestBackendTestCase(SimpleTestCase, AnymailTestMixin):
|
class TestBackendTestCase(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Base TestCase using Anymail's TestBackend"""
|
"""Base TestCase using Anymail's Test EmailBackend"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestBackendTestCase, self).setUp()
|
super(TestBackendTestCase, self).setUp()
|
||||||
@@ -42,7 +42,7 @@ class TestBackendTestCase(SimpleTestCase, AnymailTestMixin):
|
|||||||
return recorded_send_params[-1]
|
return recorded_send_params[-1]
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND='anymail.backends.test.TestBackend') # but no ANYMAIL settings overrides
|
@override_settings(EMAIL_BACKEND='anymail.backends.test.EmailBackend') # but no ANYMAIL settings overrides
|
||||||
class BackendSettingsTests(SimpleTestCase, AnymailTestMixin): # (so not TestBackendTestCase)
|
class BackendSettingsTests(SimpleTestCase, AnymailTestMixin): # (so not TestBackendTestCase)
|
||||||
"""Test settings initializations for Anymail EmailBackends"""
|
"""Test settings initializations for Anymail EmailBackends"""
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ class UnsupportedFeatureTests(TestBackendTestCase):
|
|||||||
|
|
||||||
def test_unsupported_feature(self):
|
def test_unsupported_feature(self):
|
||||||
"""Unsupported features raise AnymailUnsupportedFeature"""
|
"""Unsupported features raise AnymailUnsupportedFeature"""
|
||||||
# TestBackend doesn't support non-HTML alternative parts
|
# Test EmailBackend doesn't support non-HTML alternative parts
|
||||||
self.message.attach_alternative(b'FAKE_MP3_DATA', 'audio/mpeg')
|
self.message.attach_alternative(b'FAKE_MP3_DATA', 'audio/mpeg')
|
||||||
with self.assertRaises(AnymailUnsupportedFeature):
|
with self.assertRaises(AnymailUnsupportedFeature):
|
||||||
self.message.send()
|
self.message.send()
|
||||||
@@ -135,10 +135,10 @@ class SendDefaultsTests(TestBackendTestCase):
|
|||||||
self.assertEqual(params['tags'], ['globaltag'])
|
self.assertEqual(params['tags'], ['globaltag'])
|
||||||
self.assertEqual(params['template_id'], 'my-template')
|
self.assertEqual(params['template_id'], 'my-template')
|
||||||
self.assertEqual(params['track_clicks'], True)
|
self.assertEqual(params['track_clicks'], True)
|
||||||
self.assertEqual(params['globalextra'], 'globalsetting') # TestBackend merges esp_extra into params
|
self.assertEqual(params['globalextra'], 'globalsetting') # Test EmailBackend merges esp_extra into params
|
||||||
|
|
||||||
@override_settings(ANYMAIL={
|
@override_settings(ANYMAIL={
|
||||||
'TEST_SEND_DEFAULTS': { # "TEST" is the name of the TestBackend's ESP
|
'TEST_SEND_DEFAULTS': { # "TEST" is the name of the Test EmailBackend's ESP
|
||||||
'metadata': {'global': 'espvalue'},
|
'metadata': {'global': 'espvalue'},
|
||||||
'tags': ['esptag'],
|
'tags': ['esptag'],
|
||||||
'track_opens': False,
|
'track_opens': False,
|
||||||
@@ -152,7 +152,7 @@ class SendDefaultsTests(TestBackendTestCase):
|
|||||||
self.assertEqual(params['metadata'], {'global': 'espvalue'})
|
self.assertEqual(params['metadata'], {'global': 'espvalue'})
|
||||||
self.assertEqual(params['tags'], ['esptag'])
|
self.assertEqual(params['tags'], ['esptag'])
|
||||||
self.assertEqual(params['track_opens'], False)
|
self.assertEqual(params['track_opens'], False)
|
||||||
self.assertEqual(params['globalextra'], 'espsetting') # TestBackend merges esp_extra into params
|
self.assertEqual(params['globalextra'], 'espsetting') # Test EmailBackend merges esp_extra into params
|
||||||
|
|
||||||
@override_settings(ANYMAIL={
|
@override_settings(ANYMAIL={
|
||||||
'SEND_DEFAULTS': {
|
'SEND_DEFAULTS': {
|
||||||
@@ -199,7 +199,7 @@ class SendDefaultsTests(TestBackendTestCase):
|
|||||||
'template_id': 'global-template',
|
'template_id': 'global-template',
|
||||||
'esp_extra': {'globalextra': 'globalsetting'},
|
'esp_extra': {'globalextra': 'globalsetting'},
|
||||||
},
|
},
|
||||||
'TEST_SEND_DEFAULTS': { # "TEST" is the name of the TestBackend's ESP
|
'TEST_SEND_DEFAULTS': { # "TEST" is the name of the Test EmailBackend's ESP
|
||||||
'merge_global_data': {'esp': 'espmerge'},
|
'merge_global_data': {'esp': 'espmerge'},
|
||||||
'metadata': {'esp': 'espvalue'},
|
'metadata': {'esp': 'espvalue'},
|
||||||
'tags': ['esptag'],
|
'tags': ['esptag'],
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from .mock_requests_backend import RequestsBackendMockAPITestCase, SessionSharin
|
|||||||
from .utils import sample_image_content, sample_image_path, SAMPLE_IMAGE_FILENAME, AnymailTestMixin
|
from .utils import sample_image_content, sample_image_path, SAMPLE_IMAGE_FILENAME, AnymailTestMixin
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND='anymail.backends.mailgun.MailgunBackend',
|
@override_settings(EMAIL_BACKEND='anymail.backends.mailgun.EmailBackend',
|
||||||
ANYMAIL={'MAILGUN_API_KEY': 'test_api_key'})
|
ANYMAIL={'MAILGUN_API_KEY': 'test_api_key'})
|
||||||
class MailgunBackendMockAPITestCase(RequestsBackendMockAPITestCase):
|
class MailgunBackendMockAPITestCase(RequestsBackendMockAPITestCase):
|
||||||
DEFAULT_RAW_RESPONSE = b"""{
|
DEFAULT_RAW_RESPONSE = b"""{
|
||||||
@@ -483,7 +483,7 @@ class MailgunBackendSessionSharingTestCase(SessionSharingTestCasesMixin, Mailgun
|
|||||||
pass # tests are defined in the mixin
|
pass # tests are defined in the mixin
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND="anymail.backends.mailgun.MailgunBackend")
|
@override_settings(EMAIL_BACKEND="anymail.backends.mailgun.EmailBackend")
|
||||||
class MailgunBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
class MailgunBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Test ESP backend without required settings in place"""
|
"""Test ESP backend without required settings in place"""
|
||||||
|
|
||||||
@@ -494,3 +494,13 @@ class MailgunBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
|||||||
# Make sure the error mentions MAILGUN_API_KEY and ANYMAIL_MAILGUN_API_KEY
|
# Make sure the error mentions MAILGUN_API_KEY and ANYMAIL_MAILGUN_API_KEY
|
||||||
self.assertRegex(errmsg, r'\bMAILGUN_API_KEY\b')
|
self.assertRegex(errmsg, r'\bMAILGUN_API_KEY\b')
|
||||||
self.assertRegex(errmsg, r'\bANYMAIL_MAILGUN_API_KEY\b')
|
self.assertRegex(errmsg, r'\bANYMAIL_MAILGUN_API_KEY\b')
|
||||||
|
|
||||||
|
|
||||||
|
class MailgunBackendDeprecationTests(MailgunBackendMockAPITestCase):
|
||||||
|
@override_settings(EMAIL_BACKEND='anymail.backends.mailgun.MailgunBackend')
|
||||||
|
def test_renamed_backend_warning(self):
|
||||||
|
# ...mailgun.MailgunBackend --> ...mailgun.EmailBackend
|
||||||
|
with self.assertWarnsRegex(DeprecationWarning,
|
||||||
|
r'anymail\.backends\.mailgun\.EmailBackend'):
|
||||||
|
self.message.send()
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ MAILGUN_TEST_DOMAIN = os.getenv('MAILGUN_TEST_DOMAIN')
|
|||||||
@override_settings(ANYMAIL={'MAILGUN_API_KEY': MAILGUN_TEST_API_KEY,
|
@override_settings(ANYMAIL={'MAILGUN_API_KEY': MAILGUN_TEST_API_KEY,
|
||||||
'MAILGUN_SENDER_DOMAIN': MAILGUN_TEST_DOMAIN,
|
'MAILGUN_SENDER_DOMAIN': MAILGUN_TEST_DOMAIN,
|
||||||
'MAILGUN_SEND_DEFAULTS': {'esp_extra': {'o:testmode': 'yes'}}},
|
'MAILGUN_SEND_DEFAULTS': {'esp_extra': {'o:testmode': 'yes'}}},
|
||||||
EMAIL_BACKEND="anymail.backends.mailgun.MailgunBackend")
|
EMAIL_BACKEND="anymail.backends.mailgun.EmailBackend")
|
||||||
class MailgunBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
class MailgunBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Mailgun API integration tests
|
"""Mailgun API integration tests
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from .mock_requests_backend import RequestsBackendMockAPITestCase, SessionSharin
|
|||||||
from .utils import sample_image_content, sample_image_path, SAMPLE_IMAGE_FILENAME, AnymailTestMixin, decode_att
|
from .utils import sample_image_content, sample_image_path, SAMPLE_IMAGE_FILENAME, AnymailTestMixin, decode_att
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND='anymail.backends.mandrill.MandrillBackend',
|
@override_settings(EMAIL_BACKEND='anymail.backends.mandrill.EmailBackend',
|
||||||
ANYMAIL={'MANDRILL_API_KEY': 'test_api_key'})
|
ANYMAIL={'MANDRILL_API_KEY': 'test_api_key'})
|
||||||
class MandrillBackendMockAPITestCase(RequestsBackendMockAPITestCase):
|
class MandrillBackendMockAPITestCase(RequestsBackendMockAPITestCase):
|
||||||
DEFAULT_RAW_RESPONSE = b"""[{
|
DEFAULT_RAW_RESPONSE = b"""[{
|
||||||
@@ -588,7 +588,7 @@ class MandrillBackendSessionSharingTestCase(SessionSharingTestCasesMixin, Mandri
|
|||||||
pass # tests are defined in the mixin
|
pass # tests are defined in the mixin
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND="anymail.backends.mandrill.MandrillBackend")
|
@override_settings(EMAIL_BACKEND="anymail.backends.mandrill.EmailBackend")
|
||||||
class MandrillBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
class MandrillBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Test backend without required settings"""
|
"""Test backend without required settings"""
|
||||||
|
|
||||||
@@ -598,3 +598,12 @@ class MandrillBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin)
|
|||||||
errmsg = str(cm.exception)
|
errmsg = str(cm.exception)
|
||||||
self.assertRegex(errmsg, r'\bMANDRILL_API_KEY\b')
|
self.assertRegex(errmsg, r'\bMANDRILL_API_KEY\b')
|
||||||
self.assertRegex(errmsg, r'\bANYMAIL_MANDRILL_API_KEY\b')
|
self.assertRegex(errmsg, r'\bANYMAIL_MANDRILL_API_KEY\b')
|
||||||
|
|
||||||
|
|
||||||
|
class MandrillBackendDeprecationTests(MandrillBackendMockAPITestCase):
|
||||||
|
@override_settings(EMAIL_BACKEND='anymail.backends.mandrill.MandrillBackend')
|
||||||
|
def test_renamed_backend_warning(self):
|
||||||
|
# ...mandrill.MandrillBackend --> ...mandrill.EmailBackend
|
||||||
|
with self.assertWarnsRegex(DeprecationWarning,
|
||||||
|
r'anymail\.backends\.mandrill\.EmailBackend'):
|
||||||
|
self.message.send()
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ MANDRILL_TEST_API_KEY = os.getenv('MANDRILL_TEST_API_KEY')
|
|||||||
@unittest.skipUnless(MANDRILL_TEST_API_KEY,
|
@unittest.skipUnless(MANDRILL_TEST_API_KEY,
|
||||||
"Set MANDRILL_TEST_API_KEY environment variable to run integration tests")
|
"Set MANDRILL_TEST_API_KEY environment variable to run integration tests")
|
||||||
@override_settings(MANDRILL_API_KEY=MANDRILL_TEST_API_KEY,
|
@override_settings(MANDRILL_API_KEY=MANDRILL_TEST_API_KEY,
|
||||||
EMAIL_BACKEND="anymail.backends.mandrill.MandrillBackend")
|
EMAIL_BACKEND="anymail.backends.mandrill.EmailBackend")
|
||||||
class MandrillBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
class MandrillBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Mandrill API integration tests
|
"""Mandrill API integration tests
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from .mock_requests_backend import RequestsBackendMockAPITestCase, SessionSharin
|
|||||||
from .utils import sample_image_content, sample_image_path, SAMPLE_IMAGE_FILENAME, AnymailTestMixin, decode_att
|
from .utils import sample_image_content, sample_image_path, SAMPLE_IMAGE_FILENAME, AnymailTestMixin, decode_att
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND='anymail.backends.postmark.PostmarkBackend',
|
@override_settings(EMAIL_BACKEND='anymail.backends.postmark.EmailBackend',
|
||||||
ANYMAIL={'POSTMARK_SERVER_TOKEN': 'test_server_token'})
|
ANYMAIL={'POSTMARK_SERVER_TOKEN': 'test_server_token'})
|
||||||
class PostmarkBackendMockAPITestCase(RequestsBackendMockAPITestCase):
|
class PostmarkBackendMockAPITestCase(RequestsBackendMockAPITestCase):
|
||||||
DEFAULT_RAW_RESPONSE = b"""{
|
DEFAULT_RAW_RESPONSE = b"""{
|
||||||
@@ -560,7 +560,7 @@ class PostmarkBackendSessionSharingTestCase(SessionSharingTestCasesMixin, Postma
|
|||||||
pass # tests are defined in the mixin
|
pass # tests are defined in the mixin
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND="anymail.backends.postmark.PostmarkBackend")
|
@override_settings(EMAIL_BACKEND="anymail.backends.postmark.EmailBackend")
|
||||||
class PostmarkBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
class PostmarkBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Test ESP backend without required settings in place"""
|
"""Test ESP backend without required settings in place"""
|
||||||
|
|
||||||
@@ -570,3 +570,12 @@ class PostmarkBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin)
|
|||||||
errmsg = str(cm.exception)
|
errmsg = str(cm.exception)
|
||||||
self.assertRegex(errmsg, r'\bPOSTMARK_SERVER_TOKEN\b')
|
self.assertRegex(errmsg, r'\bPOSTMARK_SERVER_TOKEN\b')
|
||||||
self.assertRegex(errmsg, r'\bANYMAIL_POSTMARK_SERVER_TOKEN\b')
|
self.assertRegex(errmsg, r'\bANYMAIL_POSTMARK_SERVER_TOKEN\b')
|
||||||
|
|
||||||
|
|
||||||
|
class PostmarkBackendDeprecationTests(PostmarkBackendMockAPITestCase):
|
||||||
|
@override_settings(EMAIL_BACKEND='anymail.backends.postmark.PostmarkBackend')
|
||||||
|
def test_renamed_backend_warning(self):
|
||||||
|
# ...postmark.PostmarkBackend --> ...postmark.EmailBackend
|
||||||
|
with self.assertWarnsRegex(DeprecationWarning,
|
||||||
|
r'anymail\.backends\.postmark\.EmailBackend'):
|
||||||
|
self.message.send()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from .utils import AnymailTestMixin, sample_image_path, RUN_LIVE_TESTS
|
|||||||
|
|
||||||
@unittest.skipUnless(RUN_LIVE_TESTS, "RUN_LIVE_TESTS disabled in this environment")
|
@unittest.skipUnless(RUN_LIVE_TESTS, "RUN_LIVE_TESTS disabled in this environment")
|
||||||
@override_settings(ANYMAIL_POSTMARK_SERVER_TOKEN="POSTMARK_API_TEST",
|
@override_settings(ANYMAIL_POSTMARK_SERVER_TOKEN="POSTMARK_API_TEST",
|
||||||
EMAIL_BACKEND="anymail.backends.postmark.PostmarkBackend")
|
EMAIL_BACKEND="anymail.backends.postmark.EmailBackend")
|
||||||
class PostmarkBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
class PostmarkBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Postmark API integration tests
|
"""Postmark API integration tests
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
|
||||||
from anymail.backends.test import TestBackend
|
from anymail.backends.test import EmailBackend as TestEmailBackend
|
||||||
from anymail.exceptions import AnymailCancelSend, AnymailRecipientsRefused
|
from anymail.exceptions import AnymailCancelSend, AnymailRecipientsRefused
|
||||||
from anymail.message import AnymailRecipientStatus
|
from anymail.message import AnymailRecipientStatus
|
||||||
from anymail.signals import pre_send, post_send
|
from anymail.signals import pre_send, post_send
|
||||||
@@ -16,9 +16,9 @@ class TestPreSendSignal(TestBackendTestCase):
|
|||||||
@receiver(pre_send, weak=False)
|
@receiver(pre_send, weak=False)
|
||||||
def handle_pre_send(sender, message, esp_name, **kwargs):
|
def handle_pre_send(sender, message, esp_name, **kwargs):
|
||||||
self.assertEqual(self.get_send_count(), 0) # not sent yet
|
self.assertEqual(self.get_send_count(), 0) # not sent yet
|
||||||
self.assertEqual(sender, TestBackend)
|
self.assertEqual(sender, TestEmailBackend)
|
||||||
self.assertEqual(message, self.message)
|
self.assertEqual(message, self.message)
|
||||||
self.assertEqual(esp_name, "Test") # the TestBackend's ESP is named "Test"
|
self.assertEqual(esp_name, "Test") # the TestEmailBackend's ESP is named "Test"
|
||||||
self.receiver_called = True
|
self.receiver_called = True
|
||||||
self.addCleanup(pre_send.disconnect, receiver=handle_pre_send)
|
self.addCleanup(pre_send.disconnect, receiver=handle_pre_send)
|
||||||
|
|
||||||
@@ -62,13 +62,13 @@ class TestPostSendSignal(TestBackendTestCase):
|
|||||||
@receiver(post_send, weak=False)
|
@receiver(post_send, weak=False)
|
||||||
def handle_post_send(sender, message, status, esp_name, **kwargs):
|
def handle_post_send(sender, message, status, esp_name, **kwargs):
|
||||||
self.assertEqual(self.get_send_count(), 1) # already sent
|
self.assertEqual(self.get_send_count(), 1) # already sent
|
||||||
self.assertEqual(sender, TestBackend)
|
self.assertEqual(sender, TestEmailBackend)
|
||||||
self.assertEqual(message, self.message)
|
self.assertEqual(message, self.message)
|
||||||
self.assertEqual(status.status, {'sent'})
|
self.assertEqual(status.status, {'sent'})
|
||||||
self.assertEqual(status.message_id, 1) # TestBackend default message_id
|
self.assertEqual(status.message_id, 1) # TestEmailBackend default message_id
|
||||||
self.assertEqual(status.recipients['to@example.com'].status, 'sent')
|
self.assertEqual(status.recipients['to@example.com'].status, 'sent')
|
||||||
self.assertEqual(status.recipients['to@example.com'].message_id, 1)
|
self.assertEqual(status.recipients['to@example.com'].message_id, 1)
|
||||||
self.assertEqual(esp_name, "Test") # the TestBackend's ESP is named "Test"
|
self.assertEqual(esp_name, "Test") # the TestEmailBackend's ESP is named "Test"
|
||||||
self.receiver_called = True
|
self.receiver_called = True
|
||||||
self.addCleanup(post_send.disconnect, receiver=handle_post_send)
|
self.addCleanup(post_send.disconnect, receiver=handle_post_send)
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from .mock_requests_backend import RequestsBackendMockAPITestCase, SessionSharin
|
|||||||
from .utils import sample_image_content, sample_image_path, SAMPLE_IMAGE_FILENAME, AnymailTestMixin
|
from .utils import sample_image_content, sample_image_path, SAMPLE_IMAGE_FILENAME, AnymailTestMixin
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND='anymail.backends.sendgrid.SendGridBackend',
|
@override_settings(EMAIL_BACKEND='anymail.backends.sendgrid.EmailBackend',
|
||||||
ANYMAIL={'SENDGRID_API_KEY': 'test_api_key'})
|
ANYMAIL={'SENDGRID_API_KEY': 'test_api_key'})
|
||||||
class SendGridBackendMockAPITestCase(RequestsBackendMockAPITestCase):
|
class SendGridBackendMockAPITestCase(RequestsBackendMockAPITestCase):
|
||||||
DEFAULT_RAW_RESPONSE = b"" # SendGrid v3 success responses are empty
|
DEFAULT_RAW_RESPONSE = b"" # SendGrid v3 success responses are empty
|
||||||
@@ -619,7 +619,7 @@ class SendGridBackendSessionSharingTestCase(SessionSharingTestCasesMixin, SendGr
|
|||||||
pass # tests are defined in the mixin
|
pass # tests are defined in the mixin
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND="anymail.backends.sendgrid.SendGridBackend")
|
@override_settings(EMAIL_BACKEND="anymail.backends.sendgrid.EmailBackend")
|
||||||
class SendGridBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
class SendGridBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Test ESP backend without required settings in place"""
|
"""Test ESP backend without required settings in place"""
|
||||||
|
|
||||||
@@ -628,7 +628,7 @@ class SendGridBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin)
|
|||||||
mail.send_mail('Subject', 'Message', 'from@example.com', ['to@example.com'])
|
mail.send_mail('Subject', 'Message', 'from@example.com', ['to@example.com'])
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND="anymail.backends.sendgrid.SendGridBackend")
|
@override_settings(EMAIL_BACKEND="anymail.backends.sendgrid.EmailBackend")
|
||||||
class SendGridBackendDisallowsV2Tests(SimpleTestCase, AnymailTestMixin):
|
class SendGridBackendDisallowsV2Tests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Using v2-API-only features should cause errors with v3 backend"""
|
"""Using v2-API-only features should cause errors with v3 backend"""
|
||||||
|
|
||||||
@@ -645,3 +645,12 @@ class SendGridBackendDisallowsV2Tests(SimpleTestCase, AnymailTestMixin):
|
|||||||
message.esp_extra = {'x-smtpapi': {'asm_group_id': 1}}
|
message.esp_extra = {'x-smtpapi': {'asm_group_id': 1}}
|
||||||
with self.assertRaisesRegex(AnymailConfigurationError, r'\bsendgrid_v2\.EmailBackend\b'):
|
with self.assertRaisesRegex(AnymailConfigurationError, r'\bsendgrid_v2\.EmailBackend\b'):
|
||||||
message.send()
|
message.send()
|
||||||
|
|
||||||
|
|
||||||
|
class SendGridBackendDeprecationTests(SendGridBackendMockAPITestCase):
|
||||||
|
@override_settings(EMAIL_BACKEND='anymail.backends.sendgrid.SendGridBackend')
|
||||||
|
def test_renamed_backend_warning(self):
|
||||||
|
# ...sendgrid.SendGridBackend --> ...sendgrid.EmailBackend
|
||||||
|
with self.assertWarnsRegex(DeprecationWarning,
|
||||||
|
r'anymail\.backends\.sendgrid\.EmailBackend'):
|
||||||
|
self.message.send()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ SENDGRID_TEST_TEMPLATE_ID = os.getenv('SENDGRID_TEST_TEMPLATE_ID')
|
|||||||
ANYMAIL_SENDGRID_SEND_DEFAULTS={"esp_extra": {
|
ANYMAIL_SENDGRID_SEND_DEFAULTS={"esp_extra": {
|
||||||
"mail_settings": {"sandbox_mode": {"enable": True}},
|
"mail_settings": {"sandbox_mode": {"enable": True}},
|
||||||
}},
|
}},
|
||||||
EMAIL_BACKEND="anymail.backends.sendgrid.SendGridBackend")
|
EMAIL_BACKEND="anymail.backends.sendgrid.EmailBackend")
|
||||||
class SendGridBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
class SendGridBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""SendGrid v3 API integration tests
|
"""SendGrid v3 API integration tests
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from anymail.message import attach_inline_image_file
|
|||||||
from .utils import AnymailTestMixin, decode_att, SAMPLE_IMAGE_FILENAME, sample_image_path, sample_image_content
|
from .utils import AnymailTestMixin, decode_att, SAMPLE_IMAGE_FILENAME, sample_image_path, sample_image_content
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND='anymail.backends.sparkpost.SparkPostBackend',
|
@override_settings(EMAIL_BACKEND='anymail.backends.sparkpost.EmailBackend',
|
||||||
ANYMAIL={'SPARKPOST_API_KEY': 'test_api_key'})
|
ANYMAIL={'SPARKPOST_API_KEY': 'test_api_key'})
|
||||||
class SparkPostBackendMockAPITestCase(SimpleTestCase, AnymailTestMixin):
|
class SparkPostBackendMockAPITestCase(SimpleTestCase, AnymailTestMixin):
|
||||||
"""TestCase that uses SparkPostEmailBackend with a mocked transmissions.send API"""
|
"""TestCase that uses SparkPostEmailBackend with a mocked transmissions.send API"""
|
||||||
@@ -559,7 +559,7 @@ class SparkPostBackendRecipientsRefusedTests(SparkPostBackendMockAPITestCase):
|
|||||||
self.assertEqual(sent, 1) # refused message is included in sent count
|
self.assertEqual(sent, 1) # refused message is included in sent count
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND="anymail.backends.sparkpost.SparkPostBackend")
|
@override_settings(EMAIL_BACKEND="anymail.backends.sparkpost.EmailBackend")
|
||||||
class SparkPostBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
class SparkPostBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""Test ESP backend without required settings in place"""
|
"""Test ESP backend without required settings in place"""
|
||||||
|
|
||||||
@@ -580,3 +580,12 @@ class SparkPostBackendImproperlyConfiguredTests(SimpleTestCase, AnymailTestMixin
|
|||||||
# Poke into implementation details to verify:
|
# Poke into implementation details to verify:
|
||||||
self.assertIsNone(conn.api_key) # Anymail prop
|
self.assertIsNone(conn.api_key) # Anymail prop
|
||||||
self.assertEqual(conn.sp.api_key, 'key_from_environment') # SparkPost prop
|
self.assertEqual(conn.sp.api_key, 'key_from_environment') # SparkPost prop
|
||||||
|
|
||||||
|
|
||||||
|
class SparkPostBackendDeprecationTests(SparkPostBackendMockAPITestCase):
|
||||||
|
@override_settings(EMAIL_BACKEND='anymail.backends.sparkpost.SparkPostBackend')
|
||||||
|
def test_renamed_backend_warning(self):
|
||||||
|
# ...sparkpost.SparkPostBackend --> ...sparkpost.EmailBackend
|
||||||
|
with self.assertWarnsRegex(DeprecationWarning,
|
||||||
|
r'anymail\.backends\.sparkpost\.EmailBackend'):
|
||||||
|
self.message.send()
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ SPARKPOST_TEST_API_KEY = os.getenv('SPARKPOST_TEST_API_KEY')
|
|||||||
"Set SPARKPOST_TEST_API_KEY environment variable "
|
"Set SPARKPOST_TEST_API_KEY environment variable "
|
||||||
"to run SparkPost integration tests")
|
"to run SparkPost integration tests")
|
||||||
@override_settings(ANYMAIL_SPARKPOST_API_KEY=SPARKPOST_TEST_API_KEY,
|
@override_settings(ANYMAIL_SPARKPOST_API_KEY=SPARKPOST_TEST_API_KEY,
|
||||||
EMAIL_BACKEND="anymail.backends.sparkpost.SparkPostBackend")
|
EMAIL_BACKEND="anymail.backends.sparkpost.EmailBackend")
|
||||||
class SparkPostBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
class SparkPostBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
|
||||||
"""SparkPost API integration tests
|
"""SparkPost API integration tests
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user