Merge branch 'release/0.0.10'
This commit is contained in:
commit
0b12acd4ac
13
.env.example
13
.env.example
@ -34,9 +34,22 @@ JWT_EXPIRATION_TIME=3600
|
|||||||
# Encryption key for API keys
|
# Encryption key for API keys
|
||||||
ENCRYPTION_KEY="your-encryption-key"
|
ENCRYPTION_KEY="your-encryption-key"
|
||||||
|
|
||||||
|
# Email provider settings
|
||||||
|
EMAIL_PROVIDER="sendgrid"
|
||||||
|
|
||||||
# SendGrid
|
# SendGrid
|
||||||
SENDGRID_API_KEY="your-sendgrid-api-key"
|
SENDGRID_API_KEY="your-sendgrid-api-key"
|
||||||
EMAIL_FROM="noreply@yourdomain.com"
|
EMAIL_FROM="noreply@yourdomain.com"
|
||||||
|
|
||||||
|
# SMTP settings
|
||||||
|
SMTP_HOST="your-smtp-host"
|
||||||
|
SMTP_FROM="noreply-smtp@yourdomain.com"
|
||||||
|
SMTP_USER="your-smtp-username"
|
||||||
|
SMTP_PASSWORD="your-smtp-password"
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_USE_TLS=true
|
||||||
|
SMTP_USE_SSL=false
|
||||||
|
|
||||||
APP_URL="https://yourdomain.com"
|
APP_URL="https://yourdomain.com"
|
||||||
|
|
||||||
LANGFUSE_PUBLIC_KEY="your-langfuse-public-key"
|
LANGFUSE_PUBLIC_KEY="your-langfuse-public-key"
|
||||||
|
21
.github/workflows/docker-image.yml
vendored
21
.github/workflows/docker-image.yml
vendored
@ -7,8 +7,10 @@ on:
|
|||||||
branches: ["main", "develop"]
|
branches: ["main", "develop"]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: ghcr.io
|
GHCR_REGISTRY: ghcr.io
|
||||||
|
DOCKERHUB_REGISTRY: docker.io
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
DOCKERHUB_IMAGE: ${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-push:
|
build-and-push:
|
||||||
@ -21,18 +23,27 @@ jobs:
|
|||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Log in to the Container registry
|
- name: Log in to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.GHCR_REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Extract metadata (tags, labels) for Docker
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata for Docker
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
images: |
|
||||||
|
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE }}
|
||||||
tags: |
|
tags: |
|
||||||
type=raw,value=develop,enable=${{ github.ref == format('refs/heads/{0}', 'develop') }}
|
type=raw,value=develop,enable=${{ github.ref == format('refs/heads/{0}', 'develop') }}
|
||||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||||
|
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Improve context management in agent execution
|
- Improve context management in agent execution
|
||||||
- Add file support for A2A protocol (Agent-to-Agent) endpoints
|
- Add file support for A2A protocol (Agent-to-Agent) endpoints
|
||||||
- Implement multimodal content processing in A2A messages
|
- Implement multimodal content processing in A2A messages
|
||||||
|
- Add SMTP email provider support as alternative to SendGrid
|
||||||
|
|
||||||
## [0.0.9] - 2025-05-13
|
## [0.0.9] - 2025-05-13
|
||||||
|
|
||||||
|
28
README.md
28
README.md
@ -331,7 +331,7 @@ Authorization: Bearer your-token-jwt
|
|||||||
- **Uvicorn**: ASGI server
|
- **Uvicorn**: ASGI server
|
||||||
- **Redis**: Cache and session management
|
- **Redis**: Cache and session management
|
||||||
- **JWT**: Secure token authentication
|
- **JWT**: Secure token authentication
|
||||||
- **SendGrid**: Email service for notifications
|
- **SendGrid/SMTP**: Email service for notifications (configurable)
|
||||||
- **Jinja2**: Template engine for email rendering
|
- **Jinja2**: Template engine for email rendering
|
||||||
- **Bcrypt**: Password hashing and security
|
- **Bcrypt**: Password hashing and security
|
||||||
- **LangGraph**: Framework for building stateful, multi-agent workflows
|
- **LangGraph**: Framework for building stateful, multi-agent workflows
|
||||||
@ -469,7 +469,9 @@ You'll also need the following accounts/API keys:
|
|||||||
- Python 3.10+
|
- Python 3.10+
|
||||||
- PostgreSQL
|
- PostgreSQL
|
||||||
- Redis
|
- Redis
|
||||||
- SendGrid Account (for email sending)
|
- Email provider:
|
||||||
|
- SendGrid Account (if using SendGrid email provider)
|
||||||
|
- SMTP Server (if using SMTP email provider)
|
||||||
|
|
||||||
## 🔧 Installation
|
## 🔧 Installation
|
||||||
|
|
||||||
@ -566,11 +568,23 @@ JWT_SECRET_KEY="your-jwt-secret-key"
|
|||||||
JWT_ALGORITHM="HS256"
|
JWT_ALGORITHM="HS256"
|
||||||
JWT_EXPIRATION_TIME=30 # In seconds
|
JWT_EXPIRATION_TIME=30 # In seconds
|
||||||
|
|
||||||
# SendGrid for emails
|
# Email provider configuration
|
||||||
|
EMAIL_PROVIDER="sendgrid" # Options: "sendgrid" or "smtp"
|
||||||
|
|
||||||
|
# SendGrid (if EMAIL_PROVIDER=sendgrid)
|
||||||
SENDGRID_API_KEY="your-sendgrid-api-key"
|
SENDGRID_API_KEY="your-sendgrid-api-key"
|
||||||
EMAIL_FROM="noreply@yourdomain.com"
|
EMAIL_FROM="noreply@yourdomain.com"
|
||||||
APP_URL="https://yourdomain.com"
|
APP_URL="https://yourdomain.com"
|
||||||
|
|
||||||
|
# SMTP (if EMAIL_PROVIDER=smtp)
|
||||||
|
SMTP_FROM="noreply-smtp@yourdomain.com"
|
||||||
|
SMTP_USER="your-smtp-username"
|
||||||
|
SMTP_PASSWORD="your-smtp-password"
|
||||||
|
SMTP_HOST="your-smtp-host"
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_USE_TLS=true
|
||||||
|
SMTP_USE_SSL=false
|
||||||
|
|
||||||
# Encryption for API keys
|
# Encryption for API keys
|
||||||
ENCRYPTION_KEY="your-encryption-key"
|
ENCRYPTION_KEY="your-encryption-key"
|
||||||
```
|
```
|
||||||
@ -787,8 +801,12 @@ The main environment variables used by the API container:
|
|||||||
- `POSTGRES_CONNECTION_STRING`: PostgreSQL connection string
|
- `POSTGRES_CONNECTION_STRING`: PostgreSQL connection string
|
||||||
- `REDIS_HOST`: Redis host (use "redis" when running with Docker)
|
- `REDIS_HOST`: Redis host (use "redis" when running with Docker)
|
||||||
- `JWT_SECRET_KEY`: Secret key for JWT token generation
|
- `JWT_SECRET_KEY`: Secret key for JWT token generation
|
||||||
- `SENDGRID_API_KEY`: SendGrid API key for sending emails
|
- `EMAIL_PROVIDER`: Email provider to use ("sendgrid" or "smtp")
|
||||||
- `EMAIL_FROM`: Email used as sender
|
- `SENDGRID_API_KEY`: SendGrid API key (if using SendGrid)
|
||||||
|
- `EMAIL_FROM`: Email used as sender (for SendGrid)
|
||||||
|
- `SMTP_FROM`: Email used as sender (for SMTP)
|
||||||
|
- `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASSWORD`: SMTP server configuration
|
||||||
|
- `SMTP_USE_TLS`, `SMTP_USE_SSL`: SMTP security settings
|
||||||
- `APP_URL`: Base URL of the application
|
- `APP_URL`: Base URL of the application
|
||||||
|
|
||||||
## 🔒 Secure API Key Management
|
## 🔒 Secure API Key Management
|
||||||
|
@ -81,9 +81,22 @@ class Settings(BaseSettings):
|
|||||||
# Encryption settings
|
# Encryption settings
|
||||||
ENCRYPTION_KEY: str = os.getenv("ENCRYPTION_KEY", secrets.token_urlsafe(32))
|
ENCRYPTION_KEY: str = os.getenv("ENCRYPTION_KEY", secrets.token_urlsafe(32))
|
||||||
|
|
||||||
|
# Email provider settings
|
||||||
|
EMAIL_PROVIDER: str = os.getenv("EMAIL_PROVIDER", "sendgrid")
|
||||||
|
|
||||||
# SendGrid settings
|
# SendGrid settings
|
||||||
SENDGRID_API_KEY: str = os.getenv("SENDGRID_API_KEY", "")
|
SENDGRID_API_KEY: str = os.getenv("SENDGRID_API_KEY", "")
|
||||||
EMAIL_FROM: str = os.getenv("EMAIL_FROM", "noreply@yourdomain.com")
|
EMAIL_FROM: str = os.getenv("EMAIL_FROM", "noreply@yourdomain.com")
|
||||||
|
|
||||||
|
# SMTP settings
|
||||||
|
SMTP_HOST: str = os.getenv("SMTP_HOST", "")
|
||||||
|
SMTP_PORT: int = int(os.getenv("SMTP_PORT", 587))
|
||||||
|
SMTP_USER: str = os.getenv("SMTP_USER", "")
|
||||||
|
SMTP_PASSWORD: str = os.getenv("SMTP_PASSWORD", "")
|
||||||
|
SMTP_USE_TLS: bool = os.getenv("SMTP_USE_TLS", "true").lower() == "true"
|
||||||
|
SMTP_USE_SSL: bool = os.getenv("SMTP_USE_SSL", "false").lower() == "true"
|
||||||
|
SMTP_FROM: str = os.getenv("SMTP_FROM", "")
|
||||||
|
|
||||||
APP_URL: str = os.getenv("APP_URL", "http://localhost:8000")
|
APP_URL: str = os.getenv("APP_URL", "http://localhost:8000")
|
||||||
|
|
||||||
# Server settings
|
# Server settings
|
||||||
|
@ -33,7 +33,11 @@ import logging
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||||
import os
|
import os
|
||||||
|
import smtplib
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from config.settings import settings
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -67,6 +71,110 @@ def _render_template(template_name: str, context: dict) -> str:
|
|||||||
return f"<p>Could not display email content. Please access {context.get('verification_link', '') or context.get('reset_link', '')}</p>"
|
return f"<p>Could not display email content. Please access {context.get('verification_link', '') or context.get('reset_link', '')}</p>"
|
||||||
|
|
||||||
|
|
||||||
|
def _send_email_sendgrid(to_email: str, subject: str, html_content: str) -> bool:
|
||||||
|
"""
|
||||||
|
Send an email using SendGrid provider
|
||||||
|
|
||||||
|
Args:
|
||||||
|
to_email: Recipient's email
|
||||||
|
subject: Email subject
|
||||||
|
html_content: HTML content of the email
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the email was sent successfully, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
sg = sendgrid.SendGridAPIClient(api_key=settings.SENDGRID_API_KEY)
|
||||||
|
from_email = Email(settings.EMAIL_FROM)
|
||||||
|
to_email = To(to_email)
|
||||||
|
content = Content("text/html", html_content)
|
||||||
|
|
||||||
|
mail = Mail(from_email, to_email, subject, content)
|
||||||
|
response = sg.client.mail.send.post(request_body=mail.get())
|
||||||
|
|
||||||
|
if response.status_code >= 200 and response.status_code < 300:
|
||||||
|
logger.info(f"Email sent via SendGrid to {to_email}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"Failed to send email via SendGrid to {to_email}. Status: {response.status_code}"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error sending email via SendGrid to {to_email}: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _send_email_smtp(to_email: str, subject: str, html_content: str) -> bool:
|
||||||
|
"""
|
||||||
|
Send an email using SMTP provider
|
||||||
|
|
||||||
|
Args:
|
||||||
|
to_email: Recipient's email
|
||||||
|
subject: Email subject
|
||||||
|
html_content: HTML content of the email
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the email was sent successfully, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Create message container
|
||||||
|
msg = MIMEMultipart('alternative')
|
||||||
|
msg['Subject'] = subject
|
||||||
|
msg['From'] = settings.SMTP_FROM or settings.EMAIL_FROM
|
||||||
|
msg['To'] = to_email
|
||||||
|
|
||||||
|
# Attach HTML content
|
||||||
|
part = MIMEText(html_content, 'html')
|
||||||
|
msg.attach(part)
|
||||||
|
|
||||||
|
# Setup SMTP server
|
||||||
|
if settings.SMTP_USE_SSL:
|
||||||
|
server = smtplib.SMTP_SSL(settings.SMTP_HOST, settings.SMTP_PORT)
|
||||||
|
else:
|
||||||
|
server = smtplib.SMTP(settings.SMTP_HOST, settings.SMTP_PORT)
|
||||||
|
if settings.SMTP_USE_TLS:
|
||||||
|
server.starttls()
|
||||||
|
|
||||||
|
# Login if credentials are provided
|
||||||
|
if settings.SMTP_USER and settings.SMTP_PASSWORD:
|
||||||
|
server.login(settings.SMTP_USER, settings.SMTP_PASSWORD)
|
||||||
|
|
||||||
|
# Send email
|
||||||
|
server.sendmail(
|
||||||
|
settings.SMTP_FROM or settings.EMAIL_FROM,
|
||||||
|
to_email,
|
||||||
|
msg.as_string()
|
||||||
|
)
|
||||||
|
server.quit()
|
||||||
|
|
||||||
|
logger.info(f"Email sent via SMTP to {to_email}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error sending email via SMTP to {to_email}: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def send_email(to_email: str, subject: str, html_content: str) -> bool:
|
||||||
|
"""
|
||||||
|
Send an email using the configured provider
|
||||||
|
|
||||||
|
Args:
|
||||||
|
to_email: Recipient's email
|
||||||
|
subject: Email subject
|
||||||
|
html_content: HTML content of the email
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the email was sent successfully, False otherwise
|
||||||
|
"""
|
||||||
|
if settings.EMAIL_PROVIDER.lower() == "smtp":
|
||||||
|
return _send_email_smtp(to_email, subject, html_content)
|
||||||
|
else: # Default to SendGrid
|
||||||
|
return _send_email_sendgrid(to_email, subject, html_content)
|
||||||
|
|
||||||
|
|
||||||
def send_verification_email(email: str, token: str) -> bool:
|
def send_verification_email(email: str, token: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Send a verification email to the user
|
Send a verification email to the user
|
||||||
@ -79,40 +187,22 @@ def send_verification_email(email: str, token: str) -> bool:
|
|||||||
bool: True if the email was sent successfully, False otherwise
|
bool: True if the email was sent successfully, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
sg = sendgrid.SendGridAPIClient(api_key=os.getenv("SENDGRID_API_KEY"))
|
|
||||||
from_email = Email(os.getenv("EMAIL_FROM"))
|
|
||||||
to_email = To(email)
|
|
||||||
subject = "Email Verification - Evo AI"
|
subject = "Email Verification - Evo AI"
|
||||||
|
verification_link = f"{settings.APP_URL}/security/verify-email?code={token}"
|
||||||
verification_link = f"{os.getenv('APP_URL')}/security/verify-email?code={token}"
|
|
||||||
|
|
||||||
html_content = _render_template(
|
html_content = _render_template(
|
||||||
"verification_email",
|
"verification_email",
|
||||||
{
|
{
|
||||||
"verification_link": verification_link,
|
"verification_link": verification_link,
|
||||||
"user_name": email.split("@")[
|
"user_name": email.split("@")[0], # Use part of the email as temporary name
|
||||||
0
|
|
||||||
], # Use part of the email as temporary name
|
|
||||||
"current_year": datetime.now().year,
|
"current_year": datetime.now().year,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
content = Content("text/html", html_content)
|
return send_email(email, subject, html_content)
|
||||||
|
|
||||||
mail = Mail(from_email, to_email, subject, content)
|
|
||||||
response = sg.client.mail.send.post(request_body=mail.get())
|
|
||||||
|
|
||||||
if response.status_code >= 200 and response.status_code < 300:
|
|
||||||
logger.info(f"Verification email sent to {email}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error(
|
|
||||||
f"Failed to send verification email to {email}. Status: {response.status_code}"
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error sending verification email to {email}: {str(e)}")
|
logger.error(f"Error preparing verification email to {email}: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -128,40 +218,22 @@ def send_password_reset_email(email: str, token: str) -> bool:
|
|||||||
bool: True if the email was sent successfully, False otherwise
|
bool: True if the email was sent successfully, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
sg = sendgrid.SendGridAPIClient(api_key=os.getenv("SENDGRID_API_KEY"))
|
|
||||||
from_email = Email(os.getenv("EMAIL_FROM"))
|
|
||||||
to_email = To(email)
|
|
||||||
subject = "Password Reset - Evo AI"
|
subject = "Password Reset - Evo AI"
|
||||||
|
reset_link = f"{settings.APP_URL}/security/reset-password?token={token}"
|
||||||
reset_link = f"{os.getenv('APP_URL')}/security/reset-password?token={token}"
|
|
||||||
|
|
||||||
html_content = _render_template(
|
html_content = _render_template(
|
||||||
"password_reset",
|
"password_reset",
|
||||||
{
|
{
|
||||||
"reset_link": reset_link,
|
"reset_link": reset_link,
|
||||||
"user_name": email.split("@")[
|
"user_name": email.split("@")[0], # Use part of the email as temporary name
|
||||||
0
|
|
||||||
], # Use part of the email as temporary name
|
|
||||||
"current_year": datetime.now().year,
|
"current_year": datetime.now().year,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
content = Content("text/html", html_content)
|
return send_email(email, subject, html_content)
|
||||||
|
|
||||||
mail = Mail(from_email, to_email, subject, content)
|
|
||||||
response = sg.client.mail.send.post(request_body=mail.get())
|
|
||||||
|
|
||||||
if response.status_code >= 200 and response.status_code < 300:
|
|
||||||
logger.info(f"Password reset email sent to {email}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error(
|
|
||||||
f"Failed to send password reset email to {email}. Status: {response.status_code}"
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error sending password reset email to {email}: {str(e)}")
|
logger.error(f"Error preparing password reset email to {email}: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -177,12 +249,8 @@ def send_welcome_email(email: str, user_name: str = None) -> bool:
|
|||||||
bool: True if the email was sent successfully, False otherwise
|
bool: True if the email was sent successfully, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
sg = sendgrid.SendGridAPIClient(api_key=os.getenv("SENDGRID_API_KEY"))
|
|
||||||
from_email = Email(os.getenv("EMAIL_FROM"))
|
|
||||||
to_email = To(email)
|
|
||||||
subject = "Welcome to Evo AI"
|
subject = "Welcome to Evo AI"
|
||||||
|
dashboard_link = f"{settings.APP_URL}/dashboard"
|
||||||
dashboard_link = f"{os.getenv('APP_URL')}/dashboard"
|
|
||||||
|
|
||||||
html_content = _render_template(
|
html_content = _render_template(
|
||||||
"welcome_email",
|
"welcome_email",
|
||||||
@ -193,22 +261,10 @@ def send_welcome_email(email: str, user_name: str = None) -> bool:
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
content = Content("text/html", html_content)
|
return send_email(email, subject, html_content)
|
||||||
|
|
||||||
mail = Mail(from_email, to_email, subject, content)
|
|
||||||
response = sg.client.mail.send.post(request_body=mail.get())
|
|
||||||
|
|
||||||
if response.status_code >= 200 and response.status_code < 300:
|
|
||||||
logger.info(f"Welcome email sent to {email}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error(
|
|
||||||
f"Failed to send welcome email to {email}. Status: {response.status_code}"
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error sending welcome email to {email}: {str(e)}")
|
logger.error(f"Error preparing welcome email to {email}: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -228,14 +284,8 @@ def send_account_locked_email(
|
|||||||
bool: True if the email was sent successfully, False otherwise
|
bool: True if the email was sent successfully, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
sg = sendgrid.SendGridAPIClient(api_key=os.getenv("SENDGRID_API_KEY"))
|
|
||||||
from_email = Email(os.getenv("EMAIL_FROM"))
|
|
||||||
to_email = To(email)
|
|
||||||
subject = "Security Alert - Account Locked"
|
subject = "Security Alert - Account Locked"
|
||||||
|
reset_link = f"{settings.APP_URL}/security/reset-password?token={reset_token}"
|
||||||
reset_link = (
|
|
||||||
f"{os.getenv('APP_URL')}/security/reset-password?token={reset_token}"
|
|
||||||
)
|
|
||||||
|
|
||||||
html_content = _render_template(
|
html_content = _render_template(
|
||||||
"account_locked",
|
"account_locked",
|
||||||
@ -248,20 +298,8 @@ def send_account_locked_email(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
content = Content("text/html", html_content)
|
return send_email(email, subject, html_content)
|
||||||
|
|
||||||
mail = Mail(from_email, to_email, subject, content)
|
|
||||||
response = sg.client.mail.send.post(request_body=mail.get())
|
|
||||||
|
|
||||||
if response.status_code >= 200 and response.status_code < 300:
|
|
||||||
logger.info(f"Account locked email sent to {email}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error(
|
|
||||||
f"Failed to send account locked email to {email}. Status: {response.status_code}"
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error sending account locked email to {email}: {str(e)}")
|
logger.error(f"Error preparing account locked email to {email}: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
Loading…
Reference in New Issue
Block a user