diff --git a/api/ee/src/services/organization_service.py b/api/ee/src/services/organization_service.py index 5378008ae3..fb3ccaa745 100644 --- a/api/ee/src/services/organization_service.py +++ b/api/ee/src/services/organization_service.py @@ -104,8 +104,8 @@ async def send_invitation_email( f"&project_id={project_param}" ) - # If Sendgrid is not configured, return the link for manual sharing (URL-based invitation) - if not env.sendgrid.enabled: + # If email delivery is not configured, return the link for manual sharing. + if not (env.smtp.enabled or env.sendgrid.enabled): return invite_link html_content = html_template.format( diff --git a/api/oss/src/core/auth/supertokens/config.py b/api/oss/src/core/auth/supertokens/config.py index 80b0d34668..eb8286222b 100644 --- a/api/oss/src/core/auth/supertokens/config.py +++ b/api/oss/src/core/auth/supertokens/config.py @@ -2,6 +2,11 @@ from urllib.parse import urlparse from supertokens_python import init, InputAppInfo, SupertokensConfig +from supertokens_python.ingredients.emaildelivery.types import ( + EmailDeliveryConfig, + SMTPSettings, + SMTPSettingsFrom, +) from supertokens_python.recipe import ( emailpassword, passwordless, @@ -58,6 +63,32 @@ def get_supertokens_config() -> Dict[str, Any]: } +def get_passwordless_email_delivery(): + """Route passwordless OTP emails through SMTP when SMTP is configured.""" + if not env.smtp.enabled: + return None + + if not env.smtp.use_ssl and not env.smtp.use_tls: + log.warning( + "Passwordless email delivery via SuperTokens may still attempt STARTTLS " + "even though SMTP_USE_TLS=false; set SMTP_USE_SSL=true or " + "SMTP_USE_TLS=true to avoid this difference." + ) + + return EmailDeliveryConfig( + service=passwordless.SMTPService( + SMTPSettings( + host=env.smtp.host, + port=env.smtp.port, + from_=SMTPSettingsFrom(name="Agenta", email=env.smtp.from_email), + username=env.smtp.username, + password=env.smtp.password, + secure=env.smtp.use_ssl, + ) + ) + ) + + def get_app_info() -> InputAppInfo: """Get SuperTokens app info.""" # Extract domain from full URL (e.g., "http://localhost/api" -> "http://localhost") @@ -402,6 +433,7 @@ def init_supertokens(): apis=override_passwordless_apis, functions=override_passwordless_functions, ), + email_delivery=get_passwordless_email_delivery(), ) ) diff --git a/api/oss/src/services/email_service.py b/api/oss/src/services/email_service.py index 8ad0540996..f2693d2886 100644 --- a/api/oss/src/services/email_service.py +++ b/api/oss/src/services/email_service.py @@ -1,4 +1,8 @@ +import asyncio import os +import smtplib +import ssl +from email.message import EmailMessage import sendgrid from sendgrid.helpers.mail import Mail @@ -10,7 +14,15 @@ log = get_logger(__name__) -# Initialize SendGrid only if enabled +# Initialize email providers only if enabled +if env.smtp.enabled: + log.info("✓ SMTP email enabled") +else: + if (env.smtp.host or env.smtp.port) and not env.smtp.from_email: + log.warn("✗ SMTP disabled: missing sender email address") + else: + log.warn("✗ SMTP disabled") + if env.sendgrid.enabled: sg = sendgrid.SendGridAPIClient(api_key=env.sendgrid.api_key) log.info("✓ SendGrid enabled") @@ -54,11 +66,84 @@ async def send_email( HTTPException: If there is an error sending the email. """ - # No-op if SendGrid is disabled - if not env.sendgrid.enabled: - log.info(f"[SENDGRID] Email disabled - would send '{subject}' to {to_email}") - return True + if env.smtp.enabled: + return await _send_smtp_email( + to_email=to_email, + subject=subject, + html_content=html_content, + from_email=from_email, + ) + + if env.sendgrid.enabled: + return await _send_sendgrid_email( + to_email=to_email, + subject=subject, + html_content=html_content, + from_email=from_email, + ) + + log.info("[EMAIL] Email disabled - skipping email send") + return True + + +async def _send_smtp_email( + to_email: str, subject: str, html_content: str, from_email: str +) -> bool: + try: + return await asyncio.to_thread( + _send_smtp_email_sync, + to_email=to_email, + subject=subject, + html_content=html_content, + from_email=from_email, + ) + except Exception: + log.exception("Failed to send SMTP email") + raise HTTPException( + status_code=500, + detail="Failed to send email", + ) + + +def _send_smtp_email_sync( + to_email: str, subject: str, html_content: str, from_email: str +) -> bool: + message = EmailMessage() + message["From"] = from_email or env.smtp.from_email + message["To"] = to_email + message["Subject"] = subject + message.set_content(html_content, subtype="html") + + context = ssl.create_default_context() + + if env.smtp.use_ssl: + with smtplib.SMTP_SSL( + env.smtp.host, + env.smtp.port, + context=context, + timeout=env.smtp.timeout, + ) as smtp: + if env.smtp.username: + smtp.login(env.smtp.username, env.smtp.password) + smtp.send_message(message) + else: + with smtplib.SMTP( + env.smtp.host, + env.smtp.port, + timeout=env.smtp.timeout, + ) as smtp: + if env.smtp.use_tls: + smtp.starttls(context=context) + if env.smtp.username: + smtp.login(env.smtp.username, env.smtp.password) + smtp.send_message(message) + return True + + +async def _send_sendgrid_email( + to_email: str, subject: str, html_content: str, from_email: str +) -> bool: message = Mail( from_email=from_email, to_emails=to_email, diff --git a/api/oss/src/services/organization_service.py b/api/oss/src/services/organization_service.py index 18a1031949..68f84a7064 100644 --- a/api/oss/src/services/organization_service.py +++ b/api/oss/src/services/organization_service.py @@ -154,8 +154,8 @@ async def send_invitation_email( f"&project_id={project_param}" ) - # If Sendgrid is not configured, return the link for manual sharing (URL-based invitation) - if not env.sendgrid.enabled: + # If email delivery is not configured, return the link for manual sharing. + if not (env.smtp.enabled or env.sendgrid.enabled): return invite_link html_template = email_service.read_email_template("./templates/send_email.html") @@ -169,11 +169,12 @@ async def send_invitation_email( ), ) - if not env.sendgrid.from_address: - raise ValueError("Sendgrid requires a sender email address to work.") + from_email = env.smtp.from_email if env.smtp.enabled else env.sendgrid.from_address + if not from_email: + raise ValueError("Email delivery requires a sender email address to work.") await email_service.send_email( - from_email=env.sendgrid.from_address, + from_email=from_email, to_email=email, subject=f"{user.username} invited you to join their organization", html_content=html_content, diff --git a/api/oss/src/services/user_service.py b/api/oss/src/services/user_service.py index d254510e72..17e1d73b15 100644 --- a/api/oss/src/services/user_service.py +++ b/api/oss/src/services/user_service.py @@ -148,7 +148,7 @@ async def generate_user_password_reset_link(user_id: str, admin_user_id: str): email=user.email, ) - if not env.sendgrid.api_key: + if not (env.smtp.enabled or env.sendgrid.enabled): return password_reset_link html_template = email_service.read_email_template("./templates/send_email.html") @@ -159,11 +159,12 @@ async def generate_user_password_reset_link(user_id: str, admin_user_id: str): call_to_action=f"""
Click the link below to reset your password:
Hello
", + from_email="caller@example.com", + ) + + smtp = FakeSmtp.instances[0] + assert smtp.host == "smtp.example.com" + assert smtp.port == 587 + smtp.starttls.assert_called_once() + smtp.login.assert_called_once_with("user", "secret") + message = smtp.send_message.call_args.args[0] + assert message["From"] == "caller@example.com" + assert message["To"] == "to@example.com" + assert message["Subject"] == "Subject" + + +@pytest.mark.asyncio +async def test_send_email_prefers_smtp_over_sendgrid(monkeypatch): + _enable_smtp(monkeypatch, use_tls=False, use_ssl=False) + monkeypatch.setattr(env.sendgrid, "api_key", "sg-key") + monkeypatch.setattr(env.sendgrid, "from_address", "sendgrid@example.com") + fake_sendgrid = Mock() + monkeypatch.setattr(email_service, "sg", fake_sendgrid) + FakeSmtp.instances = [] + monkeypatch.setattr(email_service.smtplib, "SMTP", FakeSmtp) + + assert await email_service.send_email( + to_email="to@example.com", + subject="Subject", + html_content="Hello
", + from_email="caller@example.com", + ) + + assert FakeSmtp.instances + fake_sendgrid.send.assert_not_called() + + +@pytest.mark.asyncio +async def test_send_email_uses_smtp_ssl_without_starttls(monkeypatch): + _enable_smtp(monkeypatch, use_tls=True, use_ssl=True) + _disable_sendgrid(monkeypatch) + FakeSmtp.instances = [] + monkeypatch.setattr(email_service.smtplib, "SMTP_SSL", FakeSmtp) + + assert await email_service.send_email( + to_email="to@example.com", + subject="Subject", + html_content="Hello
", + from_email="caller@example.com", + ) + + smtp = FakeSmtp.instances[0] + assert "context" in smtp.kwargs + smtp.starttls.assert_not_called() + smtp.login.assert_called_once_with("user", "secret") + smtp.send_message.assert_called_once() + + +@pytest.mark.asyncio +async def test_send_email_falls_back_to_sendgrid(monkeypatch): + _disable_smtp(monkeypatch) + monkeypatch.setattr(env.sendgrid, "api_key", "sg-key") + monkeypatch.setattr(env.sendgrid, "from_address", "sendgrid@example.com") + fake_sendgrid = Mock() + monkeypatch.setattr(email_service, "sg", fake_sendgrid) + + assert await email_service.send_email( + to_email="to@example.com", + subject="Subject", + html_content="Hello
", + from_email="caller@example.com", + ) + + fake_sendgrid.send.assert_called_once() + + +@pytest.mark.asyncio +async def test_send_email_noops_when_no_provider_is_configured(monkeypatch): + _disable_smtp(monkeypatch) + _disable_sendgrid(monkeypatch) + + assert await email_service.send_email( + to_email="to@example.com", + subject="Subject", + html_content="Hello
", + from_email="caller@example.com", + ) + + +def test_auth_email_method_uses_strict_smtp_detection(monkeypatch): + monkeypatch.setattr(env.agenta.access, "email_disabled", False) + _disable_sendgrid(monkeypatch) + _disable_smtp(monkeypatch) + + monkeypatch.setattr(env.smtp, "host", "smtp.example.com") + monkeypatch.setattr(env.smtp, "port", 587) + assert env.auth.email_method == "password" + + monkeypatch.setattr(env.smtp, "from_email", "smtp@example.com") + assert env.auth.email_method == "otp" + + +def test_incomplete_smtp_does_not_enable_email_otp(monkeypatch): + monkeypatch.setattr(env.agenta.access, "email_disabled", False) + _disable_sendgrid(monkeypatch) + _disable_smtp(monkeypatch) + + monkeypatch.setattr(env.smtp, "host", "smtp.example.com") + monkeypatch.setattr(env.smtp, "from_email", "smtp@example.com") + + assert not env.smtp.enabled + assert env.auth.email_method == "password" diff --git a/api/oss/tests/pytest/unit/test_web_entrypoint_email_env.py b/api/oss/tests/pytest/unit/test_web_entrypoint_email_env.py new file mode 100644 index 0000000000..1f65b3eb3b --- /dev/null +++ b/api/oss/tests/pytest/unit/test_web_entrypoint_email_env.py @@ -0,0 +1,68 @@ +import subprocess +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[5] + + +def _run_entrypoint(tmp_path, repo_root, env): + result = subprocess.run( + ["/bin/sh", str(repo_root / "web" / "entrypoint.sh"), "true"], + cwd=tmp_path, + env={ + "PATH": "/usr/bin:/bin", + "ENTRYPOINT_DIR": ".", + "AGENTA_LICENSE": "oss", + **env, + }, + check=True, + capture_output=True, + text=True, + ) + env_js = tmp_path / "oss" / "public" / "__env.js" + assert env_js.exists(), result.stderr + return env_js.read_text() + + +def test_entrypoint_enables_otp_for_smtp_only_config(tmp_path): + env_js = _run_entrypoint( + tmp_path, + REPO_ROOT, + { + "SMTP_HOST": "host.docker.internal", + "SMTP_PORT": "1025", + "SMTP_FROM_EMAIL": "dev@example.com", + }, + ) + + assert 'NEXT_PUBLIC_AGENTA_AUTHN_EMAIL: "otp"' in env_js + assert 'NEXT_PUBLIC_AGENTA_AUTH_EMAIL_ENABLED: "true"' in env_js + + +def test_entrypoint_preserves_sendgrid_only_otp_config(tmp_path): + env_js = _run_entrypoint( + tmp_path, + REPO_ROOT, + { + "SENDGRID_API_KEY": "sg-key", + "SENDGRID_FROM_ADDRESS": "sendgrid@example.com", + }, + ) + + assert 'NEXT_PUBLIC_AGENTA_SENDGRID_ENABLED: "true"' in env_js + assert 'NEXT_PUBLIC_AGENTA_AUTHN_EMAIL: "otp"' in env_js + assert 'NEXT_PUBLIC_AGENTA_AUTH_EMAIL_ENABLED: "true"' in env_js + + +def test_entrypoint_does_not_enable_otp_for_incomplete_smtp(tmp_path): + env_js = _run_entrypoint( + tmp_path, + REPO_ROOT, + { + "SMTP_HOST": "host.docker.internal", + "SMTP_FROM_EMAIL": "dev@example.com", + }, + ) + + assert 'NEXT_PUBLIC_AGENTA_AUTHN_EMAIL: "password"' in env_js + assert 'NEXT_PUBLIC_AGENTA_AUTH_EMAIL_ENABLED: "true"' in env_js diff --git a/docs/docs/self-host/02-configuration.mdx b/docs/docs/self-host/02-configuration.mdx index 4525c66f18..51f212b53a 100644 --- a/docs/docs/self-host/02-configuration.mdx +++ b/docs/docs/self-host/02-configuration.mdx @@ -254,8 +254,30 @@ This key has no env-var or `env.py` equivalent. | `REDIS_URI_DURABLE` | `redis.uri_durable` | `redis.uriDurable` | | `REDIS_URI_VOLATILE` | `redis.uri_volatile` | `redis.uriVolatile` | +## smtp + +SMTP is preferred for email delivery. It is enabled only when host, port, and +sender are configured. SendGrid remains supported as a fallback when SMTP is not +fully configured. + +For local Mailpit from an API container, use `SMTP_HOST=host.docker.internal` +when Mailpit runs on the host, or `SMTP_HOST=mailpit` only when Mailpit is on +the same Docker network. + +| Env var | env.py path | values.yaml path | +|---|---|---| +| `SMTP_HOST` | `smtp.host` | _(not mapped)_ | +| `SMTP_PORT` | `smtp.port` | _(not mapped)_ | +| `SMTP_USERNAME` | `smtp.username` | _(not mapped)_ | +| `SMTP_PASSWORD` | `smtp.password` | _(not mapped)_ | +| `SMTP_FROM_EMAIL` | `smtp.from_email` | _(not mapped)_ | +| `SMTP_USE_TLS` | `smtp.use_tls` | _(not mapped)_ | +| `SMTP_USE_SSL` | `smtp.use_ssl` | _(not mapped)_ | + ## sendgrid +SendGrid is used only when SMTP is not fully configured. + | Env var | env.py path | values.yaml path | |---|---|---| | `SENDGRID_API_KEY` | `sendgrid.api_key` | `sendgrid.apiKey` | @@ -322,7 +344,7 @@ future major release. | `NEW_RELIC_LICENSE_KEY` | `NEWRELIC_LICENSE_KEY` | | `NRIA_LICENSE_KEY` | `NEWRELIC_LICENSE_KEY` | | `POSTHOG_HOST` | `POSTHOG_API_URL` | -| `AGENTA_AUTHN_EMAIL_FROM` | `SENDGRID_FROM_ADDRESS` | -| `AGENTA_SEND_EMAIL_FROM_ADDRESS` | `SENDGRID_FROM_ADDRESS` | +| `AGENTA_AUTHN_EMAIL_FROM` | `SMTP_FROM_EMAIL` (preferred) or `SENDGRID_FROM_ADDRESS` fallback | +| `AGENTA_SEND_EMAIL_FROM_ADDRESS` | `SMTP_FROM_EMAIL` (preferred) or `SENDGRID_FROM_ADDRESS` fallback | | `STRIPE_TARGET` | `STRIPE_WEBHOOK_TARGET` | | `SUPERTOKENS_CONNECTION_URI` | `SUPERTOKENS_URI_CORE` | diff --git a/docs/docs/self-host/upgrades/v0.100.3-migration.mdx b/docs/docs/self-host/upgrades/v0.100.3-migration.mdx index 57a9b7d818..28989266f1 100644 --- a/docs/docs/self-host/upgrades/v0.100.3-migration.mdx +++ b/docs/docs/self-host/upgrades/v0.100.3-migration.mdx @@ -96,7 +96,7 @@ The Pydantic env loader reads the new name first and falls back to the old one w | `AGENTA_SERVICE_MIDDLEWARE_CACHE_ENABLED` (singular SERVICE) | `AGENTA_SERVICES_MIDDLEWARE_CACHING_ENABLED` | | `SUPERTOKENS_CONNECTION_URI` | `SUPERTOKENS_URI_CORE` | | `SUPERTOKENS_EMAIL_DISABLED` | `AGENTA_ACCESS_EMAIL_DISABLED` | -| `AGENTA_AUTHN_EMAIL_FROM` / `AGENTA_SEND_EMAIL_FROM_ADDRESS` | `SENDGRID_FROM_ADDRESS` | +| `AGENTA_AUTHN_EMAIL_FROM` / `AGENTA_SEND_EMAIL_FROM_ADDRESS` | `SMTP_FROM_EMAIL` (preferred) or `SENDGRID_FROM_ADDRESS` fallback | | `POSTHOG_HOST` | `POSTHOG_API_URL` | | `STRIPE_TARGET` | `STRIPE_WEBHOOK_TARGET` | | `AGENTA_PRICING` / `STRIPE_PRICING` | `AGENTA_BILLING_PRICING` | diff --git a/hosting/docker-compose/ee/env.ee.dev.example b/hosting/docker-compose/ee/env.ee.dev.example index d4aa299188..a1d2222761 100644 --- a/hosting/docker-compose/ee/env.ee.dev.example +++ b/hosting/docker-compose/ee/env.ee.dev.example @@ -214,9 +214,24 @@ POSTHOG_API_KEY=phc_3urGRy5TL1HhaHnRYL0JSHxJxigRVackhphHtozUmdp # REDIS_URI_DURABLE=redis://redis-durable:6381/0 # REDIS_URI_VOLATILE=redis://redis-volatile:6379/0 +# ================================================================== # +# smtp +# ================================================================== # +# SMTP is preferred for email delivery. For host Mailpit from Docker, use +# SMTP_HOST=host.docker.internal. Use SMTP_HOST=mailpit only when Mailpit is on +# the same Docker Compose network. +# SMTP_HOST= +# SMTP_PORT=1025 +# SMTP_USERNAME= +# SMTP_PASSWORD= +# SMTP_FROM_EMAIL= +# SMTP_USE_TLS=true +# SMTP_USE_SSL=false + # ================================================================== # # sendgrid # ================================================================== # +# SendGrid remains supported as a fallback when SMTP is not fully configured. # SENDGRID_API_KEY= # SENDGRID_FROM_ADDRESS= diff --git a/hosting/docker-compose/ee/env.ee.gh.example b/hosting/docker-compose/ee/env.ee.gh.example index 0310e956b0..2298c5beef 100644 --- a/hosting/docker-compose/ee/env.ee.gh.example +++ b/hosting/docker-compose/ee/env.ee.gh.example @@ -214,9 +214,24 @@ POSTHOG_API_KEY=phc_3urGRy5TL1HhaHnRYL0JSHxJxigRVackhphHtozUmdp # REDIS_URI_DURABLE=redis://redis-durable:6381/0 # REDIS_URI_VOLATILE=redis://redis-volatile:6379/0 +# ================================================================== # +# smtp +# ================================================================== # +# SMTP is preferred for email delivery. For host Mailpit from Docker, use +# SMTP_HOST=host.docker.internal. Use SMTP_HOST=mailpit only when Mailpit is on +# the same Docker Compose network. +# SMTP_HOST= +# SMTP_PORT=1025 +# SMTP_USERNAME= +# SMTP_PASSWORD= +# SMTP_FROM_EMAIL= +# SMTP_USE_TLS=true +# SMTP_USE_SSL=false + # ================================================================== # # sendgrid # ================================================================== # +# SendGrid remains supported as a fallback when SMTP is not fully configured. # SENDGRID_API_KEY= # SENDGRID_FROM_ADDRESS= diff --git a/hosting/docker-compose/oss/env.oss.dev.example b/hosting/docker-compose/oss/env.oss.dev.example index 53aca58e84..17c405bb9b 100644 --- a/hosting/docker-compose/oss/env.oss.dev.example +++ b/hosting/docker-compose/oss/env.oss.dev.example @@ -214,9 +214,24 @@ POSTHOG_API_KEY=phc_hmVSxIjTW1REBHXgj2aw4HW9X6CXb6FzerBgP9XenC7 # REDIS_URI_DURABLE=redis://redis-durable:6381/0 # REDIS_URI_VOLATILE=redis://redis-volatile:6379/0 +# ================================================================== # +# smtp +# ================================================================== # +# SMTP is preferred for email delivery. For host Mailpit from Docker, use +# SMTP_HOST=host.docker.internal. Use SMTP_HOST=mailpit only when Mailpit is on +# the same Docker Compose network. +# SMTP_HOST= +# SMTP_PORT=1025 +# SMTP_USERNAME= +# SMTP_PASSWORD= +# SMTP_FROM_EMAIL= +# SMTP_USE_TLS=true +# SMTP_USE_SSL=false + # ================================================================== # # sendgrid # ================================================================== # +# SendGrid remains supported as a fallback when SMTP is not fully configured. # SENDGRID_API_KEY= # SENDGRID_FROM_ADDRESS= diff --git a/hosting/docker-compose/oss/env.oss.gh.example b/hosting/docker-compose/oss/env.oss.gh.example index 4fc6b1244e..0c4aa38785 100644 --- a/hosting/docker-compose/oss/env.oss.gh.example +++ b/hosting/docker-compose/oss/env.oss.gh.example @@ -214,9 +214,24 @@ POSTHOG_API_KEY=phc_hmVSxIjTW1REBHXgj2aw4HW9X6CXb6FzerBgP9XenC7 # REDIS_URI_DURABLE=redis://redis-durable:6381/0 # REDIS_URI_VOLATILE=redis://redis-volatile:6379/0 +# ================================================================== # +# smtp +# ================================================================== # +# SMTP is preferred for email delivery. For host Mailpit from Docker, use +# SMTP_HOST=host.docker.internal. Use SMTP_HOST=mailpit only when Mailpit is on +# the same Docker Compose network. +# SMTP_HOST= +# SMTP_PORT=1025 +# SMTP_USERNAME= +# SMTP_PASSWORD= +# SMTP_FROM_EMAIL= +# SMTP_USE_TLS=true +# SMTP_USE_SSL=false + # ================================================================== # # sendgrid # ================================================================== # +# SendGrid remains supported as a fallback when SMTP is not fully configured. # SENDGRID_API_KEY= # SENDGRID_FROM_ADDRESS= diff --git a/web/entrypoint.sh b/web/entrypoint.sh index bad73c7eee..e719f01f74 100755 --- a/web/entrypoint.sh +++ b/web/entrypoint.sh @@ -25,6 +25,20 @@ else export AGENTA_SENDGRID_ENABLED="false" fi +# Infer SMTP email delivery from strict SMTP requirements: host + port + sender +SMTP_FROM_EMAIL_VALUE="${SMTP_FROM_EMAIL:-${AGENTA_AUTHN_EMAIL_FROM:-${AGENTA_SEND_EMAIL_FROM_ADDRESS}}}" +if [ -n "$SMTP_HOST" ] && [ -n "$SMTP_PORT" ] && [ -n "$SMTP_FROM_EMAIL_VALUE" ]; then + AGENTA_SMTP_ENABLED="true" +else + AGENTA_SMTP_ENABLED="false" +fi + +if [ "${AGENTA_SMTP_ENABLED}" = "true" ] || [ "${AGENTA_SENDGRID_ENABLED}" = "true" ]; then + AGENTA_EMAIL_DELIVERY_ENABLED="true" +else + AGENTA_EMAIL_DELIVERY_ENABLED="false" +fi + # Infer AGENTA_TOOLS_ENABLED from COMPOSIO_API_KEY if [ -n "$COMPOSIO_API_KEY" ]; then export AGENTA_TOOLS_ENABLED="true" @@ -125,12 +139,12 @@ if [ -n "${BOXY_SAML_OAUTH_CLIENT_ID}" ] && [ -n "${BOXY_SAML_OAUTH_CLIENT_SECRE AUTH_OIDC_ENABLED="true" fi -# Derive email auth method from SUPERTOKENS_EMAIL_DISABLED and SendGrid status +# Derive email auth method from SUPERTOKENS_EMAIL_DISABLED and email delivery status SUPERTOKENS_EMAIL_DISABLED_VALUE="${SUPERTOKENS_EMAIL_DISABLED:-false}" EFFECTIVE_AUTHN_EMAIL="" if [ "${SUPERTOKENS_EMAIL_DISABLED_VALUE}" = "true" ]; then EFFECTIVE_AUTHN_EMAIL="" -elif [ "${AGENTA_SENDGRID_ENABLED}" = "true" ]; then +elif [ "${AGENTA_EMAIL_DELIVERY_ENABLED}" = "true" ]; then EFFECTIVE_AUTHN_EMAIL="otp" else EFFECTIVE_AUTHN_EMAIL="password"