feat(enterprise): add RESEND_FROM_EMAIL for self-hosted Resend sends (#28830)

Allow self-hosted installs to override the default LiteLLM sender address
via RESEND_FROM_EMAIL, matching SendGrid's SENDGRID_SENDER_EMAIL pattern.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Shivam Rawat
2026-05-30 10:09:05 -07:00
committed by GitHub
co-authored by Cursor
parent 4cc3dd7aad
commit 967fed1fa1
2 changed files with 88 additions and 7 deletions
@@ -19,12 +19,26 @@ RESEND_API_ENDPOINT = "https://api.resend.com/emails"
class ResendEmailLogger(BaseEmailLogger):
"""
Send emails using Resend's API.
Required env vars:
- RESEND_API_KEY
Optional env vars:
- RESEND_FROM_EMAIL: Override the default sender address. Must be on a
domain verified in your Resend account. When unset, falls back to the
`from_email` argument passed by the caller (which defaults to
`notifications@alerts.litellm.ai` and only works on LiteLLM Cloud).
"""
def __init__(self, internal_usage_cache=None, **kwargs):
super().__init__(internal_usage_cache=internal_usage_cache, **kwargs)
self.async_httpx_client = get_async_httpx_client(
llm_provider=httpxSpecialProvider.LoggingCallback
)
self.resend_api_key = os.getenv("RESEND_API_KEY")
self.resend_from_email = os.getenv("RESEND_FROM_EMAIL")
async def send_email(
self,
@@ -33,13 +47,14 @@ class ResendEmailLogger(BaseEmailLogger):
subject: str,
html_body: str,
):
sender_email = self.resend_from_email or from_email
verbose_logger.debug(
f"Sending email from {from_email} to {to_email} with subject {subject}"
f"Sending email from {sender_email} to {to_email} with subject {subject}"
)
response = await self.async_httpx_client.post(
url=RESEND_API_ENDPOINT,
json={
"from": from_email,
"from": sender_email,
"to": to_email,
"subject": subject,
"html": html_body,
@@ -32,7 +32,11 @@ def clear_client_cache():
@pytest.fixture
def mock_env_vars():
with mock.patch.dict(os.environ, {"RESEND_API_KEY": "test_api_key"}):
# Set test API key and ensure RESEND_FROM_EMAIL is unset for isolation
# so tests can verify the default `from_email` argument is used.
patched = {"RESEND_API_KEY": "test_api_key"}
with mock.patch.dict(os.environ, patched):
os.environ.pop("RESEND_FROM_EMAIL", None)
yield
@@ -87,7 +91,7 @@ async def test_send_email_success(mock_env_vars):
async def test_send_email_missing_api_key():
# Remove the API key from environment before initializing logger
original_key = os.environ.pop("RESEND_API_KEY", None)
try:
# Initialize the logger after removing the API key
logger = ResendEmailLogger()
@@ -104,16 +108,19 @@ async def test_send_email_missing_api_key():
mock_response.raise_for_status.return_value = None
mock_response.status_code = 200
mock_response.json.return_value = {"id": "test_email_id"}
mock_async_client = mock.AsyncMock()
mock_async_client.post.return_value = mock_response
# Directly inject the mock client to bypass any caching
logger.async_httpx_client = mock_async_client
# Send email
await logger.send_email(
from_email=from_email, to_email=to_email, subject=subject, html_body=html_body
from_email=from_email,
to_email=to_email,
subject=subject,
html_body=html_body,
)
# Verify the HTTP client was called with None as the API key
@@ -159,3 +166,62 @@ async def test_send_email_multiple_recipients(mock_env_vars):
call_args = mock_async_client.post.call_args
request_body = call_args[1]["json"]
assert request_body["to"] == to_email
@pytest.mark.asyncio
async def test_send_email_uses_resend_from_email_override():
"""RESEND_FROM_EMAIL overrides the caller-supplied from_email."""
with mock.patch.dict(
os.environ,
{
"RESEND_API_KEY": "test_api_key",
"RESEND_FROM_EMAIL": "alerts@my-verified-domain.com",
},
):
logger = ResendEmailLogger()
mock_response = mock.Mock(spec=Response)
mock_response.status_code = 200
mock_response.json.return_value = {"id": "test_email_id"}
mock_response.raise_for_status.return_value = None
mock_async_client = mock.AsyncMock()
mock_async_client.post.return_value = mock_response
logger.async_httpx_client = mock_async_client
await logger.send_email(
from_email="notifications@alerts.litellm.ai",
to_email=["recipient@example.com"],
subject="Test Subject",
html_body="<p>Test email body</p>",
)
mock_async_client.post.assert_called_once()
request_body = mock_async_client.post.call_args[1]["json"]
assert request_body["from"] == "alerts@my-verified-domain.com"
@pytest.mark.asyncio
async def test_send_email_falls_back_to_argument_when_override_unset(mock_env_vars):
"""When RESEND_FROM_EMAIL is unset, the caller-supplied from_email is used."""
logger = ResendEmailLogger()
mock_response = mock.Mock(spec=Response)
mock_response.status_code = 200
mock_response.json.return_value = {"id": "test_email_id"}
mock_response.raise_for_status.return_value = None
mock_async_client = mock.AsyncMock()
mock_async_client.post.return_value = mock_response
logger.async_httpx_client = mock_async_client
await logger.send_email(
from_email="notifications@alerts.litellm.ai",
to_email=["recipient@example.com"],
subject="Test Subject",
html_body="<p>Test email body</p>",
)
mock_async_client.post.assert_called_once()
request_body = mock_async_client.post.call_args[1]["json"]
assert request_body["from"] == "notifications@alerts.litellm.ai"