mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Added Import S/MIME certificate popup
And much better handling of the sign and encrypt options
This commit is contained in:
parent
f94fc34d4f
commit
6f33bc23d3
47 changed files with 375 additions and 227 deletions
|
|
@ -16,6 +16,7 @@ import { OpenPgpImportPopupView } from 'View/Popup/OpenPgpImport';
|
||||||
import { OpenPgpGeneratePopupView } from 'View/Popup/OpenPgpGenerate';
|
import { OpenPgpGeneratePopupView } from 'View/Popup/OpenPgpGenerate';
|
||||||
|
|
||||||
import { SMimeUserStore } from 'Stores/User/SMime';
|
import { SMimeUserStore } from 'Stores/User/SMime';
|
||||||
|
import { SMimeImportPopupView } from 'View/Popup/SMimeImport';
|
||||||
|
|
||||||
import Remote from 'Remote/User/Fetch';
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
|
||||||
|
|
@ -70,6 +71,10 @@ export class UserSettingsSecurity extends AbstractViewSettings {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
importToSMime() {
|
||||||
|
showScreenPopup(SMimeImportPopupView);
|
||||||
|
}
|
||||||
|
|
||||||
onBuild() {
|
onBuild() {
|
||||||
/**
|
/**
|
||||||
* Create an iframe to display the Mailvelope keyring settings.
|
* Create an iframe to display the Mailvelope keyring settings.
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ export const GnuPGUserStore = new class {
|
||||||
this.keyring = null;
|
this.keyring = null;
|
||||||
this.publicKeys([]);
|
this.publicKeys([]);
|
||||||
this.privateKeys([]);
|
this.privateKeys([]);
|
||||||
Remote.request('GnupgGetKeys',
|
SettingsCapa('GnuPG')
|
||||||
|
&& Remote.request('GnupgGetKeys',
|
||||||
(iError, oData) => {
|
(iError, oData) => {
|
||||||
if (oData?.Result) {
|
if (oData?.Result) {
|
||||||
this.keyring = oData.Result;
|
this.keyring = oData.Result;
|
||||||
|
|
|
||||||
124
dev/Stores/User/Mailvelope.js
Normal file
124
dev/Stores/User/Mailvelope.js
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
import { SettingsGet } from 'Common/Globals';
|
||||||
|
|
||||||
|
// https://mailvelope.github.io/mailvelope/Keyring.html
|
||||||
|
let mailvelopeKeyring = null;
|
||||||
|
|
||||||
|
export const MailvelopeUserStore = {
|
||||||
|
keyring: null,
|
||||||
|
|
||||||
|
loadKeyring(identifier) {
|
||||||
|
identifier = identifier || SettingsGet('Email');
|
||||||
|
if (window.mailvelope) {
|
||||||
|
const fn = keyring => {
|
||||||
|
mailvelopeKeyring = keyring;
|
||||||
|
console.log('mailvelope ready');
|
||||||
|
};
|
||||||
|
mailvelope.getKeyring().then(fn, err => {
|
||||||
|
if (identifier) {
|
||||||
|
// attempt to create a new keyring for this app/user
|
||||||
|
mailvelope.createKeyring(identifier).then(fn, err => console.error(err));
|
||||||
|
} else {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
addEventListener('mailvelope-disconnect', event => {
|
||||||
|
alert('Mailvelope is updated to version ' + event.detail.version + '. Reload page');
|
||||||
|
}, false);
|
||||||
|
} else {
|
||||||
|
addEventListener('mailvelope', () => this.loadKeyring(identifier));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async hasPublicKeyForEmails(recipients) {
|
||||||
|
const
|
||||||
|
mailvelope = mailvelopeKeyring && await mailvelopeKeyring.validKeyForAddress(recipients)
|
||||||
|
/*.then(LookupResult => Object.entries(LookupResult))*/,
|
||||||
|
entries = mailvelope && Object.entries(mailvelope);
|
||||||
|
return entries && entries.filter(value => value[1]).length === recipients.length;
|
||||||
|
},
|
||||||
|
|
||||||
|
async getPrivateKeyFor(email/*, sign*/) {
|
||||||
|
if (mailvelopeKeyring && await mailvelopeKeyring.hasPrivateKey({email:email})) {
|
||||||
|
return ['mailvelope', email];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
async decrypt(message) {
|
||||||
|
// Try Mailvelope (does not support inline images)
|
||||||
|
if (mailvelopeKeyring) {
|
||||||
|
const sender = message.from[0].email,
|
||||||
|
armoredText = message.plain();
|
||||||
|
try {
|
||||||
|
let emails = [...message.from,...message.to,...message.cc].validUnique(),
|
||||||
|
i = emails.length;
|
||||||
|
while (i--) {
|
||||||
|
if (await this.getMailvelopePrivateKeyFor(emails[i].email)) {
|
||||||
|
/**
|
||||||
|
* https://mailvelope.github.io/mailvelope/Mailvelope.html#createEncryptedFormContainer
|
||||||
|
* Creates an iframe to display an encrypted form
|
||||||
|
*/
|
||||||
|
// mailvelope.createEncryptedFormContainer('#mailvelope-form');
|
||||||
|
/**
|
||||||
|
* https://mailvelope.github.io/mailvelope/Mailvelope.html#createDisplayContainer
|
||||||
|
* Creates an iframe to display the decrypted content of the encrypted mail.
|
||||||
|
*/
|
||||||
|
const body = message.body;
|
||||||
|
body.textContent = '';
|
||||||
|
let result = await mailvelope.createDisplayContainer(
|
||||||
|
'#'+body.id,
|
||||||
|
armoredText,
|
||||||
|
mailvelopeKeyring,
|
||||||
|
{
|
||||||
|
senderAddress: sender
|
||||||
|
// emails[i].email
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (result) {
|
||||||
|
if (result.error?.message) {
|
||||||
|
if ('PWD_DIALOG_CANCEL' !== result.error.code) {
|
||||||
|
alert(result.error.code + ': ' + result.error.message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body.classList.add('mailvelope');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns headers that should be added to an outgoing email.
|
||||||
|
* So far this is only the autocrypt header.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
mailvelopeKeyring.additionalHeadersForOutgoingEmail(from: 'abc@web.de')
|
||||||
|
.then(function(additional) {
|
||||||
|
console.log('additionalHeadersForOutgoingEmail', additional);
|
||||||
|
// logs: {autocrypt: "addr=abc@web.de; prefer-encrypt=mutual; keydata=..."}
|
||||||
|
});
|
||||||
|
|
||||||
|
mailvelopeKeyring.addSyncHandler(syncHandlerObj)
|
||||||
|
mailvelopeKeyring.createKeyBackupContainer(selector, options)
|
||||||
|
mailvelopeKeyring.createKeyGenContainer(selector, {
|
||||||
|
// userIds: [],
|
||||||
|
keySize: 4096
|
||||||
|
})
|
||||||
|
|
||||||
|
mailvelopeKeyring.exportOwnPublicKey(emailAddr).then(<AsciiArmored, Error>)
|
||||||
|
mailvelopeKeyring.importPublicKey(armored)
|
||||||
|
|
||||||
|
// https://mailvelope.github.io/mailvelope/global.html#SyncHandlerObject
|
||||||
|
mailvelopeKeyring.addSyncHandler({
|
||||||
|
uploadSync
|
||||||
|
downloadSync
|
||||||
|
backup
|
||||||
|
restore
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
@ -8,12 +8,10 @@ import { SettingsCapa, SettingsGet } from 'Common/Globals';
|
||||||
|
|
||||||
import { GnuPGUserStore } from 'Stores/User/GnuPG';
|
import { GnuPGUserStore } from 'Stores/User/GnuPG';
|
||||||
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
||||||
|
import { MailvelopeUserStore } from 'Stores/User/Mailvelope';
|
||||||
|
|
||||||
import Remote from 'Remote/User/Fetch';
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
|
||||||
// https://mailvelope.github.io/mailvelope/Keyring.html
|
|
||||||
let mailvelopeKeyring = null;
|
|
||||||
|
|
||||||
export const
|
export const
|
||||||
BEGIN_PGP_MESSAGE = '-----BEGIN PGP MESSAGE-----',
|
BEGIN_PGP_MESSAGE = '-----BEGIN PGP MESSAGE-----',
|
||||||
// BEGIN_PGP_SIGNATURE = '-----BEGIN PGP SIGNATURE-----',
|
// BEGIN_PGP_SIGNATURE = '-----BEGIN PGP SIGNATURE-----',
|
||||||
|
|
@ -37,32 +35,9 @@ export const
|
||||||
}
|
}
|
||||||
|
|
||||||
loadKeyrings(identifier) {
|
loadKeyrings(identifier) {
|
||||||
identifier = identifier || SettingsGet('Email');
|
MailvelopeUserStore.loadKeyring(identifier);
|
||||||
if (window.mailvelope) {
|
|
||||||
const fn = keyring => {
|
|
||||||
mailvelopeKeyring = keyring;
|
|
||||||
console.log('mailvelope ready');
|
|
||||||
};
|
|
||||||
mailvelope.getKeyring().then(fn, err => {
|
|
||||||
if (identifier) {
|
|
||||||
// attempt to create a new keyring for this app/user
|
|
||||||
mailvelope.createKeyring(identifier).then(fn, err => console.error(err));
|
|
||||||
} else {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addEventListener('mailvelope-disconnect', event => {
|
|
||||||
alert('Mailvelope is updated to version ' + event.detail.version + '. Reload page');
|
|
||||||
}, false);
|
|
||||||
} else {
|
|
||||||
addEventListener('mailvelope', () => this.loadKeyrings(identifier));
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenPGPUserStore.loadKeyrings();
|
OpenPGPUserStore.loadKeyrings();
|
||||||
|
GnuPGUserStore.loadKeyrings();
|
||||||
if (SettingsCapa('GnuPG')) {
|
|
||||||
GnuPGUserStore.loadKeyrings();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -92,22 +67,14 @@ export const
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
OpenPGPUserStore.isSupported() && OpenPGPUserStore.importKey(key);
|
OpenPGPUserStore.importKey(key);
|
||||||
}
|
|
||||||
|
|
||||||
async mailvelopeHasPublicKeyForEmails(recipients) {
|
|
||||||
const
|
|
||||||
mailvelope = mailvelopeKeyring && await mailvelopeKeyring.validKeyForAddress(recipients)
|
|
||||||
/*.then(LookupResult => Object.entries(LookupResult))*/,
|
|
||||||
entries = mailvelope && Object.entries(mailvelope);
|
|
||||||
return entries && entries.filter(value => value[1]).length === recipients.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if verifying/encrypting a message is possible with given email addresses.
|
* Checks if verifying/encrypting a message is possible with given email addresses.
|
||||||
* Returns the first library that can.
|
* Returns the first library that can.
|
||||||
*/
|
*/
|
||||||
async hasPublicKeyForEmails(recipients) {
|
hasPublicKeyForEmails(recipients) {
|
||||||
if (recipients.length) {
|
if (recipients.length) {
|
||||||
if (GnuPGUserStore.hasPublicKeyForEmails(recipients)) {
|
if (GnuPGUserStore.hasPublicKeyForEmails(recipients)) {
|
||||||
return 'gnupg';
|
return 'gnupg';
|
||||||
|
|
@ -119,40 +86,15 @@ export const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMailvelopePrivateKeyFor(email/*, sign*/) {
|
|
||||||
if (mailvelopeKeyring && await mailvelopeKeyring.hasPrivateKey({email:email})) {
|
|
||||||
return ['mailvelope', email];
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if signing a message is possible with given email address.
|
|
||||||
* Returns the first library that can.
|
|
||||||
*/
|
|
||||||
async getKeyForSigning(email) {
|
|
||||||
let key = OpenPGPUserStore.getPrivateKeyFor(email, 1);
|
|
||||||
if (key) {
|
|
||||||
return ['openpgp', key];
|
|
||||||
}
|
|
||||||
|
|
||||||
key = GnuPGUserStore.getPrivateKeyFor(email, 1);
|
|
||||||
if (key) {
|
|
||||||
return ['gnupg', key];
|
|
||||||
}
|
|
||||||
|
|
||||||
// return await this.getMailvelopePrivateKeyFor(email, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
async decrypt(message) {
|
async decrypt(message) {
|
||||||
const sender = message.from[0].email,
|
const armoredText = message.plain();
|
||||||
armoredText = message.plain();
|
|
||||||
if (!this.isEncrypted(armoredText)) {
|
if (!this.isEncrypted(armoredText)) {
|
||||||
throw Error('Not armored text');
|
throw Error('Not armored text');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try OpenPGP.js
|
// Try OpenPGP.js
|
||||||
if (OpenPGPUserStore.isSupported()) {
|
if (OpenPGPUserStore.isSupported()) {
|
||||||
|
const sender = message.from[0].email;
|
||||||
let result = await OpenPGPUserStore.decrypt(armoredText, sender);
|
let result = await OpenPGPUserStore.decrypt(armoredText, sender);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -160,52 +102,9 @@ export const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try Mailvelope (does not support inline images)
|
// Try Mailvelope (does not support inline images)
|
||||||
if (mailvelopeKeyring) {
|
return (await MailvelopeUserStore.decrypt(message))
|
||||||
try {
|
// Or try GnuPG
|
||||||
let emails = [...message.from,...message.to,...message.cc].validUnique(),
|
|| GnuPGUserStore.decrypt(message);
|
||||||
i = emails.length;
|
|
||||||
while (i--) {
|
|
||||||
if (await this.getMailvelopePrivateKeyFor(emails[i].email)) {
|
|
||||||
/**
|
|
||||||
* https://mailvelope.github.io/mailvelope/Mailvelope.html#createEncryptedFormContainer
|
|
||||||
* Creates an iframe to display an encrypted form
|
|
||||||
*/
|
|
||||||
// mailvelope.createEncryptedFormContainer('#mailvelope-form');
|
|
||||||
/**
|
|
||||||
* https://mailvelope.github.io/mailvelope/Mailvelope.html#createDisplayContainer
|
|
||||||
* Creates an iframe to display the decrypted content of the encrypted mail.
|
|
||||||
*/
|
|
||||||
const body = message.body;
|
|
||||||
body.textContent = '';
|
|
||||||
let result = await mailvelope.createDisplayContainer(
|
|
||||||
'#'+body.id,
|
|
||||||
armoredText,
|
|
||||||
mailvelopeKeyring,
|
|
||||||
{
|
|
||||||
senderAddress: sender
|
|
||||||
// emails[i].email
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (result) {
|
|
||||||
if (result.error?.message) {
|
|
||||||
if ('PWD_DIALOG_CANCEL' !== result.error.code) {
|
|
||||||
alert(result.error.code + ': ' + result.error.message);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
body.classList.add('mailvelope');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now try GnuPG
|
|
||||||
return GnuPGUserStore.decrypt(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async verify(message) {
|
async verify(message) {
|
||||||
|
|
@ -248,35 +147,4 @@ export const
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns headers that should be added to an outgoing email.
|
|
||||||
* So far this is only the autocrypt header.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
mailvelopeKeyring.additionalHeadersForOutgoingEmail(from: 'abc@web.de')
|
|
||||||
.then(function(additional) {
|
|
||||||
console.log('additionalHeadersForOutgoingEmail', additional);
|
|
||||||
// logs: {autocrypt: "addr=abc@web.de; prefer-encrypt=mutual; keydata=..."}
|
|
||||||
});
|
|
||||||
|
|
||||||
mailvelopeKeyring.addSyncHandler(syncHandlerObj)
|
|
||||||
mailvelopeKeyring.createKeyBackupContainer(selector, options)
|
|
||||||
mailvelopeKeyring.createKeyGenContainer(selector, {
|
|
||||||
// userIds: [],
|
|
||||||
keySize: 4096
|
|
||||||
})
|
|
||||||
|
|
||||||
mailvelopeKeyring.exportOwnPublicKey(emailAddr).then(<AsciiArmored, Error>)
|
|
||||||
mailvelopeKeyring.importPublicKey(armored)
|
|
||||||
|
|
||||||
// https://mailvelope.github.io/mailvelope/global.html#SyncHandlerObject
|
|
||||||
mailvelopeKeyring.addSyncHandler({
|
|
||||||
uploadSync
|
|
||||||
downloadSync
|
|
||||||
backup
|
|
||||||
restore
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import { FolderUserStore } from 'Stores/User/Folder';
|
||||||
import { PgpUserStore } from 'Stores/User/Pgp';
|
import { PgpUserStore } from 'Stores/User/Pgp';
|
||||||
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
||||||
import { GnuPGUserStore } from 'Stores/User/GnuPG';
|
import { GnuPGUserStore } from 'Stores/User/GnuPG';
|
||||||
|
import { MailvelopeUserStore } from 'Stores/User/Mailvelope';
|
||||||
//import { OpenPgpImportPopupView } from 'View/Popup/OpenPgpImport';
|
//import { OpenPgpImportPopupView } from 'View/Popup/OpenPgpImport';
|
||||||
import { SMimeUserStore } from 'Stores/User/SMime';
|
import { SMimeUserStore } from 'Stores/User/SMime';
|
||||||
import { Passphrases } from 'Storage/Passphrases';
|
import { Passphrases } from 'Storage/Passphrases';
|
||||||
|
|
@ -255,13 +256,6 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
doSign: false,
|
doSign: false,
|
||||||
doEncrypt: false,
|
doEncrypt: false,
|
||||||
|
|
||||||
pgpSignKey: false,
|
|
||||||
canPgpEncrypt: false,
|
|
||||||
canMailvelope: false,
|
|
||||||
|
|
||||||
canSMimeSign: false,
|
|
||||||
canSMimeEncrypt: false,
|
|
||||||
|
|
||||||
draftsFolder: '',
|
draftsFolder: '',
|
||||||
draftUid: 0,
|
draftUid: 0,
|
||||||
sending: false,
|
sending: false,
|
||||||
|
|
@ -284,6 +278,8 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.attachments = koArrayWithDestroy();
|
this.attachments = koArrayWithDestroy();
|
||||||
|
this.encryptOptions = koArrayWithDestroy();
|
||||||
|
this.signOptions = koArrayWithDestroy();
|
||||||
|
|
||||||
this.dragAndDropOver = ko.observable(false).extend({ debounce: 1 });
|
this.dragAndDropOver = ko.observable(false).extend({ debounce: 1 });
|
||||||
this.dragAndDropVisible = ko.observable(false).extend({ debounce: 1 });
|
this.dragAndDropVisible = ko.observable(false).extend({ debounce: 1 });
|
||||||
|
|
@ -336,11 +332,9 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
attachmentsInProcessCount: () => this.attachmentsInProcess.length,
|
attachmentsInProcessCount: () => this.attachmentsInProcess.length,
|
||||||
isDraft: () => this.draftsFolder() && this.draftUid(),
|
isDraft: () => this.draftsFolder() && this.draftUid(),
|
||||||
|
|
||||||
canSign: () => {
|
canEncrypt: () => this.encryptOptions().length,
|
||||||
let s = this.canSMimeSign();
|
canMailvelope: () => this.encryptOptions.includes('Mailvelope'),
|
||||||
return this.pgpSignKey() || s;
|
canSign: () => this.signOptions().length,
|
||||||
},
|
|
||||||
canEncrypt: () => this.canPgpEncrypt() | this.canSMimeEncrypt(),
|
|
||||||
|
|
||||||
identitiesOptions: () =>
|
identitiesOptions: () =>
|
||||||
IdentityUserStore.map(item => ({
|
IdentityUserStore.map(item => ({
|
||||||
|
|
@ -361,24 +355,14 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
|
|
||||||
currentIdentity: value => {
|
currentIdentity: value => {
|
||||||
if (value) {
|
if (value) {
|
||||||
const smime = !!(value.smimeKey() && value.smimeCertificate());
|
|
||||||
this.from(value.formattedName());
|
this.from(value.formattedName());
|
||||||
this.doEncrypt(value.pgpEncrypt()/* || SettingsUserStore.pgpEncrypt()*/);
|
this.doEncrypt(value.pgpEncrypt()/* || SettingsUserStore.pgpEncrypt()*/);
|
||||||
this.doSign(smime || value.pgpSign()/* || SettingsUserStore.pgpSign()*/);
|
this.doSign(value.pgpSign()/* || SettingsUserStore.pgpSign()*/);
|
||||||
this.canSMimeSign(smime);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
from: value => {
|
from: () => {
|
||||||
this.pgpSignKey(false);
|
this.initSign();
|
||||||
value = getEmail(value);
|
|
||||||
value && PgpUserStore.getKeyForSigning(value).then(result => {
|
|
||||||
console.log({
|
|
||||||
email: value,
|
|
||||||
pgpSignKey:result
|
|
||||||
});
|
|
||||||
this.pgpSignKey(result)
|
|
||||||
});
|
|
||||||
this.initEncrypt();
|
this.initEncrypt();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -1381,29 +1365,57 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
].join(',').split(',').map(value => getEmail(value.trim())).validUnique();
|
].join(',').split(',').map(value => getEmail(value.trim())).validUnique();
|
||||||
}
|
}
|
||||||
|
|
||||||
initEncrypt() {
|
/**
|
||||||
const recipients = this.allRecipients();
|
* Checks if signing a message is possible with from email address.
|
||||||
PgpUserStore.hasPublicKeyForEmails(recipients).then(result => {
|
* And sets all that can.
|
||||||
console.log({canPgpEncrypt:result});
|
*/
|
||||||
this.canPgpEncrypt(result);
|
initSign() {
|
||||||
});
|
let options = [],
|
||||||
PgpUserStore.mailvelopeHasPublicKeyForEmails(recipients).then(result => {
|
|
||||||
console.log({canMailvelope:result});
|
|
||||||
this.canMailvelope(result);
|
|
||||||
if (!result) {
|
|
||||||
'mailvelope' === this.viewArea() && this.bodyArea();
|
|
||||||
// this.dropMailvelope();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const count = recipients.length,
|
|
||||||
identity = this.currentIdentity(),
|
identity = this.currentIdentity(),
|
||||||
from = (identity.smimeKey() && identity.smimeCertificate()) ? identity.email() : null,
|
email = getEmail(this.from()),
|
||||||
length = count ? recipients.filter(email =>
|
key = OpenPGPUserStore.getPrivateKeyFor(email, 1);
|
||||||
email == from
|
key && options.push(['OpenPGP', key]);
|
||||||
|| SMimeUserStore.find(certificate => email == certificate.emailAddress && certificate.smimeencrypt)
|
key = GnuPGUserStore.getPrivateKeyFor(email, 1);
|
||||||
).length : 0;
|
key && options.push(['GnuPG', key]);
|
||||||
this.canSMimeEncrypt(length && length === count);
|
identity.smimeKey() && identity.smimeCertificate() && identity.email() === email
|
||||||
console.log({canSMimeEncrypt:this.canSMimeEncrypt()});
|
&& options.push(['S/MIME']);
|
||||||
|
console.dir({signOptions: options});
|
||||||
|
this.signOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
initEncrypt() {
|
||||||
|
const recipients = this.allRecipients(),
|
||||||
|
options = [];
|
||||||
|
|
||||||
|
if (recipients.length) {
|
||||||
|
GnuPGUserStore.hasPublicKeyForEmails(recipients)
|
||||||
|
&& options.push('GnuPG');
|
||||||
|
|
||||||
|
OpenPGPUserStore.hasPublicKeyForEmails(recipients)
|
||||||
|
&& options.push('OpenPGP');
|
||||||
|
|
||||||
|
MailvelopeUserStore.hasPublicKeyForEmails(recipients).then(result => {
|
||||||
|
if (result) {
|
||||||
|
options.push('Mailvelope');
|
||||||
|
} else {
|
||||||
|
'mailvelope' === this.viewArea() && this.bodyArea();
|
||||||
|
// this.dropMailvelope();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const count = recipients.length,
|
||||||
|
identity = this.currentIdentity(),
|
||||||
|
from = (identity.smimeKey() && identity.smimeCertificate()) ? identity.email() : null;
|
||||||
|
count
|
||||||
|
&& count === recipients.filter(email =>
|
||||||
|
email == from
|
||||||
|
|| SMimeUserStore.find(certificate => email == certificate.emailAddress && certificate.smimeencrypt)
|
||||||
|
).length
|
||||||
|
&& options.push('S/MIME');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.dir({encryptOptions:options});
|
||||||
|
this.encryptOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMessageRequestParams(sSaveFolder, draft)
|
async getMessageRequestParams(sSaveFolder, draft)
|
||||||
|
|
@ -1464,8 +1476,8 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
linkedData: []
|
linkedData: []
|
||||||
},
|
},
|
||||||
recipients = draft ? [identity.email()] : this.allRecipients(),
|
recipients = draft ? [identity.email()] : this.allRecipients(),
|
||||||
sign = !draft && this.doSign() && (this.pgpSignKey() || this.canSMimeSign()),
|
signOptions = !draft && this.doSign() && this.signOptions(),
|
||||||
encrypt = this.doEncrypt() && (this.canPgpEncrypt() || this.canSMimeEncrypt()),
|
encryptOptions = this.doEncrypt() && this.encryptOptions(),
|
||||||
isHtml = this.oEditor.isHtml();
|
isHtml = this.oEditor.isHtml();
|
||||||
|
|
||||||
if (isHtml) {
|
if (isHtml) {
|
||||||
|
|
@ -1492,7 +1504,7 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
params.autocrypt.push({addr:k, keydata:v.replace(/-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----/g).trim()})
|
params.autocrypt.push({addr:k, keydata:v.replace(/-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----/g).trim()})
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
} else if (sign || encrypt) {
|
} else if (signOptions.length || encryptOptions.length) {
|
||||||
if (!draft && !hasAttachments && !Text.length) {
|
if (!draft && !hasAttachments && !Text.length) {
|
||||||
throw i18n('COMPOSE/ERROR_EMPTY_BODY');
|
throw i18n('COMPOSE/ERROR_EMPTY_BODY');
|
||||||
}
|
}
|
||||||
|
|
@ -1512,9 +1524,10 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
alternative.children.push(data);
|
alternative.children.push(data);
|
||||||
data = alternative;
|
data = alternative;
|
||||||
}
|
}
|
||||||
if (sign) {
|
let sign = true;
|
||||||
if (sign?.[1]) {
|
for (let i = 0; i < signOptions.length; ++i) {
|
||||||
if ('openpgp' == sign[0]) {
|
if ('OpenPGP' == signOptions[i][0]) {
|
||||||
|
try {
|
||||||
// Doesn't sign attachments
|
// Doesn't sign attachments
|
||||||
params.html = params.plain = '';
|
params.html = params.plain = '';
|
||||||
let signed = new MimePart;
|
let signed = new MimePart;
|
||||||
|
|
@ -1525,34 +1538,53 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
let signature = new MimePart;
|
let signature = new MimePart;
|
||||||
signature.headers['Content-Type'] = 'application/pgp-signature; name="signature.asc"';
|
signature.headers['Content-Type'] = 'application/pgp-signature; name="signature.asc"';
|
||||||
signature.headers['Content-Transfer-Encoding'] = '7Bit';
|
signature.headers['Content-Transfer-Encoding'] = '7Bit';
|
||||||
signature.body = await OpenPGPUserStore.sign(data.toString(), sign[1], 1);
|
signature.body = await OpenPGPUserStore.sign(data.toString(), signOptions[i][1], 1);
|
||||||
signed.children.push(signature);
|
signed.children.push(signature);
|
||||||
params.signed = signed.toString();
|
params.signed = signed.toString();
|
||||||
params.boundary = signed.boundary;
|
params.boundary = signed.boundary;
|
||||||
data = signed;
|
data = signed;
|
||||||
} else if ('gnupg' == sign[0]) {
|
} catch (e) {
|
||||||
// TODO: sign in PHP fails
|
sign = false;
|
||||||
// params.signData = data.toString();
|
console.error(e);
|
||||||
params.signFingerprint = sign[1].fingerprint;
|
|
||||||
params.signPassphrase = await GnuPGUserStore.sign(sign[1]);
|
|
||||||
} else {
|
|
||||||
throw 'Signing with ' + sign[0] + ' not yet implemented';
|
|
||||||
}
|
}
|
||||||
} else if (this.canSMimeSign()) {
|
break;
|
||||||
|
}
|
||||||
|
if ('GnuPG' == signOptions[i][0]) {
|
||||||
|
// TODO: sign in PHP fails
|
||||||
|
let pass = await GnuPGUserStore.sign(signOptions[i][1]);
|
||||||
|
if (null != pass) {
|
||||||
|
// params.signData = data.toString();
|
||||||
|
params.signFingerprint = signOptions[i][1].fingerprint;
|
||||||
|
params.signPassphrase = pass;
|
||||||
|
} else {
|
||||||
|
sign = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ('S/MIME' == signOptions[i][0]) {
|
||||||
|
// TODO: sign in PHP fails
|
||||||
params.signCertificate = identity.smimeCertificate();
|
params.signCertificate = identity.smimeCertificate();
|
||||||
params.signPrivateKey = identity.smimeKey();
|
params.signPrivateKey = identity.smimeKey();
|
||||||
if (identity.smimeKeyEncrypted()) {
|
if (identity.smimeKeyEncrypted()) {
|
||||||
const pass = await Passphrases.ask(
|
const pass = await Passphrases.ask(
|
||||||
params.signPrivateKey,
|
identity.smimeKey(),
|
||||||
i18n('SMIME/PRIVATE_KEY_OF', {EMAIL: identity.email()}),
|
i18n('SMIME/PRIVATE_KEY_OF', {EMAIL: identity.email()}),
|
||||||
'CRYPTO/DECRYPT'
|
'CRYPTO/DECRYPT'
|
||||||
);
|
);
|
||||||
params.signPassphrase = pass?.password;
|
if (null != pass) {
|
||||||
// pass && pass.remember && Passphrases.set(identity, pass.password);
|
params.signPassphrase = pass.password;
|
||||||
|
// pass.remember && Passphrases.set(identity, pass.password);
|
||||||
|
} else {
|
||||||
|
sign = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (encrypt) {
|
if (signOptions.length && !sign) {
|
||||||
|
throw 'Signing failed';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encryptOptions.length) {
|
||||||
const autocrypt = () =>
|
const autocrypt = () =>
|
||||||
Object.entries(PgpUserStore.getPublicKeyOfEmails(recipients) || {}).forEach(([k,v]) =>
|
Object.entries(PgpUserStore.getPublicKeyOfEmails(recipients) || {}).forEach(([k,v]) =>
|
||||||
params.autocrypt.push({
|
params.autocrypt.push({
|
||||||
|
|
@ -1560,24 +1592,30 @@ export class ComposePopupView extends AbstractViewPopup {
|
||||||
keydata: v.replace(/-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----/g, '').trim()
|
keydata: v.replace(/-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----/g, '').trim()
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
if ('openpgp' == encrypt) {
|
for (let i = 0; i < encryptOptions.length; ++i) {
|
||||||
// Doesn't encrypt attachments
|
if ('OpenPGP' == encryptOptions[i]) {
|
||||||
params.encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients);
|
// Doesn't encrypt attachments
|
||||||
params.signed = '';
|
params.encrypted = await OpenPGPUserStore.encrypt(data.toString(), recipients);
|
||||||
autocrypt();
|
params.signed = '';
|
||||||
} else if ('gnupg' == encrypt) {
|
autocrypt();
|
||||||
// Does encrypt attachments
|
break;
|
||||||
params.encryptFingerprints = JSON.stringify(GnuPGUserStore.getPublicKeyFingerprints(recipients));
|
}
|
||||||
autocrypt();
|
if ('GnuPG' == encryptOptions[i]) {
|
||||||
} else if (this.canSMimeEncrypt() && identity && identity.smimeKey() && identity.smimeCertificate()) {
|
// Does encrypt attachments
|
||||||
params.encryptCertificates = [identity.smimeCertificate()];
|
params.encryptFingerprints = JSON.stringify(GnuPGUserStore.getPublicKeyFingerprints(recipients));
|
||||||
SMimeUserStore.forEach(certificate => {
|
autocrypt();
|
||||||
certificate.emailAddress != identity.email()
|
break;
|
||||||
&& recipients.includes(certificate.emailAddress)
|
}
|
||||||
&& params.encryptCertificates.push(certificate.id)
|
if ('S/MIME' == encryptOptions[i]) {
|
||||||
});
|
params.encryptCertificates = [identity.smimeCertificate()];
|
||||||
} else {
|
SMimeUserStore.forEach(certificate => {
|
||||||
throw 'Encryption with ' + encrypt + ' not yet implemented';
|
certificate.emailAddress != identity.email()
|
||||||
|
&& recipients.includes(certificate.emailAddress)
|
||||||
|
&& params.encryptCertificates.push(certificate.id)
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// We skip Mailvelope as it has its own window
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
50
dev/View/Popup/SMimeImport.js
Normal file
50
dev/View/Popup/SMimeImport.js
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { addObservablesTo } from 'External/ko';
|
||||||
|
import { getNotification } from 'Common/Translator';
|
||||||
|
|
||||||
|
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||||
|
|
||||||
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
|
||||||
|
export class SMimeImportPopupView extends AbstractViewPopup {
|
||||||
|
constructor() {
|
||||||
|
super('SMimeImport');
|
||||||
|
|
||||||
|
addObservablesTo(this, {
|
||||||
|
pem: '',
|
||||||
|
pemError: false,
|
||||||
|
pemErrorMessage: '',
|
||||||
|
pemValid: false
|
||||||
|
});
|
||||||
|
|
||||||
|
this.pem.subscribe(value => {
|
||||||
|
this.pemError(false);
|
||||||
|
this.pemErrorMessage('');
|
||||||
|
this.pemValid(value && value.includes('-----BEGIN CERTIFICATE-----'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
submitForm() {
|
||||||
|
if (this.pemValid()) {
|
||||||
|
Remote.request('SMimeImportCertificate',
|
||||||
|
(iError, oData) => {
|
||||||
|
if (iError) {
|
||||||
|
this.pemError(true);
|
||||||
|
this.pemErrorMessage(getNotification(iError, oData?.ErrorMessage));
|
||||||
|
// oData?.ErrorMessageAdditional;
|
||||||
|
} else {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{pem:this.pem()}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.pemError(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow() {
|
||||||
|
this.pem('');
|
||||||
|
this.pemError(false);
|
||||||
|
this.pemErrorMessage('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -173,6 +173,15 @@ trait SMime
|
||||||
return $this->DefaultResponse($result);
|
return $this->DefaultResponse($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function DoSMimeImportCertificate() : array
|
||||||
|
{
|
||||||
|
return $this->DefaultResponse(
|
||||||
|
$this->SMIME()->storeCertificate(
|
||||||
|
$this->GetActionParam('pem', '')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function DoSMimeImportCertificatesFromMessage() : array
|
public function DoSMimeImportCertificatesFromMessage() : array
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME signed message",
|
"SIGNED_MESSAGE": "S\/MIME signed message",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME encrypted message",
|
"ENCRYPTED_MESSAGE": "S\/MIME encrypted message",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Подписано с S\/MIME",
|
"SIGNED_MESSAGE": "Подписано с S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Шифровано с S\/MIME",
|
"ENCRYPTED_MESSAGE": "Шифровано с S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Zpráva podepsaná S\/MIME",
|
"SIGNED_MESSAGE": "Zpráva podepsaná S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Zpráva šifrovaná S\/MIME",
|
"ENCRYPTED_MESSAGE": "Zpráva šifrovaná S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME signeret meddelelse",
|
"SIGNED_MESSAGE": "S\/MIME signeret meddelelse",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME krypteret meddelelse",
|
"ENCRYPTED_MESSAGE": "S\/MIME krypteret meddelelse",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME-signierte Nachricht",
|
"SIGNED_MESSAGE": "S\/MIME-signierte Nachricht",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME-verschlüsselte Nachricht",
|
"ENCRYPTED_MESSAGE": "S\/MIME-verschlüsselte Nachricht",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Μήνυμα υπογεγραμμένο με S\/MIME",
|
"SIGNED_MESSAGE": "Μήνυμα υπογεγραμμένο με S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Μήνυμα κωδικοποιημένο με S\/MIME",
|
"ENCRYPTED_MESSAGE": "Μήνυμα κωδικοποιημένο με S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME signed message",
|
"SIGNED_MESSAGE": "S\/MIME signed message",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME encrypted message",
|
"ENCRYPTED_MESSAGE": "S\/MIME encrypted message",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S/MIME certificate",
|
||||||
"CERTIFICATES": "S/MIME Certificates",
|
"CERTIFICATES": "S/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S/MIME signed message",
|
"SIGNED_MESSAGE": "S/MIME signed message",
|
||||||
"ENCRYPTED_MESSAGE": "S/MIME encrypted message",
|
"ENCRYPTED_MESSAGE": "S/MIME encrypted message",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Mensaje firmado mediante S\/MIME",
|
"SIGNED_MESSAGE": "Mensaje firmado mediante S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Mensaje cifrado mediante S\/MIME",
|
"ENCRYPTED_MESSAGE": "Mensaje cifrado mediante S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME abil signeeritud kiri",
|
"SIGNED_MESSAGE": "S\/MIME abil signeeritud kiri",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME abil krüpteeritud kiri",
|
"ENCRYPTED_MESSAGE": "S\/MIME abil krüpteeritud kiri",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME sinatutako mezua",
|
"SIGNED_MESSAGE": "S\/MIME sinatutako mezua",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME zifratutako mezua",
|
"ENCRYPTED_MESSAGE": "S\/MIME zifratutako mezua",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "پیام توسط S\/MIME امضاء شد",
|
"SIGNED_MESSAGE": "پیام توسط S\/MIME امضاء شد",
|
||||||
"ENCRYPTED_MESSAGE": "پیام توسط S\/MIME رمزنگاری شد",
|
"ENCRYPTED_MESSAGE": "پیام توسط S\/MIME رمزنگاری شد",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME allekirjoitettu viesti",
|
"SIGNED_MESSAGE": "S\/MIME allekirjoitettu viesti",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME salattu visti",
|
"ENCRYPTED_MESSAGE": "S\/MIME salattu visti",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Message signé par S\/MIME",
|
"SIGNED_MESSAGE": "Message signé par S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Message chiffré par S\/MIME",
|
"ENCRYPTED_MESSAGE": "Message chiffré par S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME aláírt üzenet",
|
"SIGNED_MESSAGE": "S\/MIME aláírt üzenet",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME kódolt üzenet",
|
"ENCRYPTED_MESSAGE": "S\/MIME kódolt üzenet",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Pesan bertanda-tangan S\/MIME",
|
"SIGNED_MESSAGE": "Pesan bertanda-tangan S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Pesan terenkripsi S\/MIME",
|
"ENCRYPTED_MESSAGE": "Pesan terenkripsi S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Skeyti undirritað með S\/MIME",
|
"SIGNED_MESSAGE": "Skeyti undirritað með S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Skeyti dulritað með S\/MIME",
|
"ENCRYPTED_MESSAGE": "Skeyti dulritað með S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Messaggio firmato con S\/MIME",
|
"SIGNED_MESSAGE": "Messaggio firmato con S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Messaggio cifrato con S\/MIME",
|
"ENCRYPTED_MESSAGE": "Messaggio cifrato con S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME署名済みメッセージ",
|
"SIGNED_MESSAGE": "S\/MIME署名済みメッセージ",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME暗号化メッセージ",
|
"ENCRYPTED_MESSAGE": "S\/MIME暗号化メッセージ",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME로 서명된 메세지입니다.",
|
"SIGNED_MESSAGE": "S\/MIME로 서명된 메세지입니다.",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME로 암호화된 메세지입니다.",
|
"ENCRYPTED_MESSAGE": "S\/MIME로 암호화된 메세지입니다.",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME pasirašytas pranešimas",
|
"SIGNED_MESSAGE": "S\/MIME pasirašytas pranešimas",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME šifruotas pranešimas",
|
"ENCRYPTED_MESSAGE": "S\/MIME šifruotas pranešimas",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME signed message",
|
"SIGNED_MESSAGE": "S\/MIME signed message",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME encrypted message",
|
"ENCRYPTED_MESSAGE": "S\/MIME encrypted message",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME-signert melding",
|
"SIGNED_MESSAGE": "S\/MIME-signert melding",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME-kryptert melding",
|
"ENCRYPTED_MESSAGE": "S\/MIME-kryptert melding",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Maak een back-up van de privésleutel op de server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Maak een back-up van de privésleutel op de server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Importeer S\/MIME certificaat",
|
||||||
"CERTIFICATES": "S\/MIME Certificaten",
|
"CERTIFICATES": "S\/MIME Certificaten",
|
||||||
"SIGNED_MESSAGE": "S\/MIME ondertekend bericht",
|
"SIGNED_MESSAGE": "S\/MIME ondertekend bericht",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME versleuteld bericht",
|
"ENCRYPTED_MESSAGE": "S\/MIME versleuteld bericht",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Utwórz kopię zapasową klucza prywatnego na serwerze"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Utwórz kopię zapasową klucza prywatnego na serwerze"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Wiadomość podpisana S\/MIME",
|
"SIGNED_MESSAGE": "Wiadomość podpisana S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Wiadomość zaszyfrowana S\/MIME",
|
"ENCRYPTED_MESSAGE": "Wiadomość zaszyfrowana S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Mensagem assinada com S\/MIME",
|
"SIGNED_MESSAGE": "Mensagem assinada com S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Mensagem criptografada com S\/MIME",
|
"ENCRYPTED_MESSAGE": "Mensagem criptografada com S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Mensagem assinada com S\/MIME",
|
"SIGNED_MESSAGE": "Mensagem assinada com S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME",
|
"ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Mensagem assinada com S\/MIME",
|
"SIGNED_MESSAGE": "Mensagem assinada com S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME",
|
"ENCRYPTED_MESSAGE": "Mensagem encriptada com S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME signed message",
|
"SIGNED_MESSAGE": "S\/MIME signed message",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME encrypted message",
|
"ENCRYPTED_MESSAGE": "S\/MIME encrypted message",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME подписанное сообщение",
|
"SIGNED_MESSAGE": "S\/MIME подписанное сообщение",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME шифрованное сообщение",
|
"ENCRYPTED_MESSAGE": "S\/MIME шифрованное сообщение",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Správa podpísaná s S\/MIME",
|
"SIGNED_MESSAGE": "Správa podpísaná s S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Správa šifrovaná s S\/MIME",
|
"ENCRYPTED_MESSAGE": "Správa šifrovaná s S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Sporočilo, podpisano z S\/MIME",
|
"SIGNED_MESSAGE": "Sporočilo, podpisano z S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Sporočilo, šifrirano z S\/MIME",
|
"ENCRYPTED_MESSAGE": "Sporočilo, šifrirano z S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME-signerat meddelande",
|
"SIGNED_MESSAGE": "S\/MIME-signerat meddelande",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME-krypterat meddelande",
|
"ENCRYPTED_MESSAGE": "S\/MIME-krypterat meddelande",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME imzalı mesaj",
|
"SIGNED_MESSAGE": "S\/MIME imzalı mesaj",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME şifreli mesaj",
|
"ENCRYPTED_MESSAGE": "S\/MIME şifreli mesaj",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "S\/MIME підписане повідомлення",
|
"SIGNED_MESSAGE": "S\/MIME підписане повідомлення",
|
||||||
"ENCRYPTED_MESSAGE": "S\/MIME шифроване повідомлення",
|
"ENCRYPTED_MESSAGE": "S\/MIME шифроване повідомлення",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "Thư đã được ký xác nhận bằng mã S\/MIME",
|
"SIGNED_MESSAGE": "Thư đã được ký xác nhận bằng mã S\/MIME",
|
||||||
"ENCRYPTED_MESSAGE": "Thư đã được mã hóa bởi S\/MIME",
|
"ENCRYPTED_MESSAGE": "Thư đã được mã hóa bởi S\/MIME",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "由 S\/MIME 签名",
|
"SIGNED_MESSAGE": "由 S\/MIME 签名",
|
||||||
"ENCRYPTED_MESSAGE": "由 S\/MIME 加密",
|
"ENCRYPTED_MESSAGE": "由 S\/MIME 加密",
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@
|
||||||
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
"BACKUP_PRIVATE_KEY_ON_SERVER": "Backup private key on server"
|
||||||
},
|
},
|
||||||
"SMIME": {
|
"SMIME": {
|
||||||
|
"POPUP_IMPORT_TITLE": "Import S\/MIME certificate",
|
||||||
"CERTIFICATES": "S\/MIME Certificates",
|
"CERTIFICATES": "S\/MIME Certificates",
|
||||||
"SIGNED_MESSAGE": "已透過 S\/MIME 簽署郵件",
|
"SIGNED_MESSAGE": "已透過 S\/MIME 簽署郵件",
|
||||||
"ENCRYPTED_MESSAGE": "已透過 S\/MIME 加密郵件",
|
"ENCRYPTED_MESSAGE": "已透過 S\/MIME 加密郵件",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
<header>
|
||||||
|
<a href="#" class="close" data-bind="click: close">×</a>
|
||||||
|
<h3 data-i18n="SMIME/POPUP_IMPORT_TITLE"></h3>
|
||||||
|
</header>
|
||||||
|
<form id="smime-import" class="modal-body" autocomplete="off" data-bind="submit: submitForm">
|
||||||
|
<div class="alert" data-bind="visible: pemError() && pemErrorMessage(), text: pemErrorMessage"></div>
|
||||||
|
<div class="control-group" data-bind="css: {'error': pemError}">
|
||||||
|
<textarea class="input-xxlarge" rows="14" autofocus="" autocomplete="off" data-bind="value: pem" required=""></textarea>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<footer>
|
||||||
|
<button class="btn" form="smime-import" data-icon="✚" data-i18n="OPENPGP/POPUP_IMPORT_BUTTON"></button>
|
||||||
|
</footer>
|
||||||
|
|
@ -125,6 +125,8 @@
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary class="legend" data-i18n="SMIME/CERTIFICATES"></summary>
|
<summary class="legend" data-i18n="SMIME/CERTIFICATES"></summary>
|
||||||
|
<button class="btn" data-bind="click: importToSMime" data-icon="✚" data-i18n="OPENPGP/POPUP_IMPORT_BUTTON"></button>
|
||||||
|
|
||||||
<table class="table table-hover list-table">
|
<table class="table table-hover list-table">
|
||||||
<tbody data-bind="foreach: smimeCertificates, i18nUpdate: smimeCertificates">
|
<tbody data-bind="foreach: smimeCertificates, i18nUpdate: smimeCertificates">
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue