Add support for inline images

master
Kuba Orlik 3 years ago
parent 1371daae7f
commit 44b3cfe6de

@ -1,5 +1,6 @@
#!/usr/bin/zx --quiet #!/usr/bin/zx --quiet
var elparser = require("elparser");
import { resolve, basename } from "path"; import { resolve, basename } from "path";
const pwd = (await $`pwd`).stdout.replace("\n", ""); const pwd = (await $`pwd`).stdout.replace("\n", "");
@ -37,22 +38,46 @@ let html =
</body> </body>
</html>`; </html>`;
if (!html.includes("<body")) {
html = /* HTML */ ` <head>
<meta charset="utf-8" />
</head>
<body>
${html}
</body>`;
}
if (
html.includes(
`<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-2">`
)
) {
html = html.replace(
`<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-2">`,
""
);
}
if (!html.includes(`<meta charset="utf-8"`)) {
html = html.replace("</head>", `<meta charset="utf-8" /></head>`);
}
const attachments = (await $`mu extract ${path}`).stdout; const attachments = (await $`mu extract ${path}`).stdout;
function getSimpleHeader(body, header_name) { async function emacsEval(expr) {
const regexp = new RegExp(`:${header_name} (.*)\n`); return (await $`emacsclient --eval ${expr}`).stdout.slice(0, -1); // slice to remove trailing newline;
console.log("get simple header", header_name, body);
return body.match(regexp)[1];
} }
function formatAddress(sexp) { async function getSimpleHeader(body_sexp, header_name) {
sexp = sexp return await emacsEval(`(plist-get '${body_sexp} ':${header_name})`);
.replace(/(^\(\(|\)\)$)/g, "") }
.replace(/"? \. "/, " <")
.replace(/"$/, ">") async function formatAddress(sexp) {
.replace(/^"/, "") const [name, address] = await Promise.all([
.replace(/^nil <(.*)>$/, "$1"); emacsEval(`(car (car '${sexp}))`),
return sexp; emacsEval(`(cdr (car '${sexp}))`),
]);
return `${name === "nil" ? "" : name} <${address}>`;
} }
function escape(str) { function escape(str) {
@ -120,14 +145,45 @@ html = html.replace(
</ul></body>` </ul></body>`
); );
const subject = getSimpleHeader(mail_body, "subject").slice(1, -1); // slice to remove " const subject = (await getSimpleHeader(mail_body, "subject")).slice(1, -1); // slice to remove " and newlines
const from = formatAddress(getSimpleHeader(mail_body, "from")); const from = await formatAddress(await getSimpleHeader(mail_body, "from"));
const to = formatAddress(getSimpleHeader(mail_body, "to")); const to = await formatAddress(await getSimpleHeader(mail_body, "to"));
const date = await formatDate(getSimpleHeader(mail_body, "date")); const date = await formatDate(await getSimpleHeader(mail_body, "date"));
const parts = elparser
.parse1(`'${await getSimpleHeader(mail_body, "parts")}`)
.qsexp.list.map((entry) =>
Object.fromEntries(
entry.list.map((value, index, array) => {
if (index % 2 == 0) {
const key = array[index].symbol.slice(1);
let value = array[index + 1];
for (const subkey of ["string", "symbol"]) {
if (value[subkey] !== undefined) {
value = value[subkey];
}
}
if (value.type && value.type?.type === "int") {
value = parseInt(value.val);
}
return [key, value];
} else return [];
})
)
);
const inline_attachments = parts.filter((e) => e.cid !== undefined);
for (const inline_attachment of inline_attachments) {
await $`mu extract --overwrite ${path} ${inline_attachment.name} --target-dir=/tmp --overwrite`;
html = html.replace(
`cid:${inline_attachment.cid}`,
`./${inline_attachment.name}`
);
}
html = html.replace( html = html.replace(
/<body>/i, /<body>/i,
`<meta charset="utf-8"><body>` + `<body>` +
/* HTML */ `<h1>${subject}</h1> /* HTML */ `<h1>${subject}</h1>
<table> <table>
<tr> <tr>
@ -159,7 +215,7 @@ const output_file = `${resolve(path, "../")}/${basename(path)}.pdf`.replace(
" " " "
); );
await $`wkhtmltopdf ${output} ${output_file}`; await $`wkhtmltopdf --enable-local-file-access ${output} ${output_file}`; // --enable-local-file-access is there so the inline images don't have to be included as base64. Probably not the safest approach and base64 would be better
// console.log(pwd + "output.html"); // console.log(pwd + "output.html");
// console.log(mail_body); // console.log(mail_body);

11
package-lock.json generated

@ -9,9 +9,15 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"elparser": "^0.0.9",
"sexpr-plus": "^7.0.0" "sexpr-plus": "^7.0.0"
} }
}, },
"node_modules/elparser": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/elparser/-/elparser-0.0.9.tgz",
"integrity": "sha1-+bQxsVZSCK8roHKKE8Ux4FWbrSI="
},
"node_modules/sexpr-plus": { "node_modules/sexpr-plus": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/sexpr-plus/-/sexpr-plus-7.0.0.tgz", "resolved": "https://registry.npmjs.org/sexpr-plus/-/sexpr-plus-7.0.0.tgz",
@ -19,6 +25,11 @@
} }
}, },
"dependencies": { "dependencies": {
"elparser": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/elparser/-/elparser-0.0.9.tgz",
"integrity": "sha1-+bQxsVZSCK8roHKKE8Ux4FWbrSI="
},
"sexpr-plus": { "sexpr-plus": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/sexpr-plus/-/sexpr-plus-7.0.0.tgz", "resolved": "https://registry.npmjs.org/sexpr-plus/-/sexpr-plus-7.0.0.tgz",

@ -13,6 +13,7 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"elparser": "^0.0.9",
"sexpr-plus": "^7.0.0" "sexpr-plus": "^7.0.0"
} }
} }

Loading…
Cancel
Save