Skip to content

Commit 409f2ad

Browse files
committed
simplified message detection
1 parent d68265b commit 409f2ad

File tree

1 file changed

+50
-61
lines changed

1 file changed

+50
-61
lines changed

extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts

Lines changed: 50 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -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 = /-----BEGIN PGP MESSAGE-----(.*?)-----END PGP MESSAGE-----/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

Comments
 (0)