diff --git a/application.py b/application.py index 50a45cf..8526585 100644 --- a/application.py +++ b/application.py @@ -13,6 +13,7 @@ from motor.motor_asyncio import AsyncIOMotorClient from src.main import PropertyResearchGraph from src.utils.twilio import verify_phone_number +from src.utils.send_email import send_email # Configure logging logging.basicConfig( @@ -68,6 +69,7 @@ class JobStatus(str, Enum): class AddressRequest(BaseModel): addresses: List[str] = Field(..., min_items=1, max_items=MAX_ADDRESSES) + email: Optional[str] = Field(None, description="The email address of the sender") @validator("addresses") def validate_addresses(cls, addresses): @@ -169,13 +171,15 @@ async def process_address(job_id: str, address: str, index: int): await save_job_to_mongodb(job) -async def process_addresses(job_id: str, addresses: List[str]): +async def process_addresses(job_id: str, addresses: List[str], email: str): """Process multiple addresses sequentially with a delay between each.""" try: for i, address in enumerate(addresses): await process_address(job_id, address, i) if i < len(addresses) - 1: # Don't delay after the last address await asyncio.sleep(PROCESSING_DELAY) + if email: + await send_email(recipient_email=email) except Exception as e: logger.error(f"Error in background processing: {e}") job = jobs[job_id] @@ -211,7 +215,7 @@ async def start_research(request: AddressRequest, background_tasks: BackgroundTa await save_job_to_mongodb(job) # Start background processing - background_tasks.add_task(process_addresses, job_id, request.addresses) + background_tasks.add_task(process_addresses, job_id, request.addresses, request.email) return job diff --git a/requirements.txt b/requirements.txt index 25a6a94..f771095 100644 --- a/requirements.txt +++ b/requirements.txt @@ -50,3 +50,4 @@ asyncio>=3.4.3 # For asynchronous programming uuid>=1.30 # For generating unique identifiers starlette>=0.27.0 # FastAPI dependency twilio==9.5.1 +sendgrid==6.11.0 diff --git a/src/utils/send_email.py b/src/utils/send_email.py new file mode 100644 index 0000000..7257f20 --- /dev/null +++ b/src/utils/send_email.py @@ -0,0 +1,70 @@ + +import os +import logging +import sendgrid +from sendgrid.helpers.mail import Mail, Email, To, Content, Attachment, FileContent, FileName, FileType, Disposition +import base64 + +logger = logging.getLogger(__name__) + +sg = sendgrid.SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY')) + +async def send_email(recipient_email: str): + """Send an email containing the property research results to the recipient.""" + # Create email with attachment + from_email = Email("alukachiama@gmail.com") + to_email = To(recipient_email) + subject = f"Property Research Results" + + # Create the email content + content = Content( + "text/html", + f""" + +
+Please find attached the property research results for the addresses requested.
+The Excel file contains detailed information about property owners, contact details, and other relevant data.
+Best regards,
+Property Research System
+ + + """ + ) + + # Create the email + message = Mail( + from_email=from_email, + to_emails=to_email, + subject=subject, + html_content=content + ) + + results_dir = os.path.join(os.getcwd(), "results") + + if results_dir: + excel_path = os.path.join(results_dir, "property_owners.xlsx") + + # Create the attachment + with open(excel_path, 'rb') as f: + data = f.read() + f.close() + + encoded = base64.b64encode(data).decode() + attachment = Attachment() + attachment.file_content = FileContent(encoded) + attachment.file_type = FileType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + attachment.file_name = FileName(os.path.basename(excel_path)) + attachment.disposition = Disposition('attachment') + message.attachment = attachment + + # Send email + response = sg.client.mail.send.post(request_body=message.get()) + + if response.status_code == 202: + logger.info(f"✅ Email sent successfully with property research results for addresses provided") + print(f"✅ Email sent successfully to {recipient_email}") + else: + logger.error(f"❌ Failed to send email. Status code: {response.status_code}") + print(f"❌ Failed to send email. Status code: {response.status_code}")