Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions api/ee/src/services/db_manager_ee.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import uuid
from datetime import datetime, timezone

import sendgrid
from fastapi import HTTPException

from sqlalchemy import delete, func, update
Expand Down Expand Up @@ -60,9 +59,6 @@
from oss.src.utils.env import env


# Initialize sendgrid api client
sg = sendgrid.SendGridAPIClient(api_key=env.sendgrid.api_key)

log = get_module_logger(__name__)


Expand Down
12 changes: 8 additions & 4 deletions api/ee/src/services/organization_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 is not configured, return the link for manual sharing (URL-based invitation)
if not env.smtp.enabled and not env.sendgrid.enabled:
return invite_link

html_content = html_template.format(
Expand All @@ -118,8 +118,10 @@ async def send_invitation_email(
),
)

from_address = env.smtp.from_address or env.sendgrid.from_address or "account@hello.agenta.ai"

await email_service.send_email(
from_email="account@hello.agenta.ai",
from_email=from_address,
to_email=email,
subject=f"{user.username} invited you to join {organization.name}",
html_content=html_content,
Expand Down Expand Up @@ -152,10 +154,12 @@ async def notify_org_admin_invitation(workspace: WorkspaceDB, user: UserDB) -> b
),
)

from_address = env.smtp.from_address or env.sendgrid.from_address or "account@hello.agenta.ai"

workspace_admins = await db_manager_ee.get_workspace_administrators(workspace)
for workspace_admin in workspace_admins:
await email_service.send_email(
from_email="account@hello.agenta.ai",
from_email=from_address,
to_email=workspace_admin.email,
subject=f"New Member Joined {organization.name}",
html_content=html_content,
Expand Down
86 changes: 65 additions & 21 deletions api/oss/src/services/email_service.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os

import sendgrid
from sendgrid.helpers.mail import Mail
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

from fastapi import HTTPException

Expand All @@ -10,16 +10,25 @@

log = get_logger(__name__)

# Initialize SendGrid only if enabled
if env.sendgrid.enabled:
sg = sendgrid.SendGridAPIClient(api_key=env.sendgrid.api_key)
log.info("✓ SendGrid enabled")
# Determine which email backend to use (SMTP > SendGrid > no-op)
_USE_SMTP = env.smtp.enabled
_USE_SENDGRID = not _USE_SMTP and env.sendgrid.enabled

if _USE_SMTP:
log.info(
"✓ Email enabled via SMTP (%s:%s)", env.smtp.host, env.smtp.port
)
elif _USE_SENDGRID:
import sendgrid

_sg = sendgrid.SendGridAPIClient(api_key=env.sendgrid.api_key)
log.info("✓ Email enabled via SendGrid (legacy)")
Comment on lines +22 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether sendgrid dependency is still declared in project manifests.
fd -a "pyproject.toml" | while read -r f; do
  echo "==> $f"
  rg -n "sendgrid" "$f" || true
done

Repository: Agenta-AI/agenta

Length of output: 321


🏁 Script executed:

#!/bin/bash
# 1) Find all occurrences of "sendgrid" and highlight likely dependency declarations.
rg -n --hidden --no-ignore-vcs --glob '!*node_modules/*' --glob '!*dist/*' \
  "sendgrid" . \
  || true

# 2) Specifically search common dependency files.
for f in $(fd -a "requirements*.txt" . || true); do echo "==> $f"; rg -n "sendgrid" "$f" || true; done
for f in $(fd -a "poetry.lock" . || true); do echo "==> $f"; rg -n "sendgrid" "$f" || true; done
for f in $(fd -a "Pipfile.lock" . || true); do echo "==> $f"; rg -n "sendgrid" "$f" || true; done
for f in $(fd -a "setup.cfg" . || true); do echo "==> $f"; rg -n "sendgrid" "$f" || true; done
for f in $(fd -a "setup.py" . || true); do echo "==> $f"; rg -n "sendgrid" "$f" || true; done

Repository: Agenta-AI/agenta

Length of output: 12693


🏁 Script executed:

#!/bin/bash
# Read-only: confirm SendGrid package presence in dependency lockfile(s).
rg -n "sendgrid" api/uv.lock || true

Repository: Agenta-AI/agenta

Length of output: 760


🏁 Script executed:

rg -n "sendgrid" api/uv.lock

Repository: Agenta-AI/agenta

Length of output: 760


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="api/oss/src/services/email_service.py"

echo "==> File head/tail context (lines 1-170)"
nl -ba "$FILE" | sed -n '1,170p'

echo
echo "==> Key searches"
rg -n "smtplib|SMTP\(|timeout=|_send_via_smtp|_send_via_sendgrid|def send_email|send_email\(|_send_via_sendgrid\(|_send_via_smtp\(" "$FILE"

Repository: Agenta-AI/agenta

Length of output: 162


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="api/oss/src/services/email_service.py"

echo "==> File lines 1-200"
awk 'NR>=1 && NR<=200 {printf "%6d:%s\n", NR, $0}' "$FILE"

echo
echo "==> Search hits"
rg -n "smtplib|SMTP\(|timeout=|_send_via_smtp|_send_via_sendgrid|def send_email|send_email\(|def _send_via_smtp|def _send_via_sendgrid" "$FILE"

Repository: Agenta-AI/agenta

Length of output: 4745


Fix email_service network robustness (SMTP timeout, async blocking, formatting) and make SendGrid import safer.

  • api/oss/src/services/email_service.py: _send_via_smtp creates smtplib.SMTP(smtp_host, smtp_port) without a timeout (lines 59 & 64); add timeout=... to avoid hangs.
  • send_email is async but calls _send_via_smtp / _send_via_sendgrid synchronously (lines 113–116), blocking the event loop; run the send in a thread (e.g., asyncio.to_thread) or use async clients.
  • Keyword-only + grouped-call guideline: _send_via_smtp, _send_via_sendgrid, and send_email use positional parameters and positional calls (lines 45–47, 74–76, 89–91, 114–116); switch to * keyword-only params and format calls with #-grouped blocks.
  • Legacy SendGrid client is created at module import time (lines 20–23). sendgrid is present in api/uv.lock (6.12.5), but defer import/client creation so enabling the config can’t break startup.

else:
sg = None
_sg = None
if env.sendgrid.api_key and not env.sendgrid.from_address:
log.warn("✗ SendGrid disabled: missing sender email address")
log.warn("✗ Email disabled: missing sender email address")
else:
log.warn("✗ SendGrid disabled")
log.warn("✗ Email disabled")


def read_email_template(template_file_path):
Expand All @@ -35,6 +44,46 @@ def read_email_template(template_file_path):
return template_file.read()


def _send_via_smtp(to_email: str, subject: str, html_content: str, from_email: str) -> None:
"""Send email using SMTP."""
msg = MIMEMultipart("alternative")
msg["Subject"] = subject
msg["From"] = from_email
msg["To"] = to_email
msg.attach(MIMEText(html_content, "html"))

smtp_host = env.smtp.host
smtp_port = env.smtp.port

if env.smtp.use_tls:
server = smtplib.SMTP(smtp_host, smtp_port)
server.ehlo()
server.starttls()
server.ehlo()
else:
server = smtplib.SMTP(smtp_host, smtp_port)
Comment on lines +59 to +64
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add an SMTP connection timeout to prevent request hangs.

api/oss/src/services/email_service.py creates smtplib.SMTP(smtp_host, smtp_port) in both branches without a timeout, so a stalled network connection can block indefinitely.

Suggested fix
-        server = smtplib.SMTP(smtp_host, smtp_port)
+        server = smtplib.SMTP(smtp_host, smtp_port, timeout=10)
...
-        server = smtplib.SMTP(smtp_host, smtp_port)
+        server = smtplib.SMTP(smtp_host, smtp_port, timeout=10)

Also applies to: 67-69


try:
if env.smtp.username and env.smtp.password:
server.login(env.smtp.username, env.smtp.password)
server.sendmail(from_email, [to_email], msg.as_string())
finally:
server.quit()


def _send_via_sendgrid(to_email: str, subject: str, html_content: str, from_email: str) -> None:
"""Send email using SendGrid (legacy fallback)."""
from sendgrid.helpers.mail import Mail

message = Mail(
from_email=from_email,
to_emails=to_email,
subject=subject,
html_content=html_content,
)
_sg.send(message)


async def send_email(
to_email: str, subject: str, html_content: str, from_email: str
) -> bool:
Expand All @@ -54,20 +103,15 @@ 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}")
if not _USE_SMTP and not _USE_SENDGRID:
log.info(f"[EMAIL] Email disabled - would send '{subject}' to {to_email}")
return True

message = Mail(
from_email=from_email,
to_emails=to_email,
subject=subject,
html_content=html_content,
)

try:
sg.send(message)
if _USE_SMTP:
_send_via_smtp(to_email, subject, html_content, from_email)
else:
_send_via_sendgrid(to_email, subject, html_content, from_email)
Comment on lines +111 to +114
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="api/oss/src/services/email_service.py"
echo "== File = $FILE =="
wc -l "$FILE"
echo

# show the relevant portion around lines 90-150 (covers 111-114)
nl -ba "$FILE" | sed -n '80,160p'

# show definitions/usages of the helper functions to see if they are sync and how they perform network I/O
echo
echo "== Look for _send_via_smtp definition =="
rg -n "def _send_via_smtp" "$FILE"
echo
nl -ba "$FILE" | sed -n '1,240p' | sed -n '1,240p' | head -n 40

echo
echo "== Look for _send_via_sendgrid definition =="
rg -n "def _send_via_sendgrid" "$FILE"

echo
# print near each helper definition block (best-effort: show 40 lines after match)
python3 - <<'PY'
import re, itertools
path="api/oss/src/services/email_service.py"
lines=open(path,'r',encoding='utf-8').read().splitlines()
# find line numbers for defs
for name in ["_send_via_smtp","_send_via_sendgrid","send_email"]:
    for i,l in enumerate(lines, start=1):
        if re.search(rf"def {re.escape(name)}\b", l):
            start=max(1,i-10); end=min(len(lines), i+120)
            print(f"\n== {name} around line {i} (show {start}-{end}) ==")
            for j in range(start,end+1):
                print(f"{j:4d}: {lines[j-1]}")
            break
PY

# run ruff (non-destructive) in api folder per guidelines to see if there are existing issues related to this code
echo
echo "== ruff format/check in api/ (targeting oss tree only if available) =="
ls api
ruff --version || true
ruff format api/oss/src/services/email_service.py
ruff check api/oss/src/services/email_service.py --fix

Repository: Agenta-AI/agenta

Length of output: 216


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="api/oss/src/services/email_service.py"
echo "== File = $FILE =="
wc -l "$FILE"
echo

# Line-numbered view of the relevant range (avoid `nl` which isn't available)
python3 - <<'PY'
path="api/oss/src/services/email_service.py"
start=80
end=160
with open(path,'r',encoding='utf-8') as f:
    lines=f.readlines()
for i in range(start, min(end, len(lines))):
    print(f"{i+1:4d}: {lines[i].rstrip()}")
PY

echo
echo "== Locate helper definitions =="
rg -n "def _send_via_smtp|def _send_via_sendgrid|async def send_email" "$FILE" || true

echo
echo "== Dump helper/send_email blocks (best-effort) =="
python3 - <<'PY'
import re
path="api/oss/src/services/email_service.py"
lines=open(path,'r',encoding='utf-8').read().splitlines()
def dump_at(name):
    for idx,l in enumerate(lines, start=1):
        if re.match(rf"\s*def {re.escape(name)}\b", l) or re.match(rf"\s*async def {re.escape(name)}\b", l):
            start=max(1, idx-10); end=min(len(lines), idx+200)
            print(f"\n== {name} starting at line {idx} (show {start}-{end}) ==")
            for j in range(start,end+1):
                print(f"{j:4d}: {lines[j-1]}")
            return
    print(f"\n== {name} not found ==")
for n in ["send_email","_send_via_smtp","_send_via_sendgrid"]:
    dump_at(n)
PY

echo
echo "== Try ruff on this file (if ruff exists) =="
command -v ruff >/dev/null 2>&1 && ruff --version || echo "ruff not found in sandbox"
if command -v ruff >/dev/null 2>&1; then
  ruff format "$FILE" || true
  ruff check "$FILE" --fix || true
fi

Repository: Agenta-AI/agenta

Length of output: 8421


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="api/oss/src/services/email_service.py"
python3 - <<'PY'
path="api/oss/src/services/email_service.py"
with open(path,'r',encoding='utf-8') as f:
    lines=f.readlines()
for i,l in enumerate(lines[:80], start=1):
    print(f"{i:4d}: {l.rstrip()}")
PY

Repository: Agenta-AI/agenta

Length of output: 2839


Offload SMTP/SendGrid blocking calls from async send_email

send_email is async, but it calls synchronous SMTP/SendGrid network operations directly at lines 111-114 (smtplib.SMTP(...).sendmail(...) and _sg.send(...)), which can block the event loop under load.

Suggested fix
+import asyncio
...
-        if _USE_SMTP:
-            _send_via_smtp(to_email, subject, html_content, from_email)
-        else:
-            _send_via_sendgrid(to_email, subject, html_content, from_email)
+        if _USE_SMTP:
+            await asyncio.to_thread(
+                _send_via_smtp,
+                to_email=to_email,
+                subject=subject,
+                html_content=html_content,
+                from_email=from_email,
+            )
+        else:
+            await asyncio.to_thread(
+                _send_via_sendgrid,
+                to_email=to_email,
+                subject=subject,
+                html_content=html_content,
+                from_email=from_email,
+            )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if _USE_SMTP:
_send_via_smtp(to_email, subject, html_content, from_email)
else:
_send_via_sendgrid(to_email, subject, html_content, from_email)
if _USE_SMTP:
await asyncio.to_thread(
_send_via_smtp,
to_email=to_email,
subject=subject,
html_content=html_content,
from_email=from_email,
)
else:
await asyncio.to_thread(
_send_via_sendgrid,
to_email=to_email,
subject=subject,
html_content=html_content,
from_email=from_email,
)

return True
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
11 changes: 6 additions & 5 deletions api/oss/src/services/organization_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 is not configured, return the link for manual sharing (URL-based invitation)
if not env.smtp.enabled and not env.sendgrid.enabled:
return invite_link

html_template = email_service.read_email_template("./templates/send_email.html")
Expand All @@ -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_address = env.smtp.from_address or env.sendgrid.from_address
if not from_address:
raise ValueError("Email requires a sender email address to work.")

await email_service.send_email(
from_email=env.sendgrid.from_address,
from_email=from_address,
to_email=email,
subject=f"{user.username} invited you to join their organization",
html_content=html_content,
Expand Down
9 changes: 5 additions & 4 deletions api/oss/src/services/user_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 and not env.sendgrid.enabled:
return password_reset_link

html_template = email_service.read_email_template("./templates/send_email.html")
Expand All @@ -159,11 +159,12 @@ async def generate_user_password_reset_link(user_id: str, admin_user_id: str):
call_to_action=f"""<p>Click the link below to reset your password:</p><br><a href="{password_reset_link}">Reset Password</a>""",
)

if not env.sendgrid.from_address:
raise ValueError("Sendgrid requires a sender email address to work.")
from_address = env.smtp.from_address or env.sendgrid.from_address
if not from_address:
raise ValueError("Email requires a sender email address to work.")

await email_service.send_email(
from_email=env.sendgrid.from_address,
from_email=from_address,
to_email=user.email,
subject=f"{admin_user.username} requested a password reset for you in their workspace",
html_content=html_content,
Expand Down
45 changes: 34 additions & 11 deletions api/oss/src/utils/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -922,12 +922,40 @@ def enabled(self) -> bool:


# ---------------------------------------------------------------------------
# sendgrid
# smtp
# ---------------------------------------------------------------------------


class SmtpConfig(BaseModel):
"""SMTP Email configuration"""

host: str | None = os.getenv("SMTP_HOST")
port: int = int(os.getenv("SMTP_PORT", "587"))
username: str | None = os.getenv("SMTP_USERNAME")
password: str | None = os.getenv("SMTP_PASSWORD")
from_address: str | None = (
os.getenv("SMTP_FROM_ADDRESS")
or os.getenv("SENDGRID_FROM_ADDRESS")
or os.getenv("AGENTA_AUTHN_EMAIL_FROM")
or os.getenv("AGENTA_SEND_EMAIL_FROM_ADDRESS")
)
use_tls: bool = os.getenv("SMTP_USE_TLS", "true").lower() in ("true", "1", "yes")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use shared truthy parsing for SMTP_USE_TLS for consistent behavior.

SMTP_USE_TLS=on|enabled|y|t is currently treated as false here, while other env booleans in this file accept those values via _TRUTHY.

Suggested fix
-    use_tls: bool = os.getenv("SMTP_USE_TLS", "true").lower() in ("true", "1", "yes")
+    use_tls: bool = (os.getenv("SMTP_USE_TLS") or "true").lower() in _TRUTHY
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
use_tls: bool = os.getenv("SMTP_USE_TLS", "true").lower() in ("true", "1", "yes")
use_tls: bool = (os.getenv("SMTP_USE_TLS") or "true").lower() in _TRUTHY


model_config = ConfigDict(extra="ignore")

@property
def enabled(self) -> bool:
"""SMTP enabled if host and from address are present"""
return bool(self.host and self.from_address)


# ---------------------------------------------------------------------------
# sendgrid (legacy — kept for backwards compatibility)
# ---------------------------------------------------------------------------


class SendgridConfig(BaseModel):
"""SendGrid Email configuration"""
"""SendGrid Email configuration (legacy)"""

api_key: str | None = os.getenv("SENDGRID_API_KEY")
from_address: str | None = (
Expand Down Expand Up @@ -1037,15 +1065,9 @@ def email_method(self) -> str:
if env.agenta.access.email_disabled:
return ""

sendgrid_enabled = bool(
os.getenv("SENDGRID_API_KEY")
and (
os.getenv("SENDGRID_FROM_ADDRESS")
or os.getenv("AGENTA_AUTHN_EMAIL_FROM")
or os.getenv("AGENTA_SEND_EMAIL_FROM_ADDRESS")
)
)
return "otp" if sendgrid_enabled else "password"
# SMTP takes priority, then SendGrid fallback
email_configured = env.smtp.enabled or env.sendgrid.enabled
return "otp" if email_configured else "password"

@property
def email_enabled(self) -> bool:
Expand Down Expand Up @@ -1101,6 +1123,7 @@ class EnvironSettings(BaseModel):
posthog: PostHogConfig = PostHogConfig()
redis: RedisConfig = RedisConfig()
sendgrid: SendgridConfig = SendgridConfig()
smtp: SmtpConfig = SmtpConfig()
stripe: StripeConfig = StripeConfig()
supertokens: SuperTokensConfig = SuperTokensConfig()

Expand Down
1 change: 0 additions & 1 deletion api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ dependencies = [
"cachetools>=7,<8",
"supertokens-python>=0.31,<0.32",
"openai>=2,<3",
"sendgrid>=6,<7",
"stripe>=15,<16",
"posthog>=7,<8",
"newrelic>=13,<14",
Expand Down
13 changes: 12 additions & 1 deletion docs/docs/self-host/02-configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,18 @@ 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` |

## sendgrid
## smtp

| Env var | env.py path | values.yaml path |
|---|---|---|
| `SMTP_HOST` | `smtp.host` | `smtp.host` |
| `SMTP_PORT` | `smtp.port` | `smtp.port` |
| `SMTP_USERNAME` | `smtp.username` | `smtp.username` |
| `SMTP_PASSWORD` | `smtp.password` | `smtp.password` |
| `SMTP_FROM_ADDRESS` | `smtp.from_address` | `smtp.fromAddress` |
| `SMTP_USE_TLS` | `smtp.use_tls` | `smtp.useTls` |

## sendgrid (legacy)

| Env var | env.py path | values.yaml path |
|---|---|---|
Expand Down
12 changes: 11 additions & 1 deletion hosting/docker-compose/ee/env.ee.dev.example
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,17 @@ POSTHOG_API_KEY=phc_3urGRy5TL1HhaHnRYL0JSHxJxigRVackhphHtozUmdp
# REDIS_URI_VOLATILE=redis://redis-volatile:6379/0

# ================================================================== #
# sendgrid
# smtp
# ================================================================== #
# SMTP_HOST=
# SMTP_PORT=587
# SMTP_USERNAME=
# SMTP_PASSWORD=
# SMTP_FROM_ADDRESS=
# SMTP_USE_TLS=true

# ================================================================== #
# sendgrid (legacy — use SMTP instead)
# ================================================================== #
# SENDGRID_API_KEY=
# SENDGRID_FROM_ADDRESS=
Expand Down
12 changes: 11 additions & 1 deletion hosting/docker-compose/ee/env.ee.gh.example
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,17 @@ POSTHOG_API_KEY=phc_3urGRy5TL1HhaHnRYL0JSHxJxigRVackhphHtozUmdp
# REDIS_URI_VOLATILE=redis://redis-volatile:6379/0

# ================================================================== #
# sendgrid
# smtp
# ================================================================== #
# SMTP_HOST=
# SMTP_PORT=587
# SMTP_USERNAME=
# SMTP_PASSWORD=
# SMTP_FROM_ADDRESS=
# SMTP_USE_TLS=true

# ================================================================== #
# sendgrid (legacy — use SMTP instead)
# ================================================================== #
# SENDGRID_API_KEY=
# SENDGRID_FROM_ADDRESS=
Expand Down
12 changes: 11 additions & 1 deletion hosting/docker-compose/oss/env.oss.dev.example
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,17 @@ POSTHOG_API_KEY=phc_hmVSxIjTW1REBHXgj2aw4HW9X6CXb6FzerBgP9XenC7
# REDIS_URI_VOLATILE=redis://redis-volatile:6379/0

# ================================================================== #
# sendgrid
# smtp
# ================================================================== #
# SMTP_HOST=
# SMTP_PORT=587
# SMTP_USERNAME=
# SMTP_PASSWORD=
# SMTP_FROM_ADDRESS=
# SMTP_USE_TLS=true

# ================================================================== #
# sendgrid (legacy — use SMTP instead)
# ================================================================== #
# SENDGRID_API_KEY=
# SENDGRID_FROM_ADDRESS=
Expand Down
12 changes: 11 additions & 1 deletion hosting/docker-compose/oss/env.oss.gh.example
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,17 @@ POSTHOG_API_KEY=phc_hmVSxIjTW1REBHXgj2aw4HW9X6CXb6FzerBgP9XenC7
# REDIS_URI_VOLATILE=redis://redis-volatile:6379/0

# ================================================================== #
# sendgrid
# smtp
# ================================================================== #
# SMTP_HOST=
# SMTP_PORT=587
# SMTP_USERNAME=
# SMTP_PASSWORD=
# SMTP_FROM_ADDRESS=
# SMTP_USE_TLS=true

# ================================================================== #
# sendgrid (legacy — use SMTP instead)
# ================================================================== #
# SENDGRID_API_KEY=
# SENDGRID_FROM_ADDRESS=
Expand Down
Loading