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
8 changes: 6 additions & 2 deletions application.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
70 changes: 70 additions & 0 deletions src/utils/send_email.py
Original file line number Diff line number Diff line change
@@ -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"""
<html>
<body>
<h2>Property Research Results</h2>
<p>Please find attached the property research results for the addresses requested.</p>
<p>The Excel file contains detailed information about property owners, contact details, and other relevant data.</p>
<br>
<p>Best regards,</p>
<p>Property Research System</p>
</body>
</html>
"""
)

# 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}")