@@ -21,69 +21,69 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer {
2121 public scrollToCursorInReplyBox : ( replyMsgId : string , cursorOffsetTop : number ) => void ;
2222 private acctEmail : string ;
2323 private emailBodyFromThunderbirdMail : string ;
24- private thunderbirdEmailSelector = $ ( 'div.moz-text-plain' ) ;
24+ private emailBodyToParse = $ ( 'div.moz-text-plain' ) . text ( ) . trim ( ) ;
2525
2626 public getIntervalFunctions = ( ) : IntervalFunction [ ] => {
2727 return [ { interval : 2000 , handler : ( ) => this . replaceThunderbirdMsgPane ( ) } ] ;
2828 } ;
2929
3030 public replaceThunderbirdMsgPane = async ( ) => {
3131 if ( Catch . isThunderbirdMail ( ) ) {
32- const { messagePart, attachments } = await BrowserMsg . send . bg . await . thunderbirdMsgGet ( ) ;
33- if ( messagePart ) {
34- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
35- this . acctEmail = ( await BrowserMsg . send . bg . await . thunderbirdGetCurrentUser ( ) ) ! ;
36- const parsedPubs = ( await ContactStore . getOneWithAllPubkeys ( undefined , this . acctEmail ) ) ?. sortedPubkeys ?? [ ] ;
37- const signerKeys = parsedPubs . map ( key => KeyUtil . armor ( key . pubkey ) ) ;
38- if ( this . isPublicKeyEncryptedMsg ( ) ) {
39- const result = await MsgUtil . decryptMessage ( {
40- kisWithPp : await KeyStore . getAllWithOptionalPassPhrase ( this . acctEmail ) ,
41- encryptedData : this . emailBodyFromThunderbirdMail ,
42- verificationPubs : signerKeys ,
43- } ) ;
44- if ( result . success && result . content ) {
45- const decryptedMsg = result . content . toUtfStr ( ) ;
46- const encryptionStatus = result . isEncrypted ? 'encrypted' : 'not encrypted' ;
47- let verificationStatus = '' ;
48- if ( result ?. signature ) {
49- if ( result . signature . match ) {
50- verificationStatus = 'signed' ;
51- } else if ( result . signature . error ) {
52- verificationStatus = `could not verify signature: ${ result . signature . error } ` ;
53- } else {
54- verificationStatus = 'not signed' ;
55- }
56- }
57- const pgpBlock = this . generatePgpBlockTemplate ( encryptionStatus , verificationStatus , decryptedMsg ) ;
58- $ ( 'body' ) . html ( pgpBlock ) ; // xss-sanitized
59- } else {
60- const decryptErr = result as DecryptError ;
61- let decryptionErrorMsg = '' ;
62- if ( decryptErr . error && decryptErr . error . type === DecryptErrTypes . needPassphrase ) {
63- const acctEmail = String ( await BrowserMsg . send . bg . await . thunderbirdGetCurrentUser ( ) ) ;
64- const longids = decryptErr . longids . needPassphrase . join ( ',' ) ;
65- decryptionErrorMsg = `decrypt error: private key needs to be unlocked by your passphrase.` ;
66- await BrowserMsg . send . bg . await . thunderbirdOpenPassphraseDiaglog ( { acctEmail, longids } ) ;
32+ const { attachments } = await BrowserMsg . send . bg . await . thunderbirdMsgGet ( ) ;
33+ const pgpRegex = / - - - - - B E G I N P G P M E S S A G E - - - - - ( .* ?) - - - - - E N D P G P M E S S A G E - - - - - / s;
34+ const pgpRegexMatch = new RegExp ( pgpRegex ) . exec ( this . emailBodyToParse ) ;
35+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
36+ this . acctEmail = ( await BrowserMsg . send . bg . await . thunderbirdGetCurrentUser ( ) ) ! ;
37+ const parsedPubs = ( await ContactStore . getOneWithAllPubkeys ( undefined , this . acctEmail ) ) ?. sortedPubkeys ?? [ ] ;
38+ const signerKeys = parsedPubs . map ( key => KeyUtil . armor ( key . pubkey ) ) ;
39+ if ( pgpRegexMatch && this . resemblesAsciiArmoredMsg ( pgpRegexMatch [ 0 ] ) ) {
40+ const result = await MsgUtil . decryptMessage ( {
41+ kisWithPp : await KeyStore . getAllWithOptionalPassPhrase ( this . acctEmail ) ,
42+ encryptedData : this . emailBodyFromThunderbirdMail ,
43+ verificationPubs : signerKeys ,
44+ } ) ;
45+ if ( result . success && result . content ) {
46+ const decryptedMsg = result . content . toUtfStr ( ) ;
47+ const encryptionStatus = result . isEncrypted ? 'encrypted' : 'not encrypted' ;
48+ let verificationStatus = '' ;
49+ if ( result ?. signature ) {
50+ if ( result . signature . match ) {
51+ verificationStatus = 'signed' ;
52+ } else if ( result . signature . error ) {
53+ verificationStatus = `could not verify signature: ${ result . signature . error } ` ;
6754 } else {
68- decryptionErrorMsg = `decrypt error: ${ ( result as DecryptError ) . error . message } ` ;
55+ verificationStatus = 'not signed' ;
6956 }
70- const pgpBlock = this . generatePgpBlockTemplate ( decryptionErrorMsg , 'not signed' , this . emailBodyFromThunderbirdMail ) ;
71- $ ( 'body' ) . html ( pgpBlock ) ; // xss-sanitized
7257 }
73- } else if ( this . isCleartextMsg ( ) ) {
74- const message = await openpgp . readCleartextMessage ( { cleartextMessage : this . emailBodyFromThunderbirdMail } ) ;
75- const result = await OpenPGPKey . verify ( message , await ContactStore . getPubkeyInfos ( undefined , signerKeys ) ) ;
76- let verificationStatus = '' ;
77- let signedMessage = '' ;
78- if ( result . match && result . content ) {
79- verificationStatus = 'signed' ;
80- signedMessage = result . content . toUtfStr ( ) ;
81- } else if ( result . error ) {
82- verificationStatus = `could not verify signature: ${ result . error } ` ;
58+ const pgpBlock = this . generatePgpBlockTemplate ( encryptionStatus , verificationStatus , decryptedMsg ) ;
59+ $ ( 'body' ) . html ( pgpBlock ) ; // xss-sanitized
60+ } else {
61+ const decryptErr = result as DecryptError ;
62+ let decryptionErrorMsg = '' ;
63+ if ( decryptErr . error && decryptErr . error . type === DecryptErrTypes . needPassphrase ) {
64+ const acctEmail = String ( await BrowserMsg . send . bg . await . thunderbirdGetCurrentUser ( ) ) ;
65+ const longids = decryptErr . longids . needPassphrase . join ( ',' ) ;
66+ decryptionErrorMsg = `decrypt error: private key needs to be unlocked by your passphrase.` ;
67+ await BrowserMsg . send . bg . await . thunderbirdOpenPassphraseDiaglog ( { acctEmail, longids } ) ;
68+ } else {
69+ decryptionErrorMsg = `decrypt error: ${ ( result as DecryptError ) . error . message } ` ;
8370 }
84- const pgpBlock = this . generatePgpBlockTemplate ( 'not encrypted ' , verificationStatus , signedMessage ) ;
71+ const pgpBlock = this . generatePgpBlockTemplate ( decryptionErrorMsg , 'not signed ' , this . emailBodyFromThunderbirdMail ) ;
8572 $ ( 'body' ) . html ( pgpBlock ) ; // xss-sanitized
8673 }
74+ } else if ( this . resemblesCleartextMsg ( this . emailBodyToParse ) ) {
75+ const message = await openpgp . readCleartextMessage ( { cleartextMessage : this . emailBodyFromThunderbirdMail } ) ;
76+ const result = await OpenPGPKey . verify ( message , await ContactStore . getPubkeyInfos ( undefined , signerKeys ) ) ;
77+ let verificationStatus = '' ;
78+ let signedMessage = '' ;
79+ if ( result . match && result . content ) {
80+ verificationStatus = 'signed' ;
81+ signedMessage = result . content . toUtfStr ( ) ;
82+ } else if ( result . error ) {
83+ verificationStatus = `could not verify signature: ${ result . error } ` ;
84+ }
85+ const pgpBlock = this . generatePgpBlockTemplate ( 'not encrypted' , verificationStatus , signedMessage ) ;
86+ $ ( 'body' ) . html ( pgpBlock ) ; // xss-sanitized
8787 }
8888 if ( attachments . length ) {
8989 for ( const attachment of attachments ) {
@@ -152,11 +152,6 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer {
152152 }
153153 } ;
154154
155- private isCleartextMsg = ( ) : boolean => {
156- const emailBody = this . thunderbirdEmailSelector . text ( ) . trim ( ) ;
157- return this . resemblesCleartextMsg ( emailBody ) ;
158- } ;
159-
160155 private resemblesCleartextMsg = ( body : string ) => {
161156 this . emailBodyFromThunderbirdMail = body ;
162157 return (
@@ -166,12 +161,6 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer {
166161 ) ;
167162 } ;
168163
169- private isPublicKeyEncryptedMsg = ( ) : boolean => {
170- // todo - recognized email sent via FlowCrypt encrypted contact pages
171- const emailBody = this . thunderbirdEmailSelector . text ( ) . trim ( ) ;
172- return this . resemblesAsciiArmoredMsg ( emailBody ) ;
173- } ;
174-
175164 private resemblesAsciiArmoredMsg = ( body : string ) : boolean => {
176165 this . emailBodyFromThunderbirdMail = body ;
177166 return body . startsWith ( PgpArmor . ARMOR_HEADER_DICT . encryptedMsg . begin ) && body . endsWith ( PgpArmor . ARMOR_HEADER_DICT . encryptedMsg . end as string ) ;
0 commit comments