mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-18 11:59:26 +00:00
feat: use MailGun instead of Resend
This commit is contained in:
parent
5fd979b2a2
commit
3b60ec5547
9 changed files with 1628 additions and 54 deletions
|
|
@ -73,8 +73,9 @@ LEARNHOUSE_REDIS_CONNECTION_STRING=redis://default:strong_redis_password@redis:6
|
|||
LEARNHOUSE_CHROMADB_HOST=chromadb
|
||||
|
||||
# Email Configuration (optional)
|
||||
LEARNHOUSE_EMAIL_PROVIDER=resend
|
||||
LEARNHOUSE_RESEND_API_KEY=re_your_resend_api_key
|
||||
LEARNHOUSE_MAILGUN_API_KEY=re_your_mailgun_api_key
|
||||
LEARNHOUSE_MAILGUN_DOMAIN=re_your_mailgun_domain
|
||||
LEARNHOUSE_SYSTEM_EMAIL_ADDRESS=re_your_system_email_address
|
||||
```
|
||||
|
||||
### 5. Start the Build Process
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ class HostingConfig(BaseModel):
|
|||
|
||||
|
||||
class MailingConfig(BaseModel):
|
||||
resend_api_key: str
|
||||
mailgun_api_key: str
|
||||
mailgun_domain: str
|
||||
system_email_address: str
|
||||
|
||||
|
||||
|
|
@ -236,10 +237,14 @@ def get_learnhouse_config() -> LearnHouseConfig:
|
|||
).get("redis_connection_string")
|
||||
|
||||
# Mailing config
|
||||
env_resend_api_key = os.environ.get("LEARNHOUSE_RESEND_API_KEY")
|
||||
env_mailgun_api_key = os.environ.get("LEARNHOUSE_MAILGUN_API_KEY")
|
||||
env_mailgun_domain = os.environ.get("LEARNHOUSE_MAILGUN_DOMAIN")
|
||||
env_system_email_address = os.environ.get("LEARNHOUSE_SYSTEM_EMAIL_ADDRESS")
|
||||
resend_api_key = env_resend_api_key or yaml_config.get("mailing_config", {}).get(
|
||||
"resend_api_key"
|
||||
mailgun_api_key = env_mailgun_api_key or yaml_config.get("mailing_config", {}).get(
|
||||
"mailgun_api_key"
|
||||
)
|
||||
mailgun_domain = env_mailgun_domain or yaml_config.get("mailing_domain", {}).get(
|
||||
"mailgun_domain"
|
||||
)
|
||||
system_email_address = env_system_email_address or yaml_config.get(
|
||||
"mailing_config", {}
|
||||
|
|
@ -313,7 +318,7 @@ def get_learnhouse_config() -> LearnHouseConfig:
|
|||
ai_config=ai_config,
|
||||
redis_config=RedisConfig(redis_connection_string=redis_connection_string),
|
||||
mailing_config=MailingConfig(
|
||||
resend_api_key=resend_api_key, system_email_address=system_email_address
|
||||
mailgun_api_key=mailgun_api_key, mailgun_domain=mailgun_domain, system_email_address=system_email_address
|
||||
),
|
||||
payments_config=InternalPaymentsConfig(
|
||||
stripe=InternalStripeConfig(
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ hosting_config:
|
|||
endpoint_url: ""
|
||||
|
||||
mailing_config:
|
||||
resend_api_key: ""
|
||||
mailgun_api_key: ""
|
||||
mailgun_domain: ""
|
||||
system_email_adress: ""
|
||||
|
||||
database_config:
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ dependencies = [
|
|||
"pyyaml>=6.0.1",
|
||||
"redis>=5.0.7",
|
||||
"requests>=2.32.3",
|
||||
"resend>=2.4.0",
|
||||
"sqlmodel>=0.0.19",
|
||||
"tiktoken>=0.7.0",
|
||||
"uvicorn==0.30.1",
|
||||
|
|
|
|||
|
|
@ -1,19 +1,23 @@
|
|||
from pydantic import EmailStr
|
||||
import resend
|
||||
from config.config import get_learnhouse_config
|
||||
|
||||
from mailgun.client import Client
|
||||
|
||||
def send_email(to: EmailStr, subject: str, body: str):
|
||||
lh_config = get_learnhouse_config()
|
||||
params = {
|
||||
"from": "LearnHouse <" + lh_config.mailing_config.system_email_address + ">",
|
||||
"to": [to],
|
||||
|
||||
mailgun_api_key = lh_config.mailing_config.mailgun_api_key
|
||||
mailgun_domain = lh_config.mailing_config.mailgun_domain
|
||||
mailgun_client: Client = Client(auth=("api", mailgun_api_key))
|
||||
|
||||
data = {
|
||||
"from": "Learn with Mueez <" + lh_config.mailing_config.system_email_address + ">",
|
||||
"to": to,
|
||||
"subject": subject,
|
||||
"html": body,
|
||||
}
|
||||
|
||||
resend.api_key = lh_config.mailing_config.resend_api_key
|
||||
email = resend.Emails.send(params)
|
||||
|
||||
return email
|
||||
|
||||
# Send email
|
||||
req = mailgun_client.messages.create(data=data, domain=mailgun_domain)
|
||||
if id in req:
|
||||
return True
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -11,13 +11,12 @@ def send_account_creation_email(
|
|||
# send email
|
||||
return send_email(
|
||||
to=email,
|
||||
subject=f"Welcome to LearnHouse, {user.username}!",
|
||||
subject=f"Welcome to Learn with Mueez, {user.username}!",
|
||||
body=f"""
|
||||
<html>
|
||||
<body>
|
||||
<p>Hello {user.username}</p>
|
||||
<p>Welcome to LearnHouse! , get started by creating your own organization or join a one.</p>
|
||||
<p>Need some help to get started ? <a href="https://university.learnhouse.io">LearnHouse Academy</a></p>
|
||||
<p>Welcome to Learn with Mueez {user.username}! Get started by logging in at <a href="https://learn.mueezkhan.com">learn.mueezkhan.com</a> and starting a course.</p>
|
||||
<p>If you need any help, please reach out at <a href="https://mueezkhan.com/contact">mueezkhan.com/contact</a>.</p>
|
||||
</body>
|
||||
</html>
|
||||
""",
|
||||
|
|
@ -38,10 +37,11 @@ def send_password_reset_email(
|
|||
body=f"""
|
||||
<html>
|
||||
<body>
|
||||
<p>Hello {user.username}</p>
|
||||
<p>Hey {user.username}!</p>
|
||||
<p>You have requested to reset your password.</p>
|
||||
<p>Here is your reset code: {generated_reset_code}</p>
|
||||
<p>Click <a href="https://{organization.slug}.learnhouse.io/reset?orgslug={organization.slug}&email={email}&resetCode={generated_reset_code}">here</a> to reset your password.</p>
|
||||
<p>If you need any help, please reach out at <a href="https://mueezkhan.com/contact">mueezkhan.com/contact</a>.</p>
|
||||
</body>
|
||||
</html>
|
||||
""",
|
||||
|
|
|
|||
40
apps/api/uv.lock
generated
40
apps/api/uv.lock
generated
|
|
@ -1,4 +1,5 @@
|
|||
version = 1
|
||||
revision = 1
|
||||
requires-python = ">=3.12.3, <3.13.0"
|
||||
resolution-markers = [
|
||||
"python_full_version < '3.12.4'",
|
||||
|
|
@ -311,7 +312,7 @@ name = "click"
|
|||
version = "8.1.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
|
||||
wheels = [
|
||||
|
|
@ -1047,6 +1048,7 @@ dependencies = [
|
|||
{ name = "langchain-openai", version = "0.1.14", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12.4'" },
|
||||
{ name = "langchain-openai", version = "0.1.25", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12.4'" },
|
||||
{ name = "logfire", extra = ["sqlalchemy"] },
|
||||
{ name = "mailgun" },
|
||||
{ name = "openai" },
|
||||
{ name = "passlib" },
|
||||
{ name = "psycopg2-binary" },
|
||||
|
|
@ -1060,7 +1062,6 @@ dependencies = [
|
|||
{ name = "pyyaml" },
|
||||
{ name = "redis" },
|
||||
{ name = "requests" },
|
||||
{ name = "resend" },
|
||||
{ name = "sqlalchemy-utils" },
|
||||
{ name = "sqlmodel" },
|
||||
{ name = "stripe" },
|
||||
|
|
@ -1085,6 +1086,7 @@ requires-dist = [
|
|||
{ name = "langchain-community", specifier = ">=0.0.20" },
|
||||
{ name = "langchain-openai", specifier = ">=0.0.6" },
|
||||
{ name = "logfire", extras = ["sqlalchemy"], specifier = ">=3.8.0" },
|
||||
{ name = "mailgun", specifier = ">=1.0.2" },
|
||||
{ name = "openai", specifier = ">=1.50.2" },
|
||||
{ name = "passlib", specifier = ">=1.7.4" },
|
||||
{ name = "psycopg2-binary", specifier = ">=2.9.9" },
|
||||
|
|
@ -1098,7 +1100,6 @@ requires-dist = [
|
|||
{ name = "pyyaml", specifier = ">=6.0.1" },
|
||||
{ name = "redis", specifier = ">=5.0.7" },
|
||||
{ name = "requests", specifier = ">=2.32.3" },
|
||||
{ name = "resend", specifier = ">=2.4.0" },
|
||||
{ name = "sqlalchemy-utils", specifier = ">=0.41.2" },
|
||||
{ name = "sqlmodel", specifier = ">=0.0.19" },
|
||||
{ name = "stripe", specifier = ">=11.1.1" },
|
||||
|
|
@ -1130,6 +1131,18 @@ sqlalchemy = [
|
|||
{ name = "opentelemetry-instrumentation-sqlalchemy" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mailgun"
|
||||
version = "1.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "requests" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f4/37/daf8116c9937d97892efff08a2e34064dcfa2dd70065e12ec9366c1509a1/mailgun-1.0.2.tar.gz", hash = "sha256:5c7964426c823866e8de2b4e9062e2874494cfd92c59a0319996f573bea05507", size = 57593 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/26/bb/c97937ca4f75d221e5ff12d73a46c4fc770f26f942aad9fe09ff0aeea4d5/mailgun-1.0.2-py3-none-any.whl", hash = "sha256:79ac6c9e6c5166c97bd078756a278a19fcd3a9afaffc3747806026012b8343e3", size = 46536 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mako"
|
||||
version = "1.3.9"
|
||||
|
|
@ -1859,7 +1872,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
version = "2.32.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
|
|
@ -1867,9 +1880,9 @@ dependencies = [
|
|||
{ name = "idna" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1897,19 +1910,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resend"
|
||||
version = "2.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "requests" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/46/ff/f4235a93533cb04199ab50ef250afa514ada55a4a4b86e32e0c763931926/resend-2.6.0.tar.gz", hash = "sha256:e714210b761febd02a067a1ee00106b6aeb79c0a6dda80b58588b089550f0184", size = 13120 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/67/c8b10fa620303affa2240e7f45221a3c103a2e7d4f96dd8b9da4ec6cc84a/resend-2.6.0-py2.py3-none-any.whl", hash = "sha256:53f21fdee6ef18b2c90319b79b38fee048b6d47336283c0a1818bebcaf93c401", size = 19635 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rich"
|
||||
version = "13.9.4"
|
||||
|
|
@ -2123,7 +2123,7 @@ name = "tqdm"
|
|||
version = "4.67.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 }
|
||||
wheels = [
|
||||
|
|
|
|||
1564
apps/web/bun.lock
Normal file
1564
apps/web/bun.lock
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -28,9 +28,9 @@ services:
|
|||
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
||||
# Additional required environment variables
|
||||
- LEARNHOUSE_CONTACT_EMAIL=${LEARNHOUSE_CONTACT_EMAIL}
|
||||
- LEARNHOUSE_EMAIL_PROVIDER=${LEARNHOUSE_EMAIL_PROVIDER}
|
||||
- LEARNHOUSE_IS_AI_ENABLED=${LEARNHOUSE_IS_AI_ENABLED}
|
||||
- LEARNHOUSE_RESEND_API_KEY=${LEARNHOUSE_RESEND_API_KEY}
|
||||
- LEARNHOUSE_MAILGUN_API_KEY=${LEARNHOUSE_MAILGUN_API_KEY}
|
||||
- LEARNHOUSE_MAILGUN_DOMAIN=${LEARNHOUSE_MAILGUN_DOMAIN}
|
||||
- LEARNHOUSE_SELF_HOSTED=${LEARNHOUSE_SELF_HOSTED}
|
||||
- LEARNHOUSE_SITE_DESCRIPTION=${LEARNHOUSE_SITE_DESCRIPTION}
|
||||
- LEARNHOUSE_SITE_NAME=${LEARNHOUSE_SITE_NAME}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue