Skip to content

Commit

Permalink
Support EU region endpoint (#131)
Browse files Browse the repository at this point in the history
* Add SENDGRID_HOST_URL setting to fix #129

* Bump mypy and add type check to fix issue

* Remove unused import from test

* Set mypy to 1.4.1

* Add https:// to API url

* Add seperate TESTING_SENDGRID_EU_API_KEY for testing EU sub accounts

* Pass EU settings var to workflow

* Update tox config to pass TESTING_SENDGRID_EU_API_KEY to envs

---------

Co-authored-by: Steven Sklar <[email protected]>
  • Loading branch information
mikemanger and sklarsa authored Nov 26, 2024
1 parent b7f11f9 commit bcfa80e
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 10 deletions.
1 change: 1 addition & 0 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ jobs:
- name: Test with tox
env:
SENDGRID_API_KEY: ${{ secrets.SENDGRID_API_KEY }}
TESTING_SENDGRID_EU_API_KEY: ${{ secrets.TESTING_SENDGRID_EU_API_KEY }}
run: tox
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ To use the backend, simply install the package (using pip), set the `EMAIL_BACKE

1. To toggle sandbox mode (when django is running in DEBUG mode), set `SENDGRID_SANDBOX_MODE_IN_DEBUG = True/False`.
1. To err on the side of caution, this defaults to True, so emails sent in DEBUG mode will not be delivered, unless this setting is explicitly set to False.
2. `SENDGRID_ECHO_TO_STDOUT` will echo to stdout or any other file-like
1. `SENDGRID_ECHO_TO_STDOUT` will echo to stdout or any other file-like
object that is passed to the backend via the `stream` kwarg.
3. `SENDGRID_TRACK_EMAIL_OPENS` - defaults to true and tracks email open events via the Sendgrid service. These events are logged in the Statistics UI, Email Activity interface, and are reported by the Event Webhook.
4. `SENDGRID_TRACK_CLICKS_HTML` - defaults to true and, if enabled in your Sendgrid account, will tracks click events on links found in the HTML message sent.
5. `SENDGRID_TRACK_CLICKS_PLAIN` - defaults to true and, if enabled in your Sendgrid account, will tracks click events on links found in the plain text message sent.
1. `SENDGRID_TRACK_EMAIL_OPENS` - defaults to true and tracks email open events via the Sendgrid service. These events are logged in the Statistics UI, Email Activity interface, and are reported by the Event Webhook.
1. `SENDGRID_TRACK_CLICKS_HTML` - defaults to true and, if enabled in your Sendgrid account, will tracks click events on links found in the HTML message sent.
1. `SENDGRID_TRACK_CLICKS_PLAIN` - defaults to true and, if enabled in your Sendgrid account, will tracks click events on links found in the plain text message sent.
1. `SENDGRID_HOST_URL` - Allows changing the base API URI. Set to `https://api.eu.sendgrid.com` to use the EU region.

## Usage

Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ legacy_tox_ini = """
commands =
pytest ./test --cov=sendgrid_backend
passenv =
pass_env =
SENDGRID_API_KEY
TESTING_SENDGRID_EU_API_KEY
"""
17 changes: 14 additions & 3 deletions sendgrid_backend/mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,24 @@ def __init__(self, *args, **kwargs):
# or passed as an argument to the init function, which takes precedence
# over the setting.

sg_args = {}
if "api_key" in kwargs:
self.sg = SendGridAPIClient(api_key=kwargs["api_key"])
sg_args["api_key"] = kwargs["api_key"]
elif hasattr(settings, "SENDGRID_API_KEY") and settings.SENDGRID_API_KEY:
self.sg = SendGridAPIClient(api_key=settings.SENDGRID_API_KEY)
sg_args["api_key"] = settings.SENDGRID_API_KEY
else:
raise ImproperlyConfigured(
"settings.py must contain a value for SENDGRID_API_KEY. "
+ "You may also pass a value to the api_key argument (optional)."
)

if "host" in kwargs:
sg_args["host"] = kwargs["host"]
elif hasattr(settings, "SENDGRID_HOST_URL") and settings.SENDGRID_HOST_URL:
sg_args["host"] = settings.SENDGRID_HOST_URL

self.sg = SendGridAPIClient(**sg_args)

# Configure sandbox mode based on settings
sandbox_mode_in_debug = get_django_setting(
"SENDGRID_SANDBOX_MODE_IN_DEBUG", True
Expand Down Expand Up @@ -212,7 +220,10 @@ def set_prop(attachment, prop_name, value):
filename = f"part-{uuid.uuid4().hex}{ext}"
set_prop(sg_attch, "filename", filename)
# todo: Read content if stream?
set_prop(sg_attch, "content", django_attch.get_payload().replace("\n", ""))
payload = django_attch.get_payload()
if isinstance(payload, str):
payload = payload.replace("\n", "")
set_prop(sg_attch, "content", payload)

# Content-type handling. Includes the 'method' param.
content_type = django_attch.get_content_type()
Expand Down
1 change: 0 additions & 1 deletion test/test_mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
Header,
MailSettings,
Personalization,
SpamCheck,
Substitution,
TrackingSettings,
)
Expand Down
33 changes: 32 additions & 1 deletion test/test_post_to_sendgrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TestPostToSendgrid(SimpleTestCase):
)
def test_post(self):
"""
Sends a POST to sendgrid's live API using a private API key that is stored
Sends a POST to SendGrid's live API using a private API key that is stored
in github.
"""

Expand All @@ -35,3 +35,34 @@ def test_post(self):
)
val = msg.send()
self.assertEqual(val, 1)

# TESTING_SENDGRID_EU_API_KEY is only used for testing.
@pytest.mark.skipif(
not os.environ.get("TESTING_SENDGRID_EU_API_KEY"),
reason="requires TESTING_SENDGRID_EU_API_KEY env var",
)
def test_eu_post(self):
"""
Sends a POST to SendGrid's live EU API using a private API key that is stored
in GitHub.
"""

SENDGRID_API_KEY = os.environ.get("TESTING_SENDGRID_EU_API_KEY")

# Set DEBUG=True so sandbox mode is enabled
settings = {
"DEBUG": True,
"SENDGRID_API_KEY": SENDGRID_API_KEY,
"SENDGRID_HOST_URL": "https://api.eu.sendgrid.com",
"EMAIL_BACKEND": "sendgrid_backend.SendgridBackend",
}

with override_settings(**settings):
msg = EmailMessage(
subject="Hello, World!",
body="Hello, World!",
from_email="Sam Smith <[email protected]>",
to=["John Doe <[email protected]>"],
)
val = msg.send()
self.assertEqual(val, 1)

0 comments on commit bcfa80e

Please sign in to comment.