Spaces:
Sleeping
Sleeping
| import os | |
| from typing import Type | |
| from dotenv import load_dotenv | |
| from pydantic import BaseModel, Field | |
| from crewai.tools import BaseTool | |
| # Try importing sendgrid with fallback | |
| try: | |
| import sendgrid | |
| from sendgrid.helpers.mail import Mail | |
| SENDGRID_AVAILABLE = True | |
| print("β SendGrid package imported successfully") | |
| except ImportError: | |
| SENDGRID_AVAILABLE = False | |
| print("β SendGrid package not available - add 'sendgrid' to requirements.txt") | |
| # Load environment variables | |
| load_dotenv() | |
| class SendEmailInput(BaseModel): | |
| sender_email: str = Field(..., description="The email address of the visitor sending the message.") | |
| subject: str = Field(..., description="A concise subject line for the email.") | |
| body: str = Field(..., description="The main content of the email, formatted professionally.") | |
| class SendEmailTool(BaseTool): | |
| name: str = "SendEmailTool" | |
| description: str = "Sends an email using the SendGrid API." | |
| args_schema: Type[BaseModel] = SendEmailInput | |
| def _run(self, sender_email: str, subject: str, body: str) -> str: | |
| print("π Starting SendGrid email process...") | |
| # Check if sendgrid is available | |
| if not SENDGRID_AVAILABLE: | |
| return "β Error: SendGrid package not installed. Add 'sendgrid' to requirements.txt and redeploy." | |
| # Get environment variables | |
| api_key = os.getenv("SENDGRID_API_KEY") or os.environ.get("SENDGRID_API_KEY") | |
| verified_sender = os.getenv("VERIFIED_SENDER_EMAIL") or os.environ.get("VERIFIED_SENDER_EMAIL") | |
| receiver_email = os.getenv("RECEIVER_EMAIL") or os.environ.get("RECEIVER_EMAIL") | |
| # Debug info | |
| print(f"π Debug Info:") | |
| print(f" - SendGrid API Key present: {bool(api_key)}") | |
| print(f" - Verified sender present: {bool(verified_sender)}") | |
| print(f" - Receiver email present: {bool(receiver_email)}") | |
| print(f" - Contact sender: {sender_email}") | |
| # Check required variables | |
| if not api_key: | |
| return "β Error: SENDGRID_API_KEY not found in environment variables." | |
| if not verified_sender: | |
| return "β Error: VERIFIED_SENDER_EMAIL not found in environment variables." | |
| if not receiver_email: | |
| return "β Error: RECEIVER_EMAIL not found in environment variables." | |
| # Validate API key format | |
| if not api_key.startswith('SG.'): | |
| return f"β Error: Invalid SendGrid API key format. Should start with 'SG.' but starts with '{api_key[:5]}'." | |
| try: | |
| # Initialize SendGrid | |
| sg = sendgrid.SendGridAPIClient(api_key=api_key) | |
| print("β SendGrid client initialized") | |
| # Create HTML content (fix f-string backslash issue) | |
| formatted_body = body.replace('\n', '<br>').replace(chr(10), '<br>') | |
| html_content = f""" | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <style> | |
| body {{ font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }} | |
| .header {{ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; }} | |
| .content {{ background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 10px 0; }} | |
| .message {{ background: white; padding: 15px; border-left: 4px solid #667eea; margin: 15px 0; }} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <h1 style="margin: 0;">π§ New Portfolio Contact</h1> | |
| </div> | |
| <div class="content"> | |
| <p><strong>From:</strong> <a href="mailto:{sender_email}">{sender_email}</a></p> | |
| <p><strong>Subject:</strong> {subject}</p> | |
| <div class="message"> | |
| <h3>Message:</h3> | |
| {formatted_body} | |
| </div> | |
| <hr> | |
| <p style="color: #666; font-size: 12px;"> | |
| This message was sent through your portfolio contact form.<br> | |
| Reply to this email to respond directly to {sender_email} | |
| </p> | |
| </div> | |
| </body> | |
| </html> | |
| """ | |
| # Create message | |
| message = Mail( | |
| from_email=verified_sender, | |
| to_emails=receiver_email, | |
| subject=f"Portfolio Contact: {subject}", | |
| html_content=html_content | |
| ) | |
| message.reply_to = sender_email | |
| print(f"π§ Prepared email:") | |
| print(f" - From: {verified_sender}") | |
| print(f" - To: {receiver_email}") | |
| print(f" - Reply-to: {sender_email}") | |
| # Send email | |
| print("π€ Sending via SendGrid...") | |
| response = sg.send(message) | |
| print(f"π¨ Response: Status {response.status_code}") | |
| if response.status_code == 202: | |
| return f"β Email sent successfully via SendGrid! (Status: {response.status_code})" | |
| elif response.status_code == 401: | |
| return "β SendGrid Error: Invalid API key" | |
| elif response.status_code == 403: | |
| return "β SendGrid Error: Permission denied - check sender email verification" | |
| else: | |
| return f"β οΈ SendGrid Response: Status {response.status_code}" | |
| except Exception as e: | |
| error_msg = str(e) | |
| print(f"β SendGrid Error: {type(e).__name__}: {error_msg}") | |
| if "Unauthorized" in error_msg or "401" in error_msg: | |
| return "β SendGrid: Invalid API key" | |
| elif "Forbidden" in error_msg or "403" in error_msg: | |
| return "β SendGrid: Sender email not verified or insufficient permissions" | |
| else: | |
| return f"β SendGrid Error: {error_msg}" |