Skip to content

a port of Mime.processDecoded (to MsgBlocks) #1223

Description

@tomholub

For decoding mime content, in TS we use this method:

publicstaticdecode=async(mimeMsg: Uint8Array): Promise<MimeContent>=>{letmimeContent: MimeContent={attachments: [],headers: {},subject: undefined,text: undefined,html: undefined,signature: undefined,from: undefined,to: [],cc: [],bcc: []};constparser=newMimeParser();constleafNodes: {[key: string]: MimeParserNode}={};parser.onbody=(node: MimeParserNode)=>{constpath=String(node.path.join('.'));if(typeofleafNodes[path]==='undefined'){leafNodes[path]=node;}};returnawaitnewPromise((resolve,reject)=>{try{parser.onend=()=>{try{for(constnameofObject.keys(parser.node.headers)){mimeContent.headers[name]=parser.node.headers[name][0].value;}mimeContent.rawSignedContent=Mime.retrieveRawSignedContent([parser.node]);for(constnodeofObject.values(leafNodes)){if(Mime.getNodeType(node)==='application/pgp-signature'){mimeContent.signature=node.rawContent;}elseif(Mime.getNodeType(node)==='text/html'&&!Mime.getNodeFilename(node)){// html content may be broken up into smaller pieces by attachments in between// AppleMail does this with inline attachmentsmimeContent.html=(mimeContent.html||'')+Mime.getNodeContentAsUtfStr(node);}elseif(Mime.getNodeType(node)==='text/plain'&&(!Mime.getNodeFilename(node)||Mime.isNodeInline(node))){mimeContent.text=(mimeContent.text ? `${mimeContent.text}\n\n` : '')+Mime.getNodeContentAsUtfStr(node);}elseif(Mime.getNodeType(node)==='text/rfc822-headers'){if(node._parentNode&&node._parentNode.headers.subject){mimeContent.subject=node._parentNode.headers.subject[0].value;}}else{mimeContent.attachments.push(Mime.getNodeAsAttachment(node));}}constheaders=Mime.headerGetAddress(mimeContent,['from','to','cc','bcc']);mimeContent.subject=String(mimeContent.subject||mimeContent.headers.subject||'');mimeContent=Object.assign(mimeContent,headers);resolve(mimeContent);}catch(e){reject(e);}};parser.write(mimeMsg);parser.end();}catch(e){// todo - on Android we may want to fail when this happens, evaluate effect on browser extensionCatch.reportErr(e);resolve(mimeContent);}});}

But @DenBond7 probably already has some method for decoding mime. Therefore I don't want to reimplement the above, but instead use Den's methods (and its outputs) for the above purpose (if possible)

Then you take outputs from the MIME decode, and you feed them into a new method that needs implementing, similar to the one below:

publicstaticprocessDecoded=(decoded: MimeContent): MimeProccesedMsg=>{constblocks: MsgBlock[]=[];if(decoded.text){constblocksFromTextPart=MsgBlockParser.detectBlocks(Str.normalize(decoded.text)).blocks;// if there are some encryption-related blocks found in the text section, which we can use, and not look at the html sectionif(blocksFromTextPart.find(b=>b.type==='encryptedMsg'||b.type==='signedMsg'||b.type==='publicKey'||b.type==='privateKey')){blocks.push(...blocksFromTextPart);// because the html most likely containt the same thing, just harder to parse pgp sections cause it's html}elseif(decoded.html){// if no pgp blocks found in text part and there is html part, prefer htmlblocks.push(MsgBlock.fromContent('plainHtml',decoded.html));}else{// else if no html and just a plain text message, use thatblocks.push(...blocksFromTextPart);}}elseif(decoded.html){blocks.push(MsgBlock.fromContent('plainHtml',decoded.html));}for(constfileofdecoded.attachments){consttreatAs=file.treatAs();if(treatAs==='encryptedMsg'){constarmored=PgpArmor.clip(file.getData().toUtfStr());if(armored){blocks.push(MsgBlock.fromContent('encryptedMsg',armored));}}elseif(treatAs==='signature'){decoded.signature=decoded.signature||file.getData().toUtfStr();}elseif(treatAs==='publicKey'){blocks.push(...MsgBlockParser.detectBlocks(file.getData().toUtfStr()).blocks);}elseif(treatAs==='privateKey'){blocks.push(...MsgBlockParser.detectBlocks(file.getData().toUtfStr()).blocks);}elseif(treatAs==='encryptedFile'){blocks.push(MsgBlock.fromAttachment('encryptedAttachment','',{name: file.name,type: file.type,length: file.getData().length,data: file.getData()}));}elseif(treatAs==='plainFile'){blocks.push(MsgBlock.fromAttachment('plainAttachment','',{name: file.name,type: file.type,length: file.getData().length,data: file.getData(),inline: file.inline,cid: file.cid}));}}if(decoded.signature){for(constblockofblocks){if(block.type==='plainText'){block.type='signedText';block.signature=decoded.signature;}elseif(block.type==='plainHtml'){block.type='signedHtml';block.signature=decoded.signature;}}if(!blocks.find(block=>['plainText','plainHtml','signedMsg','signedHtml','signedText'].includes(block.type))){// signed an empty messageblocks.push(newMsgBlock("signedMsg","",true,decoded.signature));}}return{headers: decoded.headers, blocks,from: decoded.from,to: decoded.to,rawSignedContent: decoded.rawSignedContent};}

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions