mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-08 22:18:28 +03:00
#89 improved sign and encrypt
This commit is contained in:
parent
e7b2ed9881
commit
8e515ed2af
2 changed files with 124 additions and 105 deletions
|
|
@ -104,25 +104,24 @@ class MimePart {
|
|||
constructor() {
|
||||
this.headers = {};
|
||||
this.body = '';
|
||||
this.boundary = '';
|
||||
this.children = [];
|
||||
}
|
||||
|
||||
toString() {
|
||||
const hasSub = this.children.length,
|
||||
boundary = 'part' + Jua.randomId(),
|
||||
boundary = this.boundary || (this.boundary = 'part' + Jua.randomId()),
|
||||
headers = this.headers;
|
||||
if (hasSub) {
|
||||
headers['Content-Type'] = headers['Content-Type'] + `; boundary="${boundary}"`;
|
||||
headers['Content-Type'] += `; boundary="${boundary}"`;
|
||||
}
|
||||
let result = Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join('\r\n') + '\r\n';
|
||||
if (this.body) {
|
||||
result += '\r\n' + this.body.replace(/\r?\n/g, '\r\n');
|
||||
}
|
||||
let result =
|
||||
Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join('\r\n')
|
||||
+ '\r\n\r\n'
|
||||
+ this.body;
|
||||
if (hasSub) {
|
||||
this.children.forEach(part => {
|
||||
result = result + '\r\n--' + boundary + '\r\n' + part
|
||||
});
|
||||
result = result + '\r\n--' + boundary + '--\r\n';
|
||||
this.children.forEach(part => result += '\r\n--' + boundary + '\r\n' + part);
|
||||
result += '\r\n--' + boundary + '--\r\n';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -367,7 +366,7 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
|
||||
async getMessageRequestParams(sSaveFolder, draft)
|
||||
{
|
||||
let
|
||||
const
|
||||
identity = this.currentIdentity(),
|
||||
params = {
|
||||
IdentityID: identity.id(),
|
||||
|
|
@ -391,8 +390,9 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
recipients = draft ? [identity.email()] : this.allRecipients(),
|
||||
sign = !draft && this.pgpSign() && this.canPgpSign(),
|
||||
encrypt = this.pgpEncrypt() && this.canPgpEncrypt(),
|
||||
TextIsHtml = this.oEditor.isHtml(),
|
||||
Text = this.oEditor.getData();
|
||||
TextIsHtml = this.oEditor.isHtml();
|
||||
|
||||
let Text = this.oEditor.getData();
|
||||
if (TextIsHtml) {
|
||||
let l;
|
||||
do {
|
||||
|
|
@ -403,53 +403,70 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
// Remove hubspot data-hs- attributes
|
||||
.replace(/(<[^>]+)\s+data-hs-[a-z-]+=("[^"]+"|'[^']+')/gi, '$1');
|
||||
} while (l != Text.length)
|
||||
params.Html = Text;
|
||||
} else {
|
||||
params.Text = Text;
|
||||
}
|
||||
|
||||
if (this.mailvelope && 'mailvelope' === this.viewArea()) {
|
||||
params.Encrypted = draft
|
||||
? await this.mailvelope.createDraft()
|
||||
: await this.mailvelope.encrypt(recipients);
|
||||
} else if ('openpgp' == encrypt || (sign && 'openpgp' == sign[0])) {
|
||||
} else if (sign || encrypt) {
|
||||
let data = new MimePart;
|
||||
data.headers['Content-Type'] = 'text/'+(TextIsHtml?'html':'plain')+'; charset="utf-8"';
|
||||
data.headers['Content-Transfer-Encoding'] = 'base64';
|
||||
data.body = base64_encode(Text);
|
||||
if (sign && sign[1]) {
|
||||
let signed = new MimePart;
|
||||
signed.headers['Content-Type'] =
|
||||
'multipart/signed; micalg="pgp-sha256"; protocol="application/pgp-signature"';
|
||||
signed.headers['Content-Transfer-Encoding'] = '7Bit';
|
||||
signed.children.push(data);
|
||||
let signature = new MimePart;
|
||||
signature.headers['Content-Type'] = 'application/pgp-signature; name="signature.asc"';
|
||||
signature.headers['Content-Transfer-Encoding'] = '7Bit';
|
||||
signature.body = await OpenPGPUserStore.sign(data.toString(), sign[1], 1);
|
||||
signed.children.push(signature);
|
||||
data = signed;
|
||||
}
|
||||
if (encrypt) {
|
||||
params.Encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients);
|
||||
} else {
|
||||
params.Signed = data.toString();
|
||||
}
|
||||
} else if ('gnupg' == encrypt || (sign && 'gnupg' == sign[0])) {
|
||||
params.Html = TextIsHtml ? Text : '';
|
||||
params.Text = TextIsHtml ? '' : Text;
|
||||
/* // TODO: sign in PHP fails
|
||||
if (sign) {
|
||||
params.SignFingerprint = sign[1].fingerprint;
|
||||
params.SignPassphrase = await GnuPGUserStore.sign(sign[1]);
|
||||
if (TextIsHtml) {
|
||||
let alternative = new MimePart;
|
||||
alternative.headers['Content-Type'] = 'multipart/alternative';
|
||||
alternative.children.push(data);
|
||||
data = new MimePart;
|
||||
data.headers['Content-Type'] = 'text/plain; charset="utf-8"';
|
||||
data.headers['Content-Transfer-Encoding'] = 'base64';
|
||||
data.body = base64_encode(htmlToPlain(Text));
|
||||
alternative.children.push(data);
|
||||
data = alternative;
|
||||
}
|
||||
if (sign && !draft && sign[1]) {
|
||||
if ('openpgp' == sign[0]) {
|
||||
// Doesn't sign attachments
|
||||
let signed = new MimePart;
|
||||
signed.headers['Content-Type'] =
|
||||
'multipart/signed; micalg="pgp-sha256"; protocol="application/pgp-signature"';
|
||||
signed.headers['Content-Transfer-Encoding'] = '7Bit';
|
||||
signed.children.push(data);
|
||||
let signature = new MimePart;
|
||||
signature.headers['Content-Type'] = 'application/pgp-signature; name="signature.asc"';
|
||||
signature.headers['Content-Transfer-Encoding'] = '7Bit';
|
||||
signature.body = await OpenPGPUserStore.sign(data.toString(), sign[1], 1);
|
||||
signed.children.push(signature);
|
||||
data = signed;
|
||||
/*
|
||||
} else if ('gnupg' == sign[0])) {
|
||||
// TODO: sign in PHP fails
|
||||
params.SignFingerprint = sign[1].fingerprint;
|
||||
params.SignPassphrase = await GnuPGUserStore.sign(sign[1]);
|
||||
*/
|
||||
if (encrypt) {
|
||||
params.EncryptFingerprints = GnuPGUserStore.getPublicKeyFingerprints(recipients).join(',');
|
||||
} else {
|
||||
throw 'Signing with ' + sign[0] + ' not yet implemented';
|
||||
}
|
||||
params.Signed = data.toString();
|
||||
params.Boundary = data.boundary;
|
||||
params.Html = params.Text = '';
|
||||
}
|
||||
if (encrypt) {
|
||||
if ('openpgp' == encrypt) {
|
||||
// Doesn't encrypt attachments
|
||||
params.Encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients);
|
||||
params.Signed = '';
|
||||
} else if ('gnupg' == encrypt) {
|
||||
// Does encrypt attachments
|
||||
params.EncryptFingerprints = JSON.stringify(GnuPGUserStore.getPublicKeyFingerprints(recipients));
|
||||
} else {
|
||||
throw 'Encryption with ' + encrypt + ' not yet implemented';
|
||||
}
|
||||
}
|
||||
} else if (encrypt) {
|
||||
throw 'Encryption with ' + encrypt + ' not yet implemented';
|
||||
} else if (sign) {
|
||||
throw 'Signing with ' + sign[0] + ' not yet implemented';
|
||||
} else {
|
||||
params.Html = TextIsHtml ? Text : '';
|
||||
params.Text = TextIsHtml ? '' : Text;
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1102,43 +1102,10 @@ trait Messages
|
|||
$aFoundContentLocationUrls = array();
|
||||
$oPart;
|
||||
|
||||
if ($sHtml = $this->GetActionParam('Html', '')) {
|
||||
$oPart = new MimePart;
|
||||
$oPart->Headers->AddByName(
|
||||
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
|
||||
\MailSo\Mime\Enumerations\MimeType::MULTIPART_ALTERNATIVE
|
||||
);
|
||||
$oMessage->SubParts->append($oPart);
|
||||
|
||||
$sHtml = \MailSo\Base\HtmlUtils::BuildHtml($sHtml, $aFoundCids, $aFoundDataURL, $aFoundContentLocationUrls);
|
||||
$this->Plugins()->RunHook('filter.message-html', array($oAccount, $oMessage, &$sHtml));
|
||||
$oAlternativePart = new MimePart;
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/html; charset=utf-8');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, 'quoted-printable');
|
||||
$oAlternativePart->Body = \MailSo\Base\StreamWrappers\Binary::CreateStream(
|
||||
\MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sHtml))),
|
||||
'convert.quoted-printable-encode'
|
||||
);
|
||||
$oPart->SubParts->append($oAlternativePart);
|
||||
|
||||
$sPlain = \MailSo\Base\HtmlUtils::ConvertHtmlToPlain($sHtml);
|
||||
$this->Plugins()->RunHook('filter.message-plain', array($oAccount, $oMessage, &$sPlain));
|
||||
$oAlternativePart = new MimePart;
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/plain; charset=utf-8');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, 'quoted-printable');
|
||||
$oAlternativePart->Body = \MailSo\Base\StreamWrappers\Binary::CreateStream(
|
||||
\MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sPlain))),
|
||||
'convert.quoted-printable-encode'
|
||||
);
|
||||
$oPart->SubParts->append($oAlternativePart);
|
||||
|
||||
unset($oAlternativePart);
|
||||
unset($sHtml);
|
||||
unset($sPlain);
|
||||
|
||||
} else if ($sSigned = $this->GetActionParam('Signed', '')) {
|
||||
if ($sSigned = $this->GetActionParam('Signed', '')) {
|
||||
$aSigned = \explode("\r\n\r\n", $sSigned, 2);
|
||||
$sBoundary = \preg_replace('/^.+boundary="([^"]+)".+$/Dsi', '$1', $aSigned[0]);
|
||||
// $sBoundary = \preg_replace('/^.+boundary="([^"]+)".+$/Dsi', '$1', $aSigned[0]);
|
||||
$sBoundary = $this->GetActionParam('Boundary', '');
|
||||
|
||||
$oPart = new MimePart;
|
||||
$oPart->Headers->AddByName(
|
||||
|
|
@ -1178,40 +1145,76 @@ trait Messages
|
|||
unset($sEncrypted);
|
||||
|
||||
} else {
|
||||
$sPlain = $this->GetActionParam('Text', '');
|
||||
if ($sSignature = $this->GetActionParam('Signature', null)) {
|
||||
if ($sHtml = $this->GetActionParam('Html', '')) {
|
||||
$oPart = new MimePart;
|
||||
$oPart->Headers->AddByName(
|
||||
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
|
||||
'multipart/signed; micalg="pgp-sha256"; protocol="application/pgp-signature"'
|
||||
\MailSo\Mime\Enumerations\MimeType::MULTIPART_ALTERNATIVE
|
||||
);
|
||||
$oMessage->SubParts->append($oPart);
|
||||
|
||||
$sHtml = \MailSo\Base\HtmlUtils::BuildHtml($sHtml, $aFoundCids, $aFoundDataURL, $aFoundContentLocationUrls);
|
||||
$this->Plugins()->RunHook('filter.message-html', array($oAccount, $oMessage, &$sHtml));
|
||||
$oAlternativePart = new MimePart;
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/plain; charset="utf-8"; protected-headers="v1"');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, 'base64');
|
||||
$oAlternativePart->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sPlain)));
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/html; charset=utf-8');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, 'quoted-printable');
|
||||
$oAlternativePart->Body = \MailSo\Base\StreamWrappers\Binary::CreateStream(
|
||||
\MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sHtml))),
|
||||
'convert.quoted-printable-encode'
|
||||
);
|
||||
$oPart->SubParts->append($oAlternativePart);
|
||||
|
||||
$oAlternativePart = new MimePart;
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'application/pgp-signature; name="signature.asc"');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, '7Bit');
|
||||
$oAlternativePart->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sSignature)));
|
||||
$oPart->SubParts->append($oAlternativePart);
|
||||
} else {
|
||||
$sPlain = \MailSo\Base\HtmlUtils::ConvertHtmlToPlain($sHtml);
|
||||
$this->Plugins()->RunHook('filter.message-plain', array($oAccount, $oMessage, &$sPlain));
|
||||
$oAlternativePart = new MimePart;
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/plain; charset="utf-8"');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/plain; charset=utf-8');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, 'quoted-printable');
|
||||
$oAlternativePart->Body = \MailSo\Base\StreamWrappers\Binary::CreateStream(
|
||||
\MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sPlain))),
|
||||
'convert.quoted-printable-encode'
|
||||
);
|
||||
$oMessage->SubParts->append($oAlternativePart);
|
||||
$oPart->SubParts->append($oAlternativePart);
|
||||
|
||||
unset($oAlternativePart);
|
||||
unset($sHtml);
|
||||
unset($sPlain);
|
||||
|
||||
} else {
|
||||
$sPlain = $this->GetActionParam('Text', '');
|
||||
if ($sSignature = $this->GetActionParam('Signature', null)) {
|
||||
$oPart = new MimePart;
|
||||
$oPart->Headers->AddByName(
|
||||
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
|
||||
'multipart/signed; micalg="pgp-sha256"; protocol="application/pgp-signature"'
|
||||
);
|
||||
$oMessage->SubParts->append($oPart);
|
||||
|
||||
$oAlternativePart = new MimePart;
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/plain; charset="utf-8"; protected-headers="v1"');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, 'base64');
|
||||
$oAlternativePart->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sPlain)));
|
||||
$oPart->SubParts->append($oAlternativePart);
|
||||
|
||||
$oAlternativePart = new MimePart;
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'application/pgp-signature; name="signature.asc"');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, '7Bit');
|
||||
$oAlternativePart->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sSignature)));
|
||||
$oPart->SubParts->append($oAlternativePart);
|
||||
} else {
|
||||
$this->Plugins()->RunHook('filter.message-plain', array($oAccount, $oMessage, &$sPlain));
|
||||
$oAlternativePart = new MimePart;
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/plain; charset="utf-8"');
|
||||
$oAlternativePart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, 'quoted-printable');
|
||||
$oAlternativePart->Body = \MailSo\Base\StreamWrappers\Binary::CreateStream(
|
||||
\MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(\preg_replace('/\\R/', "\r\n", \trim($sPlain))),
|
||||
'convert.quoted-printable-encode'
|
||||
);
|
||||
$oMessage->SubParts->append($oAlternativePart);
|
||||
}
|
||||
unset($oAlternativePart);
|
||||
unset($sSignature);
|
||||
unset($sPlain);
|
||||
}
|
||||
unset($oAlternativePart);
|
||||
unset($sSignature);
|
||||
unset($sPlain);
|
||||
}
|
||||
unset($oPart);
|
||||
|
||||
|
|
@ -1305,15 +1308,14 @@ trait Messages
|
|||
*/
|
||||
}
|
||||
|
||||
// TODO: encrypt
|
||||
$sFingerprints = $this->GetActionParam('EncryptFingerprints', '');
|
||||
if ($sFingerprints) {
|
||||
$aFingerprints = \json_decode($this->GetActionParam('EncryptFingerprints', ''), true);
|
||||
if ($aFingerprints) {
|
||||
$GPG = $this->GnuPG();
|
||||
$oBody = $oMessage->GetRootPart();
|
||||
$fp = \fopen('php://memory', 'r+b');
|
||||
$resource = $oBody->ToStream();
|
||||
\stream_copy_to_stream($resource, $fp);
|
||||
foreach (\explode(',', $sFingerprints) as $sFingerprint) {
|
||||
foreach ($aFingerprints as $sFingerprint) {
|
||||
$GPG->addEncryptKey($sFingerprint);
|
||||
}
|
||||
$sEncrypted = $GPG->encryptStream($fp);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue