From b28456683cf6079889977fd0814f98f7563104b5 Mon Sep 17 00:00:00 2001 From: Mohit Raj Date: Sat, 2 Mar 2024 16:53:02 +0530 Subject: [PATCH] feat: check ebook size before sending and show warning --- README.md | 50 ++++++++++++++++++++++++++------------------------ config.json | 4 +++- email.ts | 34 ++++++++++++++++++++++++++++------ 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index c4de724..a3da93f 100644 --- a/README.md +++ b/README.md @@ -59,28 +59,30 @@ List of eReaders that support sending ebook using email: Configuration options available in the [config file](config.json) -| Option | Type | Description | -| ----------------------- | -------- | --------------------------------------------------------- | -| token | string | Omnivore API Token | -| endpoint | string | Omnivore GraphQL API endpoint | -| title | string | Title of the ebook | -| author | string | Author of the ebook | -| cover | string | URL for fetching cover image for the ebook | -| description | string | Description of the ebook | -| addLabelsInContent | boolean | Whether to add the labels for the article below title | -| addArticleLinkInContent | boolean | Whether to add the link for the article below title | -| allowImages | boolean | Whether to add images linked in article in the ebook | -| outputFileName | string | ebook file name | -| maxArticleCount | number | Number of articles to fetch | -| searchQuery | string | Valid query for article search, default: "sort:saved-desc". Change it to "sort:saved-asc" for fetching oldest articles first | -| ignoredLabels | string[] | List of labels to exclude from the ebook | -| ignoredLinks | string[] | List of urls to exclude from the ebook | -| emailSupport | boolean | Whether to send the ebook via email (to your eReader) | -| emailHost | string | SMTP Hostname of your email provider | -| emailPort | number | Usually one of 587, 465 or 25. Prefer 587 when available | -| emailUser | string | Username/Email address of your email account | -| emailPassword | string | Password of your email account. Prefer app password | -| emailRecipient | string | Email address that should receive your ebook | -| emailFrom | string | Sender name that appears to the email receiver | -| emailAllowSTARTTLS | boolean | Allow connecting to the SMTP server using STARTTLS | +| Option | Type | Description | +| ------------------------ | -------- | -------------------------------------------------------- | +| token | string | Omnivore API Token | +| endpoint | string | Omnivore GraphQL API endpoint | +| title | string | Title of the ebook | +| author | string | Author of the ebook | +| cover | string | URL for fetching cover image for the ebook | +| description | string | Description of the ebook | +| addLabelsInContent | boolean | Whether to add the labels for the article below title | +| addArticleLinkInContent | boolean | Whether to add the link for the article below title | +| allowImages | boolean | Whether to add images linked in article in the ebook | +| outputFileName | string | ebook file name | +| maxArticleCount | number | Number of articles to fetch | +| searchQuery | string | Valid query for article search, default: "sort:saved-desc". Change it to "sort:saved-asc" for fetching oldest articles first | +| ignoredLabels | string[] | List of labels to exclude from the ebook | +| ignoredLinks | string[] | List of urls to exclude from the ebook | +| emailSupport | boolean | Whether to send the ebook via email (to your eReader) | +| emailHost | string | SMTP Hostname of your email provider | +| emailPort | number | Usually one of 587, 465 or 25. Prefer 587 when available | +| emailUser | string | Username/Email address of your email account | +| emailPassword | string | Password of your email account. Prefer app password | +| emailRecipient | string | Email address that should receive your ebook | +| emailFrom | string | Sender name that appears to the email receiver | +| emailAllowSTARTTLS | boolean | Allow connecting to the SMTP server using STARTTLS | +| emailSizeWarningSuppress | boolean | Show a warning if ebook is over emailSizeWarningMinSize | +| emailSizeWarningMinSize | number | Min ebook size to show warning while sending email in MB | diff --git a/config.json b/config.json index 52cdb94..5da6b4e 100644 --- a/config.json +++ b/config.json @@ -20,5 +20,7 @@ "emailPassword": "", "emailRecipient": "my-send-to-kindle-email@kindle.com", "emailFrom": "Omnivore EPUB Mailer", - "emailAllowSTARTTLS": true + "emailAllowSTARTTLS": true, + "emailSizeWarningSuppress": false, + "emailSizeWarningMinSize": 25 } diff --git a/email.ts b/email.ts index fd24bd4..398b59a 100644 --- a/email.ts +++ b/email.ts @@ -23,12 +23,7 @@ export async function sendEmail() { ], }; - if ( - await Deno.stat(config.outputFileName).catch((_err) => { - console.error(`🚫 ebook file '${config.outputFileName}' is missing`); - Deno.exit(1); - }) - ) { + if (await verifyEpub()) { try { console.log(`📧 Sending email from '${config.emailFrom} <${config.emailUser}>' to '${config.emailRecipient}'`); const info = await transporter.sendMail(mailOptions); @@ -39,3 +34,30 @@ export async function sendEmail() { } } } + +async function verifyEpub(): Promise { + try { + const file = await Deno.stat(config.outputFileName); + + // Check if it is indeed a file + if (!file.isFile) { + console.error(`🚫 ${config.outputFileName} is not a file`); + Deno.exit(1); + } + + // Convert from bytes to MB (not MiB) rounded off to 2 digits after decimal + const ebookSize = (file.size / 1_000_000).toFixed(2); + + // Show a warning if ebook is over a specified size + if (!config.emailSizeWarningSuppress && Number(ebookSize) >= config.emailSizeWarningMinSize) { + console.warn(`⚠️ ebook size is too large at ${ebookSize} MB (limit: ${config.emailSizeWarningMinSize} MB)`); + console.warn("⚠️ Many email providers and eReader emailing services may reject this email"); + console.warn("⚠️ To suppress this warning, set 'emailSuppressSizeWarning' to true in 'config.json'"); + } + } catch (_err) { + console.error(`🚫 ebook file '${config.outputFileName}' is missing`); + Deno.exit(1); + } + + return true; +}