from dotenv import load_dotenv import os, requests import smtplib from email.mime.text import MIMEText load_dotenv() # — DEBUG: confirm env-vars are loading correctly — print("→ ZAMMAD_TOKEN:", repr(os.getenv("ZAMMAD_TOKEN"))) print("→ ZAMMAD_URL: ", repr(os.getenv("ZAMMAD_URL"))) print("→ TWENTY_API_KEY:", repr(os.getenv("TWENTY_API_KEY"))) me = requests.get( f"{os.getenv('ZAMMAD_URL')}/api/v1/users/me", headers={"Authorization": f"Token token={os.getenv('ZAMMAD_TOKEN')}"} ) print("→ GET /users/me:", me.status_code, me.text) def is_business_opportunity(text): keywords = ["partner", "quote", "enterprise", "demo", "pricing", "ai", "onboarding"] return any(word in text.lower() for word in keywords) def push_to_twenty(submission): url = f"{os.getenv('TWENTY_API')}/people" headers = { "Authorization": f"Bearer {os.getenv('TWENTY_API_KEY')}", "Content-Type": "application/json" } payload = { "name": { "firstName": submission["first_name"], "lastName": submission["last_name"] }, "position": "first", "emails": { "primaryEmail": submission["email"], "additionalEmails": [] } } res = requests.post(url, headers=headers, json=payload) if res.status_code not in (200, 201): print("→ TwentyCRM error:", res.status_code, res.text) res.raise_for_status() return res.json()["data"]["createPerson"]["id"] def create_zammad_ticket(submission, is_lead): """ Create a new ticket in Zammad (always in 'Users' group). Title = "Sales: {Name}" if lead, else "Other: {Name}". If is_lead, article is an email to Gabriele & Scott; otherwise a note. """ ZAMMAD_URL = os.getenv('ZAMMAD_URL') ZAMMAD_TOKEN = os.getenv('ZAMMAD_TOKEN') ZAMMAD_GROUP = os.getenv('ZAMMAD_GROUP') # must be "Users" url = f"{ZAMMAD_URL}/api/v1/tickets" headers = { "Authorization": f"Token token={ZAMMAD_TOKEN}", "Content-Type": "application/json" } name = f"{submission['first_name']} {submission['last_name']}" ticket_title = f"{'Sales' if is_lead else 'Other'}: {name}" customer = submission["email"] if is_lead: # Email‐style article to_addrs = "daniel.grozdanovic@icloud.com" #gabriele.sanguigno@toothfairyai.com, scott.aquilina@toothfairyai.com article_subject = ticket_title article_body = ( f"Name: {name}\n" f"Email: {customer}\n\n" f"Message:\n{submission['message']}" ) article = { "to": to_addrs, "subject": article_subject, "body": article_body, "note": submission["message"], "type": "email", "internal": False } else: # Internal note article = { "subject": ticket_title, "body": submission["message"], "note": submission["message"], "type": "note", "internal": False } payload = { "title": ticket_title, "customer": customer, "group": ZAMMAD_GROUP, "article": article } res = requests.post(url, headers=headers, json=payload) if res.status_code not in (200, 201): print("→ Zammad create-ticket ERROR:", res.status_code, res.text) print("→ Payload was:", payload) res.raise_for_status() return res.json() def tag_zammad_ticket(ticket_id, tag): url = f"{os.getenv('ZAMMAD_URL')}/api/v1/tickets/{ticket_id}" headers = { "Authorization": f"Token token={os.getenv('ZAMMAD_TOKEN')}", "Content-Type": "application/json" } res = requests.put(url, headers=headers, json={"tags":[tag]}) if res.status_code not in (200, 201): print("→ Zammad tag-ticket ERROR:", res.status_code, res.text) res.raise_for_status() return res.json() def send_email(to, subject, body): msg = MIMEText(body) msg["From"] = os.getenv("SMTP_USERNAME") msg["To"] = to msg["Subject"] = subject with smtplib.SMTP(os.getenv("SMTP_SERVER"), int(os.getenv("SMTP_PORT"))) as server: server.starttls() server.login(os.getenv("SMTP_USERNAME"), os.getenv("SMTP_PASSWORD")) server.send_message(msg) def process_submission(submission): is_lead = is_business_opportunity(submission["message"]) crm_id = push_to_twenty(submission) tag = "sales" if is_lead else "other" # Capture the full name here so it's available for internal notifications name = f"{submission['first_name']} {submission['last_name']}" # 1) Create the ticket with the correct title & article ticket = create_zammad_ticket(submission, is_lead) # 2) Tag the ticket tag_zammad_ticket(ticket["id"], tag) # 3) Customer confirmation send_email( to=submission["email"], subject=os.getenv("CUSTOMER_REPLY_SUBJECT"), body=( f"Hi {submission['first_name']},\n\n" f"Your ticket “{ticket['title']}” (ID #{ticket['id']}) is in our system—" "we'll be in touch soon.\n\n" "Cheers,\nThe ToothFairyAI Team" ) ) # 4) Internal notification internal_to = os.getenv("SALES_EMAIL") if is_lead else os.getenv("SUPPORT_EMAIL") internal_subj = "🚀 New Business Lead" if is_lead else "ℹ️ New Inquiry" send_email( to=internal_to, subject=internal_subj, body=( f"CRM ID: {crm_id}\n" f"Zammad Ticket: #{ticket['id']} (Title: {ticket['title']}, Tags: {tag})\n" f"Name: {name}\n" f"Email: {submission['email']}\n" f"Message: {submission['message']}" ) ) if __name__ == "__main__": sample = { "first_name": "Joe", "last_name": "Smith", "email": "support@toothfairyai.com", "message": "Interested in a product demo" } process_submission(sample)