@ -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 =
< / b o d y >
< / b o d y >
< / h t m l > ` ;
< / h t m l > ` ;
if ( ! html . includes ( "<body" ) ) {
html = /* HTML */ ` <head>
< meta charset = "utf-8" / >
< / h e a d >
< body >
$ { html }
< / b o d y > ` ;
}
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(
< / u l > < / b o d y > `
< / u l > < / b o d y > `
) ;
) ;
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);