// Name: Export Postmark Delivered Emails // Description: Export delivered emails from Postmark API with subject line filtering // Author: zacjones93 // GitHub: zacjones93 import "@johnlindquist/kit" const POSTMARK_API_TOKEN = await env("POSTMARK_API_TOKEN", { hint: "Get your Server API Token from https://account.postmarkapp.com/servers", secret: true }) const subjectFilter = await arg({ placeholder: "Enter subject line filter (optional)", hint: "Leave empty to export all delivered emails", strict: false }) const fromDate = await arg({ placeholder: "From date (YYYY-MM-DD)", hint: "Start date for email export", strict: false }) const toDate = await arg({ placeholder: "To date (YYYY-MM-DD)", hint: "End date for email export", strict: false }) setLoading(true) setStatus({ status: "busy", message: "Fetching emails from Postmark..." }) const emails = [] let offset = 0 const count = 500 // Max per request while (true) { const params = new URLSearchParams({ count: count.toString(), offset: offset.toString(), status: "sent" // Only delivered emails }) if (fromDate) params.append("fromdate", fromDate) if (toDate) params.append("todate", toDate) if (subjectFilter) params.append("subject", subjectFilter) const response = await get(`https://api.postmarkapp.com/messages/outbound`, { headers: { "X-Postmark-Server-Token": POSTMARK_API_TOKEN, "Accept": "application/json" }, params }) const batch = response.data.Messages || [] if (batch.length === 0) break // Filter for only delivered emails const deliveredEmails = batch.filter(email => email.Status === "Sent") // Apply subject filter if provided const filteredEmails = subjectFilter ? deliveredEmails.filter(email => email.Subject && email.Subject.toLowerCase().includes(subjectFilter.toLowerCase()) ) : deliveredEmails emails.push(...filteredEmails) setStatus({ status: "busy", message: `Fetched ${emails.length} emails...` }) if (batch.length < count) break offset += count } setLoading(false) if (emails.length === 0) { await div(md("No emails found matching your criteria.")) exit() } const exportFormat = await arg("Choose export format:", [ { name: "CSV", value: "csv" }, { name: "JSON", value: "json" }, { name: "Markdown Table", value: "markdown" } ]) let exportContent = "" const timestamp = formatDate(new Date(), "yyyy-MM-dd-HHmm") let filename = `postmark-emails-${timestamp}` if (exportFormat === "csv") { filename += ".csv" const headers = ["Date", "To", "Subject", "Status", "Message ID", "Tag"] const csvRows = [headers.join(",")] emails.forEach(email => { const row = [ email.ReceivedAt || "", `"${email.To || ""}"`, `"${(email.Subject || "").replace(/"/g, '""')}"`, email.Status || "", email.MessageID || "", email.Tag || "" ] csvRows.push(row.join(",")) }) exportContent = csvRows.join("\n") } else if (exportFormat === "json") { filename += ".json" exportContent = JSON.stringify(emails, null, 2) } else if (exportFormat === "markdown") { filename += ".md" exportContent = `# Postmark Email Export\n\n` exportContent += `**Export Date:** ${formatDate(new Date(), "yyyy-MM-dd HH:mm")}\n` exportContent += `**Total Emails:** ${emails.length}\n` if (subjectFilter) exportContent += `**Subject Filter:** ${subjectFilter}\n` exportContent += `\n| Date | To | Subject | Status | Message ID |\n` exportContent += `|------|----|---------|---------|-----------|\n` emails.forEach(email => { const date = email.ReceivedAt ? formatDate(new Date(email.ReceivedAt), "yyyy-MM-dd HH:mm") : "" const to = (email.To || "").replace(/\|/g, "\\|") const subject = (email.Subject || "").replace(/\|/g, "\\|") const status = email.Status || "" const messageId = email.MessageID || "" exportContent += `| ${date} | ${to} | ${subject} | ${status} | ${messageId} |\n` }) } const downloadsPath = home("Downloads") const outputPath = path.join(downloadsPath, filename) await writeFile(outputPath, exportContent) await div(md(` # Export Complete! **File:** ${filename} **Location:** ${outputPath} **Total Emails:** ${emails.length} ${subjectFilter ? `**Subject Filter:** "${subjectFilter}"` : ""} The file has been saved to your Downloads folder. `)) await revealFile(outputPath)// Name: Find Missing Emails // Description: Compare two email arrays and return emails from array 2 that are not present in array 1 // Author: zacjones93 // GitHub: zacjones93 import "@johnlindquist/kit" // Get the two arrays from the user const array1Input = await editor({ placeholder: "Paste Array 1 (with MessageID objects)", language: "json", hint: "Paste the array containing objects with To/Recipients email fields" }) const array2Input = await editor({ placeholder: "Paste Array 2 (with email objects)", language: "json", hint: "Paste the array containing objects with email fields" }) try { // Parse the JSON arrays const array1 = JSON.parse(array1Input) const array2 = JSON.parse(array2Input) // Extract emails from array 1 const array1Emails = new Set() array1.forEach(item => { // Check Recipients array first if (item.Recipients && Array.isArray(item.Recipients)) { item.Recipients.forEach(email => array1Emails.add(email.toLowerCase())) } // Also check To array as backup if (item.To && Array.isArray(item.To)) { item.To.forEach(toItem => { if (toItem.Email) { array1Emails.add(toItem.Email.toLowerCase()) } }) } }) // Extract emails from array 2 that are NOT in array 1 const missingEmails = [] array2.forEach(item => { if (item.email) { const email = item.email.toLowerCase() if (!array1Emails.has(email)) { missingEmails.push(item.email) // Keep original case } } }) // Display results if (missingEmails.length === 0) { await div(md(` # ✅ No Missing Emails All emails from Array 2 are present in Array 1. **Array 1 contains:** ${array1Emails.size} unique emails **Array 2 contains:** ${array2.length} emails `)) } else { const resultText = missingEmails.join('\n') await div(md(` # 📧 Missing Emails Found **${missingEmails.length} email(s) from Array 2 are NOT present in Array 1:** \`\`\` ${resultText} \`\`\` **Array 1 contains:** ${array1Emails.size} unique emails **Array 2 contains:** ${array2.length} emails `), [ { name: 'Copy Missing Emails', shortcut: 'cmd+c', onAction: () => { copy(resultText) toast('Missing emails copied to clipboard!') } } ]) } } catch (error) { await div(md(` # ❌ Error Processing Arrays **Error:** ${error.message} Please ensure both inputs are valid JSON arrays. **Expected format for Array 1:** \`\`\`json [ { "Recipients": ["email1@example.com"], "To": [{"Email": "email1@example.com"}] } ] \`\`\` **Expected format for Array 2:** \`\`\`json [ {"email": "email2@example.com"} ] \`\`\` `)) }