Snapshot: full project state
This commit is contained in:
71
emailer.py
Normal file
71
emailer.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# Procyon — email sending via SMTP. Configurable; safe when unconfigured.
|
||||
|
||||
import smtplib
|
||||
import ssl
|
||||
from email.message import EmailMessage
|
||||
|
||||
import db
|
||||
|
||||
|
||||
def configured():
|
||||
return bool(db.get_setting('smtp_user', '')) and bool(db.get_setting('smtp_pass', ''))
|
||||
|
||||
|
||||
def send(subject, body, to_email, attachment_path=None):
|
||||
host = db.get_setting('smtp_host', 'smtp.mail.me.com')
|
||||
port = int(db.get_setting('smtp_port', '587'))
|
||||
user = db.get_setting('smtp_user', '')
|
||||
pw = db.get_setting('smtp_pass', '')
|
||||
from_email = db.get_setting('from_email', 'indianaholmes1@icloud.com')
|
||||
from_name = db.get_setting('from_name', 'Indiana Holmes')
|
||||
|
||||
if not (user and pw):
|
||||
raise RuntimeError('SMTP not configured — add iCloud app-specific password in Settings')
|
||||
|
||||
msg = EmailMessage()
|
||||
msg['Subject'] = subject
|
||||
msg['From'] = f'{from_name} <{from_email}>'
|
||||
msg['To'] = to_email
|
||||
msg['Reply-To'] = from_email
|
||||
msg.set_content(body)
|
||||
|
||||
if attachment_path:
|
||||
import os
|
||||
with open(attachment_path, 'rb') as f:
|
||||
data = f.read()
|
||||
msg.add_attachment(data, maintype='application', subtype='pdf',
|
||||
filename=os.path.basename(attachment_path))
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
with smtplib.SMTP(host, port, timeout=30) as s:
|
||||
s.starttls(context=ctx)
|
||||
s.login(user, pw)
|
||||
s.send_message(msg)
|
||||
return True
|
||||
|
||||
|
||||
def auto_send(app_id):
|
||||
"""Auto-approve + send a prepared application to its scraped contact email — no human
|
||||
gate. Guarded: only sends when a contact email was scraped, SMTP is configured, and the
|
||||
self-audit passes (no fabrication/garbage). Returns (sent: bool, message: str)."""
|
||||
import audit
|
||||
app = db.get_application(app_id)
|
||||
if not app:
|
||||
return False, 'app not found'
|
||||
job = db.get_job(app['job_id'])
|
||||
to_email = (job.get('contact_email') or '').strip() if job else ''
|
||||
if not to_email:
|
||||
return False, 'no contact email scraped'
|
||||
if not configured():
|
||||
return False, 'SMTP not configured'
|
||||
checks = db.get_audit(app_id)
|
||||
if not audit.all_pass(checks):
|
||||
return False, 'audit has FAIL items'
|
||||
try:
|
||||
send(app['email_subject'], app['email_body'], to_email,
|
||||
attachment_path=app.get('tailored_pdf') or app.get('resume_path'))
|
||||
db.update_application(app_id, status='sent', notes=f'auto-sent to {to_email}')
|
||||
db.set_job_status(app['job_id'], 'sent')
|
||||
return True, f'sent to {to_email}'
|
||||
except Exception as e:
|
||||
return False, f'send error: {e}'
|
||||
Reference in New Issue
Block a user