-
Notifications
You must be signed in to change notification settings - Fork 14
Closed
Description
part of #1051
Right now we use node for initial structure and then we tag on files in Kotlin. Can do all in Kotlin.
Current implementation is at https://github.com/FlowCrypt/flowcrypt-mobile-core/blob/master/source/mobile-interface/endpoints.ts
Here:
public composeEmail = async (uncheckedReq: any): Promise<Buffers> => {
const req = ValidateInput.composeEmail(uncheckedReq);
const mimeHeaders: RichHeaders = { to: req.to, from: req.from, subject: req.subject, cc: req.cc, bcc: req.bcc };
if (req.replyToMimeMsg) {
const previousMsg = await Mime.decode(Buf.fromUtfStr((req.replyToMimeMsg.substr(0, 10000).split('\n\n')[0] || '') + `\n\nno content`));
const replyHeaders = Mime.replyHeaders(previousMsg);
mimeHeaders['in-reply-to'] = replyHeaders['in-reply-to'];
mimeHeaders['references'] = replyHeaders['references'];
}
if (req.format === 'plain') {
const atts = (req.atts || []).map(({ name, type, base64 }) => new Att({ name, type, data: Buf.fromBase64Str(base64) }));
return fmtRes({}, Buf.fromUtfStr(await Mime.encode({ 'text/plain': req.text }, mimeHeaders, atts)));
} else if (req.format === 'encrypt-inline') {
const encryptedAtts: Att[] = [];
for (const att of req.atts || []) {
const encryptedAtt = await PgpMsg.encrypt({ pubkeys: req.pubKeys, data: Buf.fromBase64Str(att.base64), filename: att.name, armor: false }) as OpenPGP.EncryptBinaryResult;
encryptedAtts.push(new Att({ name: att.name, type: 'application/pgp-encrypted', data: encryptedAtt.message.packets.write() }))
}
const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, data: Buf.fromUtfStr(req.text), armor: true }) as OpenPGP.EncryptArmorResult;
return fmtRes({}, Buf.fromUtfStr(await Mime.encode({ 'text/plain': encrypted.data }, mimeHeaders, encryptedAtts)));
} else {
throw new Error(`Unknown format: ${req.format}`);
}
}Tests at https://github.com/FlowCrypt/flowcrypt-mobile-core/blob/master/source/test.ts
ava.default('composeEmail format:plain -> parseDecryptMsg', async t => {
const content = 'hello\nwrld';
const { keys } = getKeypairs('rsa1');
const req = { format: 'plain', text: content, to: ['some@to.com'], cc: ['some@cc.com'], bcc: [], from: 'some@from.com', subject: 'a subj' };
const { data: plainMimeMsg, json: composeEmailJson } = await request('composeEmail', req, []);
expectEmptyJson(composeEmailJson);
const plainMimeStr = plainMimeMsg.toString();
expect(plainMimeStr).contains('To: some@to.com');
expect(plainMimeStr).contains('From: some@from.com');
expect(plainMimeStr).contains('Subject: a subj');
expect(plainMimeStr).contains('Cc: some@cc.com');
expect(plainMimeStr).contains('Date: ');
expect(plainMimeStr).contains('MIME-Version: 1.0');
const { data: blocks, json: parseJson } = await request('parseDecryptMsg', { keys, isEmail: true }, plainMimeMsg);
expect(parseJson).to.deep.equal({ text: content, replyType: 'plain', subject: 'a subj' });
expectData(blocks, 'msgBlocks', [{ rendered: true, frameColor: 'plain', htmlContent: content.replace(/\n/g, '<br />') }]);
t.pass();
});
ava.default('composeEmail format:plain (reply)', async t => {
const replyToMimeMsg = `Content-Type: multipart/mixed;
boundary="----sinikael-?=_1-15535259519270.930031460416217"
To: some@to.com
From: some@from.com
Subject: Re: original
Date: Mon, 25 Mar 2019 14:59:11 +0000
Message-Id: <originalmsg@from.com>
MIME-Version: 1.0
------sinikael-?=_1-15535259519270.930031460416217
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable
orig message
------sinikael-?=_1-15535259519270.930031460416217--`
const req = { format: 'plain', text: 'replying', to: ['some@to.com'], cc: [], bcc: [], from: 'some@from.com', subject: 'Re: original', replyToMimeMsg };
const { data: mimeMsgReply, json } = await request('composeEmail', req, []);
expectEmptyJson(json);
const mimeMsgReplyStr = mimeMsgReply.toString();
expect(mimeMsgReplyStr).contains('In-Reply-To: <originalmsg@from.com>');
expect(mimeMsgReplyStr).contains('References: <originalmsg@from.com>');
t.pass();
});
ava.default('composeEmail format:encrypt-inline -> parseDecryptMsg', async t => {
const content = 'hello\nwrld';
const { pubKeys, keys } = getKeypairs('rsa1');
const req = { pubKeys, format: 'encrypt-inline', text: content, to: ['encrypted@to.com'], cc: [], bcc: [], from: 'encr@from.com', subject: 'encr subj' };
const { data: encryptedMimeMsg, json: encryptJson } = await request('composeEmail', req, []);
expectEmptyJson(encryptJson);
const encryptedMimeStr = encryptedMimeMsg.toString();
expect(encryptedMimeStr).contains('To: encrypted@to.com');
expect(encryptedMimeStr).contains('MIME-Version: 1.0');
expectData(encryptedMimeMsg, 'armoredMsg'); // armored msg block should be contained in the mime message
const { data: blocks, json: decryptJson } = await request('parseDecryptMsg', { keys, isEmail: true }, encryptedMimeMsg);
expect(decryptJson).deep.equal({ text: content, replyType: 'encrypted', subject: 'encr subj' });
expectData(blocks, 'msgBlocks', [{ rendered: true, frameColor: 'green', htmlContent: content.replace(/\n/g, '<br />') }]);
t.pass();
});Reactions are currently unavailable