@numoteq/emdash-plugin-jetemail 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.mts +7 -1
- package/dist/client.mjs +10 -0
- package/dist/index.mjs +1 -1
- package/dist/manifest.json +1 -1
- package/dist/plugin.d.mts +6 -0
- package/dist/plugin.mjs +1 -1
- package/package.json +1 -1
package/dist/client.d.mts
CHANGED
|
@@ -4,6 +4,11 @@ interface JetEmailSender {
|
|
|
4
4
|
fromName: string;
|
|
5
5
|
fromEmail: string;
|
|
6
6
|
}
|
|
7
|
+
interface JetEmailAttachment {
|
|
8
|
+
filename: string;
|
|
9
|
+
/** Raw bytes (Uint8Array or Node Buffer) or a base64 string. */
|
|
10
|
+
content: Uint8Array | string;
|
|
11
|
+
}
|
|
7
12
|
interface JetEmailMessage {
|
|
8
13
|
to: string | string[];
|
|
9
14
|
cc?: string[];
|
|
@@ -11,6 +16,7 @@ interface JetEmailMessage {
|
|
|
11
16
|
subject: string;
|
|
12
17
|
text?: string;
|
|
13
18
|
html?: string;
|
|
19
|
+
attachments?: JetEmailAttachment[];
|
|
14
20
|
}
|
|
15
21
|
type FetchFn = (url: string, init?: RequestInit) => Promise<Response>;
|
|
16
22
|
declare function formatSender(name: string, email: string): string;
|
|
@@ -18,4 +24,4 @@ declare function deliverWithJetEmail(fetchFn: FetchFn, sender: JetEmailSender, m
|
|
|
18
24
|
id?: string;
|
|
19
25
|
}>;
|
|
20
26
|
//#endregion
|
|
21
|
-
export { FetchFn, JetEmailMessage, JetEmailSender, deliverWithJetEmail, formatSender };
|
|
27
|
+
export { FetchFn, JetEmailAttachment, JetEmailMessage, JetEmailSender, deliverWithJetEmail, formatSender };
|
package/dist/client.mjs
CHANGED
|
@@ -3,6 +3,12 @@ const API_URL = "https://api.jetemail.com/email";
|
|
|
3
3
|
function formatSender(name, email) {
|
|
4
4
|
return `${name.replace(/[<>"\r\n]/g, "").trim()} <${email}>`;
|
|
5
5
|
}
|
|
6
|
+
function toBase64(content) {
|
|
7
|
+
if (typeof content === "string") return content;
|
|
8
|
+
let binary = "";
|
|
9
|
+
for (let i = 0; i < content.length; i += 32768) binary += String.fromCharCode(...content.subarray(i, i + 32768));
|
|
10
|
+
return btoa(binary);
|
|
11
|
+
}
|
|
6
12
|
async function deliverWithJetEmail(fetchFn, sender, message) {
|
|
7
13
|
const body = {
|
|
8
14
|
from: formatSender(sender.fromName, sender.fromEmail),
|
|
@@ -13,6 +19,10 @@ async function deliverWithJetEmail(fetchFn, sender, message) {
|
|
|
13
19
|
if (message.html) body.html = message.html;
|
|
14
20
|
if (message.cc?.length) body.cc = message.cc;
|
|
15
21
|
if (message.replyTo) body.reply_to = message.replyTo;
|
|
22
|
+
if (message.attachments?.length) body.attachments = message.attachments.map((file) => ({
|
|
23
|
+
filename: file.filename,
|
|
24
|
+
data: toBase64(file.content)
|
|
25
|
+
}));
|
|
16
26
|
const response = await fetchFn(API_URL, {
|
|
17
27
|
method: "POST",
|
|
18
28
|
headers: {
|
package/dist/index.mjs
CHANGED
package/dist/manifest.json
CHANGED
package/dist/plugin.d.mts
CHANGED
|
@@ -6,6 +6,11 @@ interface JetEmailSender {
|
|
|
6
6
|
fromName: string;
|
|
7
7
|
fromEmail: string;
|
|
8
8
|
}
|
|
9
|
+
interface JetEmailAttachment {
|
|
10
|
+
filename: string;
|
|
11
|
+
/** Raw bytes (Uint8Array or Node Buffer) or a base64 string. */
|
|
12
|
+
content: Uint8Array | string;
|
|
13
|
+
}
|
|
9
14
|
interface JetEmailMessage {
|
|
10
15
|
to: string | string[];
|
|
11
16
|
cc?: string[];
|
|
@@ -13,6 +18,7 @@ interface JetEmailMessage {
|
|
|
13
18
|
subject: string;
|
|
14
19
|
text?: string;
|
|
15
20
|
html?: string;
|
|
21
|
+
attachments?: JetEmailAttachment[];
|
|
16
22
|
}
|
|
17
23
|
type FetchFn = (url: string, init?: RequestInit) => Promise<Response>;
|
|
18
24
|
declare function formatSender(name: string, email: string): string;
|
package/dist/plugin.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,t){return`${e.replace(/[<>"\r\n]/g,``).trim()} <${t}>`}
|
|
1
|
+
function e(e,t){return`${e.replace(/[<>"\r\n]/g,``).trim()} <${t}>`}function t(e){if(typeof e==`string`)return e;let t=``;for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}async function n(n,r,i){let a={from:e(r.fromName,r.fromEmail),to:i.to,subject:i.subject};i.text&&(a.text=i.text),i.html&&(a.html=i.html),i.cc?.length&&(a.cc=i.cc),i.replyTo&&(a.reply_to=i.replyTo),i.attachments?.length&&(a.attachments=i.attachments.map(e=>({filename:e.filename,data:t(e.content)})));let o=await n(`https://api.jetemail.com/email`,{method:`POST`,headers:{Authorization:`Bearer ${r.apiToken}`,"Content-Type":`application/json`},body:JSON.stringify(a)});if(!o.ok){let e=(await o.text()).slice(0,500);throw Error(`JetEmail rejected the message with HTTP ${o.status}${e?`: ${e}`:``}`)}let s=await o.json().catch(()=>({}));return typeof s.id==`string`?{id:s.id}:{}}async function r(e){let t=await e.kv.get(`settings:apiToken`),n=await e.kv.get(`settings:fromName`),r=await e.kv.get(`settings:fromEmail`);if(!t||!n||!r)throw Error(`JetEmail is not configured. Set the API key, sender name and sender email.`);return{apiToken:t,fromName:n,fromEmail:r}}async function i(e){let t=await e.kv.get(`settings:fromName`)??``,n=await e.kv.get(`settings:fromEmail`)??``,r=!!await e.kv.get(`settings:apiToken`);return{blocks:[{type:`header`,text:`JetEmail`},{type:`section`,text:`Deliver EmDash transactional email through the JetEmail API. The sender domain must be verified in JetEmail and allowed for the API key.`},{type:`form`,block_id:`jetemail-settings`,fields:[{type:`text_input`,action_id:`fromName`,label:`Sender name`,initial_value:t},{type:`text_input`,action_id:`fromEmail`,label:`Sender email`,initial_value:n},{type:`secret_input`,action_id:`apiToken`,label:r?`Transactional API key (leave blank to keep current)`:`Transactional API key`}],submit:{label:`Save settings`,action_id:`save_settings`}}]}}function a(e){return{blocks:[{type:`banner`,style:`error`,text:e}],toast:{message:e,type:`error`}}}async function o(e,t){let n=typeof t.fromName==`string`?t.fromName.trim():``,r=typeof t.fromEmail==`string`?t.fromEmail.trim():``,o=typeof t.apiToken==`string`?t.apiToken.trim():``;return n.replace(/[<>"\r\n]/g,``).trim()?/^[^\s@<>]+@[^\s@<>]+$/.test(r)?o&&!o.startsWith(`transactional_`)?a(`Use a JetEmail transactional API key (transactional_…).`):(await e.kv.set(`settings:fromName`,n),await e.kv.set(`settings:fromEmail`,r),o&&await e.kv.set(`settings:apiToken`,o),{...await i(e),toast:{message:`JetEmail settings saved`,type:`success`}}):a(`Enter a valid sender email.`):a(`Enter a sender name.`)}const s={hooks:{"email:deliver":{exclusive:!0,timeout:3e4,handler:async(e,t)=>{if(!t.http)throw Error(`JetEmail requires network access.`);let i=await r(t);await n(t.http.fetch.bind(t.http),i,e.message),t.log.info(`Email delivered via JetEmail`,{to:e.message.to,subject:e.message.subject})}}},routes:{admin:{handler:async(e,t)=>{let n=e.input;return n.type===`page_load`&&n.page===`/settings`?i(t):n.type===`form_submit`&&n.action_id===`save_settings`?o(t,n.values??{}):{blocks:[]}}}}};export{s as default,n as deliverWithJetEmail,e as formatSender};
|