fix(brevo): passer X-Sib-Sandbox dans le body email, pas en header HTTP (#87)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -16,8 +16,7 @@ def init_mailer() -> None:
|
|||||||
"""Construit le client Brevo à partir des variables d'environnement."""
|
"""Construit le client Brevo à partir des variables d'environnement."""
|
||||||
global _client
|
global _client
|
||||||
api_key = os.getenv("BREVO_API_KEY", "")
|
api_key = os.getenv("BREVO_API_KEY", "")
|
||||||
headers = {"X-Sib-Sandbox": "drop"} if DEVELOPMENT else None
|
_client = Brevo(api_key=api_key)
|
||||||
_client = Brevo(api_key=api_key, headers=headers)
|
|
||||||
|
|
||||||
|
|
||||||
def _base_url() -> str:
|
def _base_url() -> str:
|
||||||
@@ -40,12 +39,14 @@ def _template_id(env_var: str) -> int:
|
|||||||
|
|
||||||
def _send_template(template_id: int, recipient: str, params: dict) -> None:
|
def _send_template(template_id: int, recipient: str, params: dict) -> None:
|
||||||
assert _client is not None, "Mailer non initialisé (init_mailer() non appelé)"
|
assert _client is not None, "Mailer non initialisé (init_mailer() non appelé)"
|
||||||
|
sandbox_headers = {"X-Sib-Sandbox": "drop"} if DEVELOPMENT else None
|
||||||
try:
|
try:
|
||||||
_client.transactional_emails.send_transac_email(
|
_client.transactional_emails.send_transac_email(
|
||||||
template_id=template_id,
|
template_id=template_id,
|
||||||
params=params,
|
params=params,
|
||||||
sender=_sender(),
|
sender=_sender(),
|
||||||
to=[SendTransacEmailRequestToItem(email=recipient)],
|
to=[SendTransacEmailRequestToItem(email=recipient)],
|
||||||
|
headers=sandbox_headers,
|
||||||
)
|
)
|
||||||
except ApiError:
|
except ApiError:
|
||||||
logger.exception(
|
logger.exception(
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ def test_send_verification_email(fake_client):
|
|||||||
assert call["to"][0].email == "a@b.c"
|
assert call["to"][0].email == "a@b.c"
|
||||||
assert call["sender"].email == "noreply@decp.info"
|
assert call["sender"].email == "noreply@decp.info"
|
||||||
assert "/auth/verify-email?token=TOKEN123" in call["params"]["link"]
|
assert "/auth/verify-email?token=TOKEN123" in call["params"]["link"]
|
||||||
|
assert call["headers"] == {"X-Sib-Sandbox": "drop"} # DEVELOPMENT=true en tests
|
||||||
|
|
||||||
|
|
||||||
def test_send_reset_email(fake_client):
|
def test_send_reset_email(fake_client):
|
||||||
|
|||||||
@@ -215,6 +215,21 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" },
|
{ url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "brevo-python"
|
||||||
|
version = "5.0.0rc1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "httpx" },
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "pydantic-core" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5a/70/4aee9ce897335397cfa03cdda512a8f55b31bb88da955f88b886db25a2d4/brevo_python-5.0.0rc1.tar.gz", hash = "sha256:7380e5d536240a4d15085bec5b3a311dcb8276b9b940b43a694c56aa7b057657", size = 492696, upload-time = "2026-05-15T09:09:25.307Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/db/c29a5593fde4675e2984ff2330d3abf17a044704e78cebb044baacfba85d/brevo_python-5.0.0rc1-py3-none-any.whl", hash = "sha256:52d522c75af386efd4035f29214c2305933005bd46891b2334a0c21f8b6cdfeb", size = 961955, upload-time = "2026-05-15T09:09:23.889Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "brotli"
|
name = "brotli"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@@ -811,6 +826,7 @@ name = "decp-info"
|
|||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
{ name = "brevo-python" },
|
||||||
{ name = "dash", extra = ["compress"] },
|
{ name = "dash", extra = ["compress"] },
|
||||||
{ name = "dash-bootstrap-components" },
|
{ name = "dash-bootstrap-components" },
|
||||||
{ name = "dash-extensions", version = "1.0.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
{ name = "dash-extensions", version = "1.0.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
||||||
@@ -822,7 +838,6 @@ dependencies = [
|
|||||||
{ name = "flask-caching" },
|
{ name = "flask-caching" },
|
||||||
{ name = "flask-cors" },
|
{ name = "flask-cors" },
|
||||||
{ name = "flask-login" },
|
{ name = "flask-login" },
|
||||||
{ name = "flask-mail" },
|
|
||||||
{ name = "flask-smorest" },
|
{ name = "flask-smorest" },
|
||||||
{ name = "flask-wtf" },
|
{ name = "flask-wtf" },
|
||||||
{ name = "gunicorn" },
|
{ name = "gunicorn" },
|
||||||
@@ -852,6 +867,7 @@ dev = [
|
|||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
|
{ name = "brevo-python", specifier = "==5.0.0rc1" },
|
||||||
{ name = "dash", specifier = "==3.4.0" },
|
{ name = "dash", specifier = "==3.4.0" },
|
||||||
{ name = "dash", extras = ["compress"] },
|
{ name = "dash", extras = ["compress"] },
|
||||||
{ name = "dash-bootstrap-components" },
|
{ name = "dash-bootstrap-components" },
|
||||||
@@ -862,7 +878,6 @@ requires-dist = [
|
|||||||
{ name = "flask-caching" },
|
{ name = "flask-caching" },
|
||||||
{ name = "flask-cors", specifier = ">=6.0.2" },
|
{ name = "flask-cors", specifier = ">=6.0.2" },
|
||||||
{ name = "flask-login" },
|
{ name = "flask-login" },
|
||||||
{ name = "flask-mail" },
|
|
||||||
{ name = "flask-smorest", specifier = ">=0.46.0" },
|
{ name = "flask-smorest", specifier = ">=0.46.0" },
|
||||||
{ name = "flask-wtf" },
|
{ name = "flask-wtf" },
|
||||||
{ name = "gunicorn" },
|
{ name = "gunicorn" },
|
||||||
@@ -1105,19 +1120,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/59/f5/67e9cc5c2036f58115f9fe0f00d203cf6780c3ff8ae0e705e7a9d9e8ff9e/Flask_Login-0.6.3-py3-none-any.whl", hash = "sha256:849b25b82a436bf830a054e74214074af59097171562ab10bfa999e6b78aae5d", size = 17303, upload-time = "2023-10-30T14:53:19.636Z" },
|
{ url = "https://files.pythonhosted.org/packages/59/f5/67e9cc5c2036f58115f9fe0f00d203cf6780c3ff8ae0e705e7a9d9e8ff9e/Flask_Login-0.6.3-py3-none-any.whl", hash = "sha256:849b25b82a436bf830a054e74214074af59097171562ab10bfa999e6b78aae5d", size = 17303, upload-time = "2023-10-30T14:53:19.636Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flask-mail"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "blinker" },
|
|
||||||
{ name = "flask" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ba/29/e92dc84c675d1e8d260d5768eb3fb65c70cbd33addecf424187587bee862/flask_mail-0.10.0.tar.gz", hash = "sha256:44083e7b02bbcce792209c06252f8569dd5a325a7aaa76afe7330422bd97881d", size = 8152, upload-time = "2024-05-23T22:30:12.612Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e4/c0/a81083da779f482494d49195d8b6c9fde21072558253e4a9fb2ec969c3c1/flask_mail-0.10.0-py3-none-any.whl", hash = "sha256:a451e490931bb3441d9b11ebab6812a16bfa81855792ae1bf9c1e1e22c4e51e7", size = 8529, upload-time = "2024-05-23T22:30:10.962Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flask-smorest"
|
name = "flask-smorest"
|
||||||
version = "0.47.0"
|
version = "0.47.0"
|
||||||
@@ -2049,30 +2051,30 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polars"
|
name = "polars"
|
||||||
version = "1.41.2"
|
version = "1.42.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "polars-runtime-32" },
|
{ name = "polars-runtime-32" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ff/f9/aeda46259b0669247a160315d2d51269de9504b9dd2f70acadbcb22f46b7/polars-1.41.2.tar.gz", hash = "sha256:256d6731162371b77f3f29a55eacb8c0fc740ddb1a293a01d2ef5b5393c5c708", size = 737996, upload-time = "2026-05-29T17:39:15.604Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/cb/91/a1d7809a6d399f0aa78d4d3a4f4daf411cb97ccfe7f236c08a01be5fc8a5/polars-1.42.0.tar.gz", hash = "sha256:283ddc923e47857924fbef36580d2e98d984a47c962bae4cbce9c0ebcc98989c", size = 740984, upload-time = "2026-06-24T05:20:13.727Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/1f/22/28f62d24f7db56ac4343588f9362d49b7b4177e55ac47a466fe696b0099b/polars-1.41.2-py3-none-any.whl", hash = "sha256:23ce9a2910b6e3e8d4258770bf44aa17170958df7af6e85feedf4458a04d8d29", size = 833445, upload-time = "2026-05-29T17:37:05.576Z" },
|
{ url = "https://files.pythonhosted.org/packages/08/4d/094819d251f2248999cb722125fd4e44ee79b753fe535338cbf442fbf45d/polars-1.42.0-py3-none-any.whl", hash = "sha256:ab10cac3f2d28a6e22e22bcac69c0e51fb33cd25aee1f45105782d4fe55a3e6a", size = 836855, upload-time = "2026-06-24T05:18:18.204Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polars-runtime-32"
|
name = "polars-runtime-32"
|
||||||
version = "1.41.2"
|
version = "1.42.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f9/56/54e3ea0e9b64f327179049e4742241cc6b1d3e8fa414b05a057dd26df367/polars_runtime_32-1.41.2.tar.gz", hash = "sha256:7af09ec1ab053da2c9669e8d15f809a4083a29be05db57111688b8051062af56", size = 2989474, upload-time = "2026-05-29T17:39:17.257Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/05/67/20759e9abbc61910cf948f5c28986ab25ef9e8009099b469d64d6a34a478/polars_runtime_32-1.42.0.tar.gz", hash = "sha256:c927e1930881fe0bf9629d12e5d44ebd4ecef2bfa02374dfc79feaa24054394f", size = 3042711, upload-time = "2026-06-24T05:20:15.715Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/d6/9b/fe72a3811c0357cdb06c67bdc7695fa1623ad47948fc523195f5ac31037f/polars_runtime_32-1.41.2-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:95a08346dac337357cdb825c8076df7d36da54c4caa59a5cb41d0a30691c5edd", size = 52265283, upload-time = "2026-05-29T17:37:09.407Z" },
|
{ url = "https://files.pythonhosted.org/packages/1c/62/8b83fca67d478e4a2b88cbba2fbff4d533052938ff96d598b7915fd9d235/polars_runtime_32-1.42.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:d235a5e8349797c16b70ad573fb9ddbd7f162796884bcbd25260908f8408affc", size = 53112358, upload-time = "2026-06-24T05:18:22.275Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0a/93/fab9da803fd80d9e83ef88c20932f637a10bc611b20415fc322eec84bc44/polars_runtime_32-1.41.2-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:dedfaeec2c7f995298da7319dd9431d662e5dd1d0ec51b1459df4a0234ceff52", size = 46571222, upload-time = "2026-05-29T17:37:13.698Z" },
|
{ url = "https://files.pythonhosted.org/packages/cf/72/06d3d78b7e8e8d3c72ea9eee310950334d50986462b3c1d40f82972495a5/polars_runtime_32-1.42.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:e7923db3bcb57e0edecde3be28629e0411414a15ef1a4c10c783ac5eadab2e1e", size = 47443757, upload-time = "2026-06-24T05:18:26.326Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c8/2a/8843f34a8ac57acd058a39b87b03b580dd352a490e9dae0415e02033bdd4/polars_runtime_32-1.41.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18eea22c5cc34e27f8a60950458ad81e6a9ea75e89363ca1367e14e7e7f781fc", size = 50409372, upload-time = "2026-05-29T17:37:17.875Z" },
|
{ url = "https://files.pythonhosted.org/packages/5a/77/20241aaf919a0f63b946fb702bc14447db290ef918e2c2943ed90d50fcc1/polars_runtime_32-1.42.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42e27e2eb5909abcedb4ab4cc04ee67c5ec2b73a5640ebd8739b1b719383fa68", size = 51360855, upload-time = "2026-06-24T05:18:30.709Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6c/c6/92b352fe88cf51bd0a19fb99e1c0cbe46aa26c14dcf7995b89869cd932ae/polars_runtime_32-1.41.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2630540dfdfb0f36f9b04a07c7c2e3f50bf2ad384113263c1c812007ee9141e0", size = 56405484, upload-time = "2026-05-29T17:37:22.684Z" },
|
{ url = "https://files.pythonhosted.org/packages/46/5c/ca14606a42628b04d82ac6ae5742ed24048bd43fbf48ae87fc4f4b9e759d/polars_runtime_32-1.42.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a3c43d4a76360bf912f8772b5ac1c23d5a8efef71408c63bba1bb0b4897a8ea", size = 57299346, upload-time = "2026-06-24T05:18:35.374Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/74/c4/bae3174c3b02f6b441d2e58594387abcd509f67a098f682a83b195f08966/polars_runtime_32-1.41.2-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:20e969e08f9b137e233c04cc04de73d9795f89eb77d34854e40a025965a43763", size = 50603512, upload-time = "2026-05-29T17:37:27.422Z" },
|
{ url = "https://files.pythonhosted.org/packages/9c/af/3ad0de43bbb97e91d605d7d76acb30be36269b8a8402890ab4f9892b6e26/polars_runtime_32-1.42.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:542a77b2b969e5157939bfb76cd0f372c4f42db6ccd58636fcefe0011162a418", size = 51512143, upload-time = "2026-06-24T05:18:39.771Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f4/ed/f2d26ae02d92c2689056838ed59e2a626326ad23c2831d58637d25f6c82a/polars_runtime_32-1.41.2-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e7016a3deb641b64a31447abbbee0f34bd020a6a9ae34ee6b743837def15e2a4", size = 54328561, upload-time = "2026-05-29T17:37:32.587Z" },
|
{ url = "https://files.pythonhosted.org/packages/b2/a5/d1133ba9d005532a6fb94544f5da09e497a8fe42c04e37c3da6faa80bd67/polars_runtime_32-1.42.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a13949abfce319de7fc4c1abee43bc9d4a4ed4d96bcc1a6037d022e4e9561d9f", size = 55214521, upload-time = "2026-06-24T05:18:43.916Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/c4/9c3831cc885dc7769e59abf8f583821a5fb4403fd0e4eba0ccc6d47a3d4b/polars_runtime_32-1.41.2-cp310-abi3-win_amd64.whl", hash = "sha256:1e5e5377c315e0dcafdfb2a31adc546abbaeb3f9cb1864e6536523d2af473265", size = 51978643, upload-time = "2026-05-29T17:37:37.443Z" },
|
{ url = "https://files.pythonhosted.org/packages/bd/54/0b8355ab29669560608b2864a5e54674dd78bbd48c04976607516e081107/polars_runtime_32-1.42.0-cp310-abi3-win_amd64.whl", hash = "sha256:91a07bd852c1d1ea19b3e27c974bc7b1b29ac948fdb2e785da3a6ec0f0683cad", size = 52718509, upload-time = "2026-06-24T05:18:48.202Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/cd/c6/79e9f3f270270d7ed5575d92b7bfef49f01abd9275447161275b23b553a8/polars_runtime_32-1.41.2-cp310-abi3-win_arm64.whl", hash = "sha256:843d96f69d18eca53429c1198e58891db7f18111f83b9c419bb45ad9d73eaed5", size = 46006901, upload-time = "2026-05-29T17:37:42.522Z" },
|
{ url = "https://files.pythonhosted.org/packages/bf/b9/7c46fdbd1dbbaaf77f9512d7665609d7e4c4d8c8849edb9a16c471041075/polars_runtime_32-1.42.0-cp310-abi3-win_arm64.whl", hash = "sha256:b7c5d7721b7bb2563d72785050ac099da1e2000d412f9c72a0cfb7b07779e75d", size = 46728464, upload-time = "2026-06-24T05:18:52.505Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
Reference in New Issue
Block a user