Email Templates & Notifications
All emails are sent via Nodemailer through Hostinger SMTP (smtp.hostinger.com:465). Two transporters exist: a primary one for system alerts and a formatted one for client-facing branded emails.
Client-Facing Emails
Package Status Email
Function: sendFormattedEmailWithData (HTTP) / generatePackageStatusEmail (helper)
Trigger: Manual HTTP call with ?clientID=...&containerID=...&test=0/1/2
Recipients: Client email from Clients collection
Test param: 0 = client only, 1 = client + test addresses, 2 = test only
Template:
- Full branded HTML with MaxShipping logo
- Blue accent (#0066cc)
- Client greeting with first name
- Container name and ship date
- Estimated arrival: ship date + 11 days
- Package table: tracking number, description, dimensions, status
- Status color coding: green (delivered/picked up), blue (in transit), orange (processing)
Invoice & Payment Emails
Invoice Failure Notification
Function: sendInvoiceFailureEmail
Trigger: Square API failure during automatic or manual invoice processing
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Template:
- Red header (#d9534f)
- Invoice ID, error message, timestamp
- Function name that failed (automatic vs manual)
Status Update Failure
Function: updateInvoiceOnPackageStatusChange (after 3 retry exhaustion)
Trigger: Failed to update package status in invoice after 3 exponential backoff retries
Recipients: jaz@omelasai.com
Content: Invoice ID, package ID, error details
Daily Reports
Daily Data Report
Function: dailyDataReport
Schedule: Daily at 1pm Asia/Manila
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Content:
- User role counts by status: receiving, check-in, transit, unloading, pickup
- Per-container breakdowns
- No-name package lists (packages with “No Name” problem in scanHistory)
- Color-coded statistics in professional HTML layout
Daily Check Report (Aggregated)
Function: dailyReportAggregator
Schedule: Daily at 7am Asia/Manila
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com
Content:
- Issue counts per category: invoices, packages, clients, containers
- Aggregated from
checkResultsFirestore collection - Simple HTML with section headers
Weekly Reports
Lost Packages
Function: weeklyLostPackagesEmail
Schedule: Thursdays at 7am Asia/Manila
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Content:
- HTML table of packages with received/unprocessed status
- Only includes packages scanned before (latest container creation date - 7 days)
- Shows tracking number, client name, last scan date
Unloaded Not Checked In
Function: weeklyUnloadedNotCheckedInEmail
Schedule: Fridays at 7am America/New_York
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Content:
- HTML table of packages unloaded but never checked in
- Lookback window: 4 weeks
- Shows tracking number, client name, container
Missing Contacts
Function: dailyMissingContactsEmail
Schedule: Thursdays at 7am America/New_York
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Content:
- Three categorized HTML tables: missing both email+phone, only email, only phone
- Client name, referenceId, location
Alert Emails
Unloaded Not Checked In (Realtime)
Function: unloadedNotCheckedIn
Trigger: New package created with status=unloaded and unloadedNotCheckedIn=true
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com
Content: Package tracking number, client name, container name (plain text)
Force Unload Alert
Function: sendForceUnloadEmail
Trigger: Callable from web app when packages are force-unloaded
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com, shipittomax@gmail.com
Content:
- HTML table with tracking numbers, client names
- Timestamps formatted in Roatan timezone (America/Chicago)
Bad Scan Alert
Function: badScanAlert
Trigger: New webLogs document with isBadScan=true
Recipients: jaz@omelasai.com, log@omelasai.com, patrick@omelasai.com
Content:
- Scan details, user info from
Usercollection - Tracking number, timestamp
- Photo evidence attached from Firebase Storage
Duplicate Package Alert
Function: detectDuplicatePackage
Trigger: New package created with a tracking number that already exists
Recipients: jazelle.osp34@gmail.com, chas@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Template:
- Red header (#d9534f)
- Summary: tracking number, duplicate count, detection time
- Detailed card per package with all fields and full scan history table
- JSON file attachments: individual package JSONs + combined JSON
Duplicate Last Name (Account Creation Request)
Function: reportDuplicateLastName
Trigger: POST request from signup form
Recipients: shipittomax@gmail.com, maxshippingroatan@gmail.com, jaz@omelasai.com
Template:
- Red header (#d9534f)
- Warning notice (#fcf8e3): “This requires manual review”
- New customer details: name, email, phone, location
- Info box (#d9edf7): existing customers with same last name
- Dark footer
Container Reports (on new container creation)
JSON Report
Function: processContainerTaskJson
Trigger: PubSub process-container-tasks (from onContainerCreated)
Recipients: jaz@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Attachments: JSON files for unprocessed packages, loaded packages, invoices
XLS Report
Function: processContainerTaskXsl
Trigger: PubSub process-container-tasks
Recipients: jaz@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Attachments:
- XLSX workbooks: unprocessed packages, loaded packages (grouped by location), invoices
- Loaded packages also saved to Firebase Storage
Prepaid Space Report
Function: prepaidSendEmail
Trigger: New container creation (after 5-min delay)
Recipients: jaz@omelasai.com, shipittomax@gmail.com, maxshippingroatan@gmail.com
Attachments: XLSX with cubic feet usage per prepaid client (21 hardcoded client IDs), dimensions, tracking numbers