diff --git a/dev/App/User.js b/dev/App/User.js index f00a071fa..829aee2b5 100644 --- a/dev/App/User.js +++ b/dev/App/User.js @@ -581,7 +581,7 @@ var sId = Utils.pString(oIdentityData['Id']), sEmail = Utils.pString(oIdentityData['Email']), - oIdentity = new IdentityModel(sId, sEmail, sId !== sAccountEmail) + oIdentity = new IdentityModel(sId, sEmail) ; oIdentity.name(Utils.pString(oIdentityData['Name'])); @@ -1410,7 +1410,6 @@ require('Stores/User/App').populate(); require('Stores/User/Settings').populate(); require('Stores/User/Notification').populate(); - require('Stores/User/Identity').populate(); require('Stores/User/Account').populate(); var @@ -1528,10 +1527,7 @@ self.contactsSync(); }, iContactsSyncInterval * 60000 + 5000); - if (Settings.capa(Enums.Capa.AdditionalAccounts) || Settings.capa(Enums.Capa.AdditionalIdentities)) - { - self.accountsAndIdentities(true); - } + self.accountsAndIdentities(true); _.delay(function () { var sF = Data.currentFolderFullNameRaw(); diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js index b73de81ce..4a5c157ed 100644 --- a/dev/Common/Enums.js +++ b/dev/Common/Enums.js @@ -45,8 +45,7 @@ 'Sieve': 'SIEVE', 'Filters': 'FILTERS', 'AttachmentThumbnails': 'ATTACHMENT_THUMBNAILS', - 'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS', - 'AdditionalIdentities': 'ADDITIONAL_IDENTITIES' + 'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS' }; /** @@ -149,7 +148,8 @@ 'FolderListSize': 4, 'MessageListSize': 5, 'LastReplyAction': 6, - 'LastSignMe': 7 + 'LastSignMe': 7, + 'ComposeLastIdentityID': 8 }; /** diff --git a/dev/Model/Account.js b/dev/Model/Account.js index ea8c11270..97de166d5 100644 --- a/dev/Model/Account.js +++ b/dev/Model/Account.js @@ -28,8 +28,8 @@ this.count = ko.observable(iCount || 0); this.deleteAccess = ko.observable(false); - this.canBeDalete = ko.observable(Utils.isUnd(bCanBeDelete) ? true : !!bCanBeDelete); - this.canBeEdit = this.canBeDalete; + this.canBeDeleted = ko.observable(Utils.isUnd(bCanBeDelete) ? true : !!bCanBeDelete); + this.canBeEdit = this.canBeDeleted; } _.extend(AccountModel.prototype, AbstractModel.prototype); diff --git a/dev/Model/Filter.js b/dev/Model/Filter.js index c950b5944..e72a0f1f8 100644 --- a/dev/Model/Filter.js +++ b/dev/Model/Filter.js @@ -140,7 +140,7 @@ this.regDisposables([this.actionNoStop, this.actionTemplate]); this.deleteAccess = ko.observable(false); - this.canBeDalete = ko.observable(true); + this.canBeDeleted = ko.observable(true); } _.extend(FilterModel.prototype, AbstractModel.prototype); diff --git a/dev/Model/Identity.js b/dev/Model/Identity.js index 6bed8d838..7a6cef544 100644 --- a/dev/Model/Identity.js +++ b/dev/Model/Identity.js @@ -15,41 +15,35 @@ /** * @param {string} sId * @param {string} sEmail - * @param {boolean=} bCanBeDelete = true * @constructor */ - function IdentityModel(sId, sEmail, bCanBeDelete) + function IdentityModel(sId, sEmail) { AbstractModel.call(this, 'IdentityModel'); - this.id = sId; + this.id = ko.observable(sId); this.email = ko.observable(sEmail); this.name = ko.observable(''); + this.replyTo = ko.observable(''); this.bcc = ko.observable(''); this.deleteAccess = ko.observable(false); - this.canBeDalete = ko.observable(bCanBeDelete); + this.canBeDeleted = ko.computed(function () { + return '' !== this.id(); + }, this); } _.extend(IdentityModel.prototype, AbstractModel.prototype); IdentityModel.prototype.formattedName = function () { - var sName = this.name(); - return '' === sName ? this.email() : sName + ' <' + this.email() + '>'; - }; + var + sName = this.name(), + sEmail = this.email() + ; - IdentityModel.prototype.formattedNameForCompose = function () - { - var sName = this.name(); - return '' === sName ? this.email() : sName + ' (' + this.email() + ')'; - }; - - IdentityModel.prototype.formattedNameForEmail = function () - { - var sName = this.name(); - return '' === sName ? this.email() : '"' + Utils.quoteName(sName) + '" <' + this.email() + '>'; + return ('' !== sName) ? sName + ' (' + sEmail + ')' : sEmail; }; module.exports = IdentityModel; diff --git a/dev/Model/Message.js b/dev/Model/Message.js index f9cd6eb61..c0fc83136 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -608,6 +608,16 @@ return MessageModel.emailsToLine(this.bcc, bFriendlyView, bWrapWithLink); }; + /** + * @param {boolean} bFriendlyView + * @param {boolean=} bWrapWithLink = false + * @return {string} + */ + MessageModel.prototype.replyToToLine = function (bFriendlyView, bWrapWithLink) + { + return MessageModel.emailsToLine(this.replyTo, bFriendlyView, bWrapWithLink); + }; + /** * @return string */ @@ -867,6 +877,7 @@ 'popupTo': this.toToLine(false), 'popupCc': this.ccToLine(false), 'popupBcc': this.bccToLine(false), + 'popupReplyTo': this.replyToToLine(false), 'popupSubject': this.subject(), 'popupIsHtml': this.isHtml(), 'popupDate': this.fullFormatDateValue(), diff --git a/dev/Screen/User/Settings.js b/dev/Screen/User/Settings.js index 042cbb521..e477fa84a 100644 --- a/dev/Screen/User/Settings.js +++ b/dev/Screen/User/Settings.js @@ -59,17 +59,6 @@ 'SettingsAccounts', 'SETTINGS_LABELS/LABEL_ACCOUNTS_NAME', 'accounts'); } - if (Settings.capa(Enums.Capa.AdditionalIdentities)) - { - kn.addSettingsViewModel(require('Settings/User/Identities'), - 'SettingsIdentities', 'SETTINGS_LABELS/LABEL_IDENTITIES_NAME', 'identities'); - } - else - { - kn.addSettingsViewModel(require('Settings/User/Identity'), - 'SettingsIdentity', 'SETTINGS_LABELS/LABEL_IDENTITY_NAME', 'identity'); - } - if (Settings.capa(Enums.Capa.Sieve)) { kn.addSettingsViewModel(require('Settings/User/Filters'), diff --git a/dev/Settings/Admin/General.js b/dev/Settings/Admin/General.js index c1be78fa8..929b1d388 100644 --- a/dev/Settings/Admin/General.js +++ b/dev/Settings/Admin/General.js @@ -33,7 +33,6 @@ this.capaUserBackground = CapaAdminStore.userBackground; this.capaGravatar = CapaAdminStore.gravatar; this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts; - this.capaAdditionalIdentities = CapaAdminStore.additionalIdentities; this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails; this.allowLanguagesOnSettings = AppAdminStore.allowLanguagesOnSettings; @@ -106,12 +105,6 @@ }); }); - self.capaAdditionalIdentities.subscribe(function (bValue) { - Remote.saveAdminConfig(null, { - 'CapaAdditionalIdentities': bValue ? '1' : '0' - }); - }); - self.capaGravatar.subscribe(function (bValue) { Remote.saveAdminConfig(null, { 'CapaGravatar': bValue ? '1' : '0' diff --git a/dev/Settings/User/Accounts.js b/dev/Settings/User/Accounts.js index bcaba3c4a..d3a85c51a 100644 --- a/dev/Settings/User/Accounts.js +++ b/dev/Settings/User/Accounts.js @@ -13,6 +13,7 @@ Links = require('Common/Links'), AccountStore = require('Stores/User/Account'), + IdentityStore = require('Stores/User/Identity'), Remote = require('Storage/User/Remote') ; @@ -23,6 +24,7 @@ function AccountsUserSettings() { this.accounts = AccountStore.accounts; + this.identities = IdentityStore.identities; this.processText = ko.computed(function () { return AccountStore.accounts.loading() ? Translator.i18n('SETTINGS_ACCOUNTS/LOADING_PROCESS') : ''; @@ -45,6 +47,20 @@ } } ]}); + + this.identityForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, + function (oPrev) { + if (oPrev) + { + oPrev.deleteAccess(false); + } + }, function (oNext) { + if (oNext) + { + oNext.deleteAccess(true); + } + } + ]}); } AccountsUserSettings.prototype.scrollableOptions = function () @@ -56,17 +72,27 @@ AccountsUserSettings.prototype.addNewAccount = function () { - require('Knoin/Knoin').showScreenPopup(require('View/Popup/AddAccount')); + require('Knoin/Knoin').showScreenPopup(require('View/Popup/Account')); }; AccountsUserSettings.prototype.editAccount = function (oAccountItem) { if (oAccountItem && oAccountItem.canBeEdit()) { - require('Knoin/Knoin').showScreenPopup(require('View/Popup/AddAccount'), [oAccountItem]); + require('Knoin/Knoin').showScreenPopup(require('View/Popup/Account'), [oAccountItem]); } }; + AccountsUserSettings.prototype.addNewIdentity = function () + { + require('Knoin/Knoin').showScreenPopup(require('View/Popup/Identity')); + }; + + AccountsUserSettings.prototype.editIdentity = function (oIdentity) + { + require('Knoin/Knoin').showScreenPopup(require('View/Popup/Identity'), [oIdentity]); + }; + /** * @param {AccountModel} oAccountToRemove */ @@ -110,18 +136,47 @@ } }; + /** + * @param {IdentityModel} oIdentityToRemove + */ + AccountsUserSettings.prototype.deleteIdentity = function (oIdentityToRemove) + { + if (oIdentityToRemove && oIdentityToRemove.deleteAccess()) + { + this.identityForDeletion(null); + + if (oIdentityToRemove) + { + IdentityStore.identities.remove(function (oIdentity) { + return oIdentityToRemove === oIdentity; + }); + + Remote.identityDelete(function () { + require('App/User').accountsAndIdentities(); + }, oIdentityToRemove.id); + } + } + }; + AccountsUserSettings.prototype.onBuild = function (oDom) { var self = this; oDom - .on('click', '.account-item .e-action', function () { + .on('click', '.accounts-list .account-item .e-action', function () { var oAccountItem = ko.dataFor(this); if (oAccountItem) { self.editAccount(oAccountItem); } }) + .on('click', '.identities-list .identity-item .e-action', function () { + var oIdentityItem = ko.dataFor(this); + if (oIdentityItem) + { + self.editIdentity(oIdentityItem); + } + }) ; }; diff --git a/dev/Settings/User/Identities.js b/dev/Settings/User/Identities.js deleted file mode 100644 index daeba7009..000000000 --- a/dev/Settings/User/Identities.js +++ /dev/null @@ -1,226 +0,0 @@ - -(function () { - - 'use strict'; - - var - _ = require('_'), - ko = require('ko'), - - Enums = require('Common/Enums'), - Utils = require('Common/Utils'), - HtmlEditor = require('Common/HtmlEditor'), - Translator = require('Common/Translator'), - - AccountStore = require('Stores/User/Account'), - IdentityStore = require('Stores/User/Identity'), - - Remote = require('Storage/User/Remote') - ; - - /** - * @constructor - */ - function IdentitiesUserSettings() - { - this.editor = null; - this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; - - this.accountEmail = AccountStore.email; - - this.displayName = AccountStore.displayName; - this.signature = AccountStore.signature; - this.replyTo = AccountStore.replyTo; - - this.signatureDom = ko.observable(null); - - this.defaultIdentityIDTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.displayNameTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.replyTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.signatureTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.identities = IdentityStore.identities; - this.defaultIdentityID = IdentityStore.defaultIdentityID; - - this.identitiesOptions = ko.computed(function () { - - var - aList = IdentityStore.identities(), - aResult = [] - ; - - if (0 < aList.length) - { - aResult.push({ - 'id': AccountStore.email.peek(), - 'name': this.formattedAccountIdentity(), - 'seporator': false - }); - - aResult.push({ - 'id': '---', - 'name': '---', - 'seporator': true, - 'disabled': true - }); - - _.each(aList, function (oItem) { - aResult.push({ - 'id': oItem.id, - 'name': oItem.formattedNameForEmail(), - 'seporator': false - }); - }); - } - - return aResult; - }, this); - - this.processText = ko.computed(function () { - return IdentityStore.identities.loading() ? Translator.i18n('SETTINGS_IDENTITIES/LOADING_PROCESS') : ''; - }, this); - - this.visibility = ko.computed(function () { - return '' === this.processText() ? 'hidden' : 'visible'; - }, this); - - this.identityForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, - function (oPrev) { - if (oPrev) - { - oPrev.deleteAccess(false); - } - }, function (oNext) { - if (oNext) - { - oNext.deleteAccess(true); - } - } - ]}); - } - - /** - * - * @return {string} - */ - IdentitiesUserSettings.prototype.formattedAccountIdentity = function () - { - var - sDisplayName = AccountStore.displayName.peek(), - sEmail = AccountStore.email.peek() - ; - - return '' === sDisplayName ? sEmail : '"' + Utils.quoteName(sDisplayName) + '" <' + sEmail + '>'; - }; - - IdentitiesUserSettings.prototype.addNewIdentity = function () - { - require('Knoin/Knoin').showScreenPopup(require('View/Popup/Identity')); - }; - - IdentitiesUserSettings.prototype.editIdentity = function (oIdentity) - { - require('Knoin/Knoin').showScreenPopup(require('View/Popup/Identity'), [oIdentity]); - }; - - /** - * @param {IdentityModel} oIdentityToRemove - */ - IdentitiesUserSettings.prototype.deleteIdentity = function (oIdentityToRemove) - { - if (oIdentityToRemove && oIdentityToRemove.deleteAccess()) - { - this.identityForDeletion(null); - - if (oIdentityToRemove) - { - IdentityStore.identities.remove(function (oIdentity) { - return oIdentityToRemove === oIdentity; - }); - - Remote.identityDelete(function () { - require('App/User').accountsAndIdentities(); - }, oIdentityToRemove.id); - } - } - }; - - IdentitiesUserSettings.prototype.onFocus = function () - { - if (!this.editor && this.signatureDom()) - { - var - self = this, - sSignature = AccountStore.signature() - ; - - this.editor = new HtmlEditor(self.signatureDom(), function () { - AccountStore.signature( - (self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData() - ); - }, function () { - if (':HTML:' === sSignature.substr(0, 6)) - { - self.editor.setHtml(sSignature.substr(6), false); - } - else - { - self.editor.setPlain(sSignature, false); - } - }); - } - }; - - IdentitiesUserSettings.prototype.onBuild = function (oDom) - { - var self = this; - - oDom - .on('click', '.identity-item .e-action', function () { - var oIdentityItem = ko.dataFor(this); - if (oIdentityItem) - { - self.editIdentity(oIdentityItem); - } - }) - ; - - _.delay(function () { - - var - f1 = Utils.settingsSaveHelperSimpleFunction(self.displayNameTrigger, self), - f2 = Utils.settingsSaveHelperSimpleFunction(self.replyTrigger, self), - f3 = Utils.settingsSaveHelperSimpleFunction(self.signatureTrigger, self), - f4 = Utils.settingsSaveHelperSimpleFunction(self.defaultIdentityIDTrigger, self) - ; - - IdentityStore.defaultIdentityID.subscribe(function (sValue) { - Remote.saveSettings(f4, { - 'DefaultIdentityID': sValue - }); - }); - - AccountStore.displayName.subscribe(function (sValue) { - Remote.saveSettings(f1, { - 'DisplayName': sValue - }); - }); - - AccountStore.replyTo.subscribe(function (sValue) { - Remote.saveSettings(f2, { - 'ReplyTo': sValue - }); - }); - - AccountStore.signature.subscribe(function (sValue) { - Remote.saveSettings(f3, { - 'Signature': sValue - }); - }); - - }, 50); - }; - - module.exports = IdentitiesUserSettings; - -}()); \ No newline at end of file diff --git a/dev/Settings/User/Identity.js b/dev/Settings/User/Identity.js deleted file mode 100644 index 873ee33fe..000000000 --- a/dev/Settings/User/Identity.js +++ /dev/null @@ -1,97 +0,0 @@ - -(function () { - - 'use strict'; - - var - _ = require('_'), - ko = require('ko'), - - Enums = require('Common/Enums'), - Utils = require('Common/Utils'), - HtmlEditor = require('Common/HtmlEditor'), - - AccountStore = require('Stores/User/Account'), - - Remote = require('Storage/User/Remote') - ; - - /** - * @constructor - */ - function IdentityUserSettings() - { - this.editor = null; - - this.displayName = AccountStore.displayName; - this.signature = AccountStore.signature; - this.replyTo = AccountStore.replyTo; - - this.signatureDom = ko.observable(null); - - this.displayNameTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.replyTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.signatureTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - } - - IdentityUserSettings.prototype.onFocus = function () - { - if (!this.editor && this.signatureDom()) - { - var - self = this, - sSignature = AccountStore.signature() - ; - - this.editor = new HtmlEditor(self.signatureDom(), function () { - AccountStore.signature( - (self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData() - ); - }, function () { - if (':HTML:' === sSignature.substr(0, 6)) - { - self.editor.setHtml(sSignature.substr(6), false); - } - else - { - self.editor.setPlain(sSignature, false); - } - }); - } - }; - - IdentityUserSettings.prototype.onBuild = function () - { - var self = this; - _.delay(function () { - - var - f1 = Utils.settingsSaveHelperSimpleFunction(self.displayNameTrigger, self), - f2 = Utils.settingsSaveHelperSimpleFunction(self.replyTrigger, self), - f3 = Utils.settingsSaveHelperSimpleFunction(self.signatureTrigger, self) - ; - - AccountStore.displayName.subscribe(function (sValue) { - Remote.saveSettings(f1, { - 'DisplayName': sValue - }); - }); - - AccountStore.replyTo.subscribe(function (sValue) { - Remote.saveSettings(f2, { - 'ReplyTo': sValue - }); - }); - - AccountStore.signature.subscribe(function (sValue) { - Remote.saveSettings(f3, { - 'Signature': sValue - }); - }); - - }, 50); - }; - - module.exports = IdentityUserSettings; - -}()); \ No newline at end of file diff --git a/dev/Storage/User/Remote.js b/dev/Storage/User/Remote.js index 437338ac8..7a467e8e6 100644 --- a/dev/Storage/User/Remote.js +++ b/dev/Storage/User/Remote.js @@ -494,10 +494,10 @@ /** * @param {?Function} fCallback + * @param {string} sIdentityID * @param {string} sMessageFolder * @param {string} sMessageUid * @param {string} sDraftFolder - * @param {string} sFrom * @param {string} sTo * @param {string} sCc * @param {string} sBcc @@ -510,17 +510,18 @@ * @param {string} sReferences * @param {boolean} bMarkAsImportant */ - RemoteUserStorage.prototype.saveMessage = function (fCallback, sMessageFolder, sMessageUid, sDraftFolder, - sFrom, sTo, sCc, sBcc, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences, bMarkAsImportant) + RemoteUserStorage.prototype.saveMessage = function (fCallback, sIdentityID, sMessageFolder, sMessageUid, sDraftFolder, + sTo, sCc, sBcc, sReplyTo, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences, bMarkAsImportant) { this.defaultRequest(fCallback, 'SaveMessage', { + 'IdentityID': sIdentityID, 'MessageFolder': sMessageFolder, 'MessageUid': sMessageUid, 'DraftFolder': sDraftFolder, - 'From': sFrom, 'To': sTo, 'Cc': sCc, 'Bcc': sBcc, + 'ReplyTo': sReplyTo, 'Subject': sSubject, 'TextIsHtml': bTextIsHtml ? '1' : '0', 'Text': sText, @@ -554,13 +555,14 @@ /** * @param {?Function} fCallback + * @param {string} sIdentityID * @param {string} sMessageFolder * @param {string} sMessageUid * @param {string} sSentFolder - * @param {string} sFrom * @param {string} sTo * @param {string} sCc * @param {string} sBcc + * @param {string} sReplyTo * @param {string} sSubject * @param {boolean} bTextIsHtml * @param {string} sText @@ -571,18 +573,19 @@ * @param {boolean} bRequestReadReceipt * @param {boolean} bMarkAsImportant */ - RemoteUserStorage.prototype.sendMessage = function (fCallback, sMessageFolder, sMessageUid, sSentFolder, - sFrom, sTo, sCc, sBcc, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences, + RemoteUserStorage.prototype.sendMessage = function (fCallback, sIdentityID, sMessageFolder, sMessageUid, sSentFolder, + sTo, sCc, sBcc, sReplyTo, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences, bRequestReadReceipt, bMarkAsImportant) { this.defaultRequest(fCallback, 'SendMessage', { + 'IdentityID': sIdentityID, 'MessageFolder': sMessageFolder, 'MessageUid': sMessageUid, 'SentFolder': sSentFolder, - 'From': sFrom, 'To': sTo, 'Cc': sCc, 'Bcc': sBcc, + 'ReplyTo': sReplyTo, 'Subject': sSubject, 'TextIsHtml': bTextIsHtml ? '1' : '0', 'Text': sText, diff --git a/dev/Stores/Admin/Capa.js b/dev/Stores/Admin/Capa.js index 46c97974f..e473d145b 100644 --- a/dev/Stores/Admin/Capa.js +++ b/dev/Stores/Admin/Capa.js @@ -17,7 +17,6 @@ function CapaAdminStore() { this.additionalAccounts = ko.observable(false); - this.additionalIdentities = ko.observable(false); this.gravatar = ko.observable(false); this.attachmentThumbnails = ko.observable(false); this.sieve = ko.observable(false); @@ -31,7 +30,6 @@ CapaAdminStore.prototype.populate = function() { this.additionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts)); - this.additionalIdentities(Settings.capa(Enums.Capa.AdditionalIdentities)); this.gravatar(Settings.capa(Enums.Capa.Gravatar)); this.attachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails)); this.sieve(Settings.capa(Enums.Capa.Sieve)); diff --git a/dev/Stores/User/Account.js b/dev/Stores/User/Account.js index b389c3b6b..f0d0ec0de 100644 --- a/dev/Stores/User/Account.js +++ b/dev/Stores/User/Account.js @@ -21,8 +21,6 @@ // this.incLogin = ko.observable(''); // this.outLogin = ko.observable(''); - this.displayName = ko.observable(''); - this.replyTo = ko.observable(''); this.signature = ko.observable(''); this.accounts = ko.observableArray([]); @@ -70,9 +68,7 @@ // this.incLogin(Settings.settingsGet('IncLogin')); // this.outLogin(Settings.settingsGet('OutLogin')); - this.displayName(Settings.settingsGet('DisplayName')); - this.replyTo(Settings.settingsGet('ReplyTo')); - this.signature(Settings.settingsGet('Signature')); +// this.signature(Settings.settingsGet('Signature')); }; module.exports = new AccountUserStore(); diff --git a/dev/Stores/User/App.js b/dev/Stores/User/App.js index e21817cdb..74f31df59 100644 --- a/dev/Stores/User/App.js +++ b/dev/Stores/User/App.js @@ -7,7 +7,7 @@ ko = require('ko'), Settings = require('Storage/Settings'), - + AppStore = require('Stores/App') ; @@ -36,7 +36,9 @@ this.projectHash(Settings.settingsGet('ProjectHash')); + this.contactsAutosave(!!Settings.settingsGet('ContactsAutosave')); this.useLocalProxyForExternalImages(!!Settings.settingsGet('UseLocalProxyForExternalImages')); + this.contactsIsAllowed(!!Settings.settingsGet('ContactsIsAllowed')); this.devEmail = Settings.settingsGet('DevEmail'); diff --git a/dev/Stores/User/Identity.js b/dev/Stores/User/Identity.js index ac5269c79..4fb95ba71 100644 --- a/dev/Stores/User/Identity.js +++ b/dev/Stores/User/Identity.js @@ -4,9 +4,7 @@ 'use strict'; var - ko = require('ko'), - - Settings = require('Storage/Settings') + ko = require('ko') ; /** @@ -14,17 +12,10 @@ */ function IdentityUserStore() { - this.defaultIdentityID = ko.observable(''); - this.identities = ko.observableArray([]); this.identities.loading = ko.observable(false).extend({'throttle': 100}); } - IdentityUserStore.prototype.populate = function () - { - this.defaultIdentityID(Settings.settingsGet('DefaultIdentityID')); - }; - module.exports = new IdentityUserStore(); }()); diff --git a/dev/Styles/@Main.less b/dev/Styles/@Main.less index 2bc6c4d97..9ad3e3c95 100644 --- a/dev/Styles/@Main.less +++ b/dev/Styles/@Main.less @@ -62,7 +62,7 @@ @import "FolderSystem.less"; @import "Filter.less"; @import "Languages.less"; -@import "AddAccount.less"; +@import "Account.less"; @import "OpenPgpKey.less"; @import "TwoFactor.less"; @import "Identity.less"; @@ -85,8 +85,6 @@ @import "Settings.less"; @import "SettingsGeneral.less"; @import "SettingsAccounts.less"; -@import "SettingsIdentity.less"; -@import "SettingsIdentities.less"; @import "SettingsOpenPGP.less"; @import "SettingsFolders.less"; @import "SettingsThemes.less"; diff --git a/dev/Styles/AddAccount.less b/dev/Styles/Account.less similarity index 92% rename from dev/Styles/AddAccount.less rename to dev/Styles/Account.less index 46ad6813d..c556708ac 100644 --- a/dev/Styles/AddAccount.less +++ b/dev/Styles/Account.less @@ -1,7 +1,7 @@ -.popups { - .b-account-add-content { - .modal-header { - background-color: #fff; - } - } -} +.popups { + .b-account-add-content { + .modal-header { + background-color: #fff; + } + } +} diff --git a/dev/Styles/SettingsAccounts.less b/dev/Styles/SettingsAccounts.less index 68e79915f..9a8419b8d 100644 --- a/dev/Styles/SettingsAccounts.less +++ b/dev/Styles/SettingsAccounts.less @@ -24,7 +24,7 @@ color: #aaa; } - .account-img { + .account-img, .identity-img { font-size: 12px; margin-right: 5px; } @@ -35,6 +35,14 @@ box-sizing: border-box; line-height: 22px; } + + .identity-name { + display: inline-block; + word-break: break-all; + box-sizing: border-box; + line-height: 22px; + cursor: pointer; + } } .account-item { @@ -67,4 +75,31 @@ opacity: 0.5; } } + + .identity-item { + + .e-action { + cursor: pointer; + } + + .button-delete { + margin-right: 15px; + margin-top: 5px; + visibility: hidden; + opacity: 0; + } + + .delete-access { + &.button-delete { + visibility: visible; + margin-right: 0; + opacity: 1; + } + } + + .delete-identity { + cursor: pointer; + opacity: 0.5; + } + } } \ No newline at end of file diff --git a/dev/Styles/SettingsIdentities.less b/dev/Styles/SettingsIdentities.less deleted file mode 100644 index 5545ef66a..000000000 --- a/dev/Styles/SettingsIdentities.less +++ /dev/null @@ -1,66 +0,0 @@ - -.b-settings-identities { - - .process-place { - text-align: center; - width: 600px; - padding: 14px 0; - } - - .e-signature-place { - display: inline-block; - width: 680px; - width: 730px; - height: 250px; - } - - .list-table { - - width: 600px; - - td { - padding: 4px 8px; - line-height: 30px; - } - - .identity-img { - font-size: 12px; - margin-right: 5px; - } - - .identity-name { - display: inline-block; - word-break: break-all; - box-sizing: border-box; - line-height: 22px; - cursor: pointer; - } - } - - .identity-item { - - .e-action { - cursor: pointer; - } - - .button-delete { - margin-right: 15px; - margin-top: 5px; - visibility: hidden; - opacity: 0; - } - - .delete-access { - &.button-delete { - visibility: visible; - margin-right: 0; - opacity: 1; - } - } - - .delete-identity { - cursor: pointer; - opacity: 0.5; - } - } -} diff --git a/dev/Styles/SettingsIdentity.less b/dev/Styles/SettingsIdentity.less deleted file mode 100644 index cb95e2f64..000000000 --- a/dev/Styles/SettingsIdentity.less +++ /dev/null @@ -1,9 +0,0 @@ - -.b-settings-identity { - .e-signature-place { - display: inline-block; - width: 680px; - width: 730px; - height: 250px; - } -} diff --git a/dev/View/Popup/AddAccount.js b/dev/View/Popup/Account.js similarity index 82% rename from dev/View/Popup/AddAccount.js rename to dev/View/Popup/Account.js index 99291002f..9bf99562e 100644 --- a/dev/View/Popup/AddAccount.js +++ b/dev/View/Popup/Account.js @@ -21,9 +21,9 @@ * @constructor * @extends AbstractView */ - function AddAccountPopupView() + function AccountPopupView() { - AbstractView.call(this, 'Popups', 'PopupsAddAccount'); + AbstractView.call(this, 'Popups', 'PopupsAccount'); this.isNew = ko.observable(true); @@ -89,10 +89,10 @@ kn.constructorEnd(this); } - kn.extendAsViewModel(['View/Popup/AddAccount', 'PopupsAddAccountViewModel'], AddAccountPopupView); - _.extend(AddAccountPopupView.prototype, AbstractView.prototype); + kn.extendAsViewModel(['View/Popup/Account', 'View/Popup/AddAccount', 'PopupsAddAccountViewModel'], AccountPopupView); + _.extend(AccountPopupView.prototype, AbstractView.prototype); - AddAccountPopupView.prototype.clearPopup = function () + AccountPopupView.prototype.clearPopup = function () { this.isNew(true); @@ -106,7 +106,7 @@ this.submitError(''); }; - AddAccountPopupView.prototype.onShow = function (oAccount) + AccountPopupView.prototype.onShow = function (oAccount) { this.clearPopup(); if (oAccount && oAccount.canBeEdit()) @@ -116,11 +116,11 @@ } }; - AddAccountPopupView.prototype.onFocus = function () + AccountPopupView.prototype.onFocus = function () { this.emailFocus(true); }; - module.exports = AddAccountPopupView; + module.exports = AccountPopupView; }()); \ No newline at end of file diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index b0ca01f46..dea6dd3ad 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -33,6 +33,7 @@ Data = require('Storage/User/Data'), Cache = require('Storage/User/Cache'), Remote = require('Storage/User/Remote'), + Local = require('Storage/Client'), ComposeAttachmentModel = require('Model/ComposeAttachment'), @@ -48,7 +49,30 @@ { AbstractView.call(this, 'Popups', 'PopupsCompose'); - var self = this; + var + self = this, + fEmailOutInHelper = function (self, oIdentity, sName, bIn) { + if (oIdentity && self && oIdentity[sName]() && (bIn ? true : self[sName]())) + { + var + sIdentityEmail = oIdentity[sName](), + aList = Utils.trim(self[sName]()).split(/[,]/) + ; + + aList = _.filter(aList, function (sEmail) { + sEmail = Utils.trim(sEmail); + return sEmail && Utils.trim(sIdentityEmail) !== sEmail; + }); + + if (bIn) + { + aList.push(sIdentityEmail); + } + + self[sName](aList.join(',')); + } + } + ; this.oEditor = null; this.aDraftInfo = null; @@ -58,8 +82,6 @@ this.triggerForResize = _.bind(this.triggerForResize, this); - this.bCapaAdditionalIdentities = Settings.capa(Enums.Capa.AdditionalIdentities); - this.allowContacts = !!AppStore.contactsIsAllowed(); this.bSkipNextHide = false; @@ -76,8 +98,8 @@ this.to.focusTrigger = ko.observable(false); this.cc = ko.observable(''); this.bcc = ko.observable(''); - this.replyTo = ko.observable(''); + this.subject = ko.observable(''); this.isHtml = ko.observable(false); @@ -97,6 +119,7 @@ this.showCc = ko.observable(false); this.showBcc = ko.observable(false); + this.showReplyTo = ko.observable(false); this.cc.subscribe(function (aValue) { if (false === self.showCc() && 0 < aValue.length) @@ -112,6 +135,13 @@ } }, this); + this.replyTo.subscribe(function (aValue) { + if (false === self.showReplyTo() && 0 < aValue.length) + { + self.showReplyTo(true); + } + }, this); + this.draftFolder = ko.observable(''); this.draftUid = ko.observable(''); this.sending = ko.observable(false); @@ -168,68 +198,63 @@ this.composeEditorArea = ko.observable(null); - this.identities = IdentityStore.identities; - this.defaultIdentityID = IdentityStore.defaultIdentityID; - this.currentIdentityID = ko.observable(''); - - this.currentIdentityString = ko.observable(''); - this.currentIdentityResultEmail = ko.observable(''); - + this.identities = AccountStore.identities; this.identitiesOptions = ko.computed(function () { - - var aList = [{ - 'optValue': AccountStore.email(), - 'optText': this.formattedFrom(false) - }]; - - _.each(IdentityStore.identities(), function (oItem) { - aList.push({ - 'optValue': oItem.id, - 'optText': oItem.formattedNameForCompose() - }); + return _.map(IdentityStore.identities(), function (oItem) { + return { + 'optValue': oItem.id(), + 'optText': oItem.formattedName() + }; }); - - return aList; - }, this); - ko.computed(function () { + this.currentIdentityID = ko.observable( + Local.get(Enums.ClientSideKeyName.ComposeLastIdentityID, '')); + + this.currentIdentity = ko.computed(function () { var - sResult = '', - sResultEmail = '', oItem = null, - aList = IdentityStore.identities(), - sID = this.currentIdentityID() + sID = this.currentIdentityID(), + aList = IdentityStore.identities() ; - if (this.bCapaAdditionalIdentities && sID && sID !== AccountStore.email()) + if (Utils.isArray(aList)) { oItem = _.find(aList, function (oItem) { - return oItem && sID === oItem['id']; + return oItem && sID === oItem.id(); }); - sResult = oItem ? oItem.formattedNameForCompose() : ''; - sResultEmail = oItem ? oItem.formattedNameForEmail() : ''; - - if ('' === sResult && aList[0]) + if (!oItem) { - this.currentIdentityID(aList[0]['id']); - return ''; + oItem = _.find(aList, function (oItem) { + return oItem && '' === oItem.id(); + }); + } + + if (!oItem) + { + oItem = aList[0] ? aList[0] : null; } } - if ('' === sResult) - { - sResult = this.formattedFrom(false); - sResultEmail = this.formattedFrom(true); + return oItem ? oItem : null; + + }, this); + + this.currentIdentity.extend({'toggleSubscribe': [this, + function (oIdentity) { + fEmailOutInHelper(this, oIdentity, 'bcc'); + fEmailOutInHelper(this, oIdentity, 'replyTo'); + }, function (oIdentity) { + fEmailOutInHelper(this, oIdentity, 'bcc', true); + fEmailOutInHelper(this, oIdentity, 'replyTo', true); } + ]}); - this.currentIdentityString(sResult); - this.currentIdentityResultEmail(sResultEmail); - - return sResult; - + this.currentIdentityView = ko.computed(function () { + var oItem = this.currentIdentity(); + return oItem ? oItem.formattedName() : 'unknown'; }, this); this.to.subscribe(function (sValue) { @@ -336,13 +361,14 @@ Remote.sendMessage( this.sendMessageResponse, + this.currentIdentityID(), this.draftFolder(), this.draftUid(), sSentFolder, - this.currentIdentityResultEmail(), sTo, this.cc(), this.bcc(), + this.replyTo(), this.subject(), this.oEditor ? this.oEditor.isHtml() : false, this.oEditor ? this.oEditor.getData(true) : '', @@ -374,13 +400,14 @@ Remote.saveMessage( this.saveMessageResponse, + this.currentIdentityID(), this.draftFolder(), this.draftUid(), FolderStore.draftFolder(), - this.currentIdentityResultEmail(), this.to(), this.cc(), this.bcc(), + this.replyTo(), this.subject(), this.oEditor ? this.oEditor.isHtml() : false, this.oEditor ? this.oEditor.getData(true) : '', @@ -434,6 +461,7 @@ this.showCc.subscribe(this.triggerForResize); this.showBcc.subscribe(this.triggerForResize); + this.showReplyTo.subscribe(this.triggerForResize); this.dropboxEnabled = SocialStore.dropbox.enabled; this.dropboxApiKey = SocialStore.dropbox.apiKey; @@ -538,7 +566,7 @@ }); }, this.oEditor.getData(), - this.currentIdentityResultEmail(), + this.currentIdentity(), this.to(), this.cc(), this.bcc() @@ -566,18 +594,23 @@ } }; - ComposePopupView.prototype.findIdentityIdByMessage = function (sComposeType, oMessage) + ComposePopupView.prototype.findIdentityByMessage = function (sComposeType, oMessage) { var - oIDs = {}, - sResult = '', - sEmail = '', + sDefaultIdentityID = Local.get(Enums.ClientSideKeyName.ComposeLastIdentityID, ''), + aIdentities = IdentityStore.identities(), + oResultIdentity = null, + oIdentitiesCache = {}, fFindHelper = function (oItem) { - if (oItem && oItem.email && oIDs[oItem.email]) + if (oResultIdentity) { - sEmail = oItem.email; - sResult = oIDs[oItem.email]; + return true; + } + + if (!oResultIdentity && oItem && oItem.email && oIdentitiesCache[oItem.email]) + { + oResultIdentity = oIdentitiesCache[oItem.email]; return true; } @@ -585,14 +618,9 @@ } ; - if (this.bCapaAdditionalIdentities) - { - _.each(IdentityStore.identities(), function (oItem) { - oIDs[oItem.email()] = oItem['id']; - }); - } - - oIDs[AccountStore.email()] = AccountStore.email(); + _.each(aIdentities, function (oItem) { + oIdentitiesCache[oItem.email()] = oItem; + }); if (oMessage) { @@ -612,18 +640,26 @@ } } - if ('' === sResult) + if (!oResultIdentity) { - sResult = IdentityStore.defaultIdentityID(); + oResultIdentity = _.find(aIdentities, function (oItem) { + return oItem.id() === sDefaultIdentityID; + }); } - if ('' === sResult) + if (!oResultIdentity && '' !== sDefaultIdentityID) { - sResult = AccountStore.email(); - sEmail = sResult; + oResultIdentity = _.find(aIdentities, function (oItem) { + return oItem.id() === ''; + }); } - return [sResult, sEmail]; + if (!oResultIdentity) + { + oResultIdentity = aIdentities[0] || null; + } + + return oResultIdentity; }; ComposePopupView.prototype.selectIdentity = function (oIdentity) @@ -631,28 +667,10 @@ if (oIdentity) { this.currentIdentityID(oIdentity.optValue); + Local.set(Enums.ClientSideKeyName.ComposeLastIdentityID, oIdentity.optValue); } }; - /** - * - * @param {boolean=} bHeaderResult = false - * @returns {string} - */ - ComposePopupView.prototype.formattedFrom = function (bHeaderResult) - { - var - sDisplayName = AccountStore.displayName(), - sEmail = AccountStore.email() - ; - - return '' === sDisplayName ? sEmail : - ((Utils.isUnd(bHeaderResult) ? false : !!bHeaderResult) ? - '"' + Utils.quoteName(sDisplayName) + '" <' + sEmail + '>' : - sDisplayName + ' (' + sEmail + ')') - ; - }; - ComposePopupView.prototype.sendMessageResponse = function (sResult, oData) { var @@ -964,7 +982,7 @@ sReplyTitle = '', aResplyAllParts = [], oExcludeEmail = {}, - oIdResult = null, + oIdentity = null, mEmail = AccountStore.email(), sSignature = AccountStore.signature(), aDownloads = [], @@ -1000,15 +1018,21 @@ oExcludeEmail[mEmail] = true; } - oIdResult = this.findIdentityIdByMessage(sComposeType, oMessage); - if (oIdResult && oIdResult[0]) + oIdentity = this.findIdentityByMessage(sComposeType, oMessage); + if (oIdentity) { - oExcludeEmail[oIdResult[1]] = true; - this.currentIdentityID(oIdResult[0]); + oExcludeEmail[oIdentity.email()] = true; + this.currentIdentityID(oIdentity.id()); + } + else + { + this.currentIdentityID(''); } this.reset(); + this.currentIdentityID.valueHasMutated(); // Populate BBC from Identity + if (Utils.isNonEmptyArray(aToEmails)) { this.to(fEmailArrayToStringLineHelper(aToEmails)); @@ -1089,6 +1113,7 @@ this.to(fEmailArrayToStringLineHelper(oMessage.to)); this.cc(fEmailArrayToStringLineHelper(oMessage.cc)); this.bcc(fEmailArrayToStringLineHelper(oMessage.bcc)); + this.replyTo(fEmailArrayToStringLineHelper(oMessage.replyTo)); this.bFromDraft = true; @@ -1107,6 +1132,7 @@ this.to(fEmailArrayToStringLineHelper(oMessage.to)); this.cc(fEmailArrayToStringLineHelper(oMessage.cc)); this.bcc(fEmailArrayToStringLineHelper(oMessage.bcc)); + this.replyTo(fEmailArrayToStringLineHelper(oMessage.replyTo)); this.subject(sSubject); this.prepearMessageAttachments(oMessage, sComposeType); @@ -1963,6 +1989,7 @@ return 0 === this.to().length && 0 === this.cc().length && 0 === this.bcc().length && + 0 === this.replyTo().length && 0 === this.subject().length && bWithoutAttach && (!this.oEditor || '' === this.oEditor.getData()) @@ -1997,6 +2024,7 @@ this.showCc(false); this.showBcc(false); + this.showReplyTo(false); Utils.delegateRunOnDestroy(this.attachments()); this.attachments([]); diff --git a/dev/View/Popup/ComposeOpenPgp.js b/dev/View/Popup/ComposeOpenPgp.js index 58956b2ad..220b0d10d 100644 --- a/dev/View/Popup/ComposeOpenPgp.js +++ b/dev/View/Popup/ComposeOpenPgp.js @@ -215,25 +215,17 @@ } }; - ComposeOpenPgpPopupView.prototype.onShow = function (fCallback, sText, sFromEmail, sTo, sCc, sBcc) + ComposeOpenPgpPopupView.prototype.onShow = function (fCallback, sText, oIdentity, sTo, sCc, sBcc) { this.clearPopup(); var - oEmail = new EmailModel(), - sResultFromEmail = '', - aRec = [] + aRec = [], + oEmail = new EmailModel() ; this.resultCallback = fCallback; - oEmail.clear(); - oEmail.mailsoParse(sFromEmail); - if ('' !== oEmail.email) - { - sResultFromEmail = oEmail.email; - } - if ('' !== sTo) { aRec.push(sTo); @@ -256,7 +248,7 @@ return '' === oEmail.email ? false : oEmail.email; })); - this.from(sResultFromEmail); + this.from(oIdentity ? oIdentity.email() : ''); this.to(aRec); this.text(sText); }; diff --git a/dev/View/Popup/Identity.js b/dev/View/Popup/Identity.js index f4ee392a7..a7c543929 100644 --- a/dev/View/Popup/Identity.js +++ b/dev/View/Popup/Identity.js @@ -10,9 +10,9 @@ Enums = require('Common/Enums'), Utils = require('Common/Utils'), Translator = require('Common/Translator'), + HtmlEditor = require('Common/HtmlEditor'), Remote = require('Storage/User/Remote'), - AccountStore = require('Stores/User/Account'), kn = require('Knoin/Knoin'), AbstractView = require('Knoin/AbstractView') @@ -30,6 +30,9 @@ this.edit = ko.observable(false); this.owner = ko.observable(false); + this.editor = null; + this.signatureDom = ko.observable(null); + this.email = ko.observable('').validateEmail(); this.email.focused = ko.observable(false); this.name = ko.observable(''); @@ -39,6 +42,8 @@ this.bcc = ko.observable('').validateSimpleEmail(); this.bcc.focused = ko.observable(false); + this.signature = ko.observable(''); + // this.email.subscribe(function () { // this.email.hasError(false); // }, this); @@ -128,6 +133,11 @@ this.submitRequest(false); this.submitError(''); + + if (this.editor) + { + this.editor.clear(false); + } }; /** @@ -141,18 +151,58 @@ { this.edit(true); - this.id = oIdentity.id; + this.id = oIdentity.id(); this.name(oIdentity.name()); this.email(oIdentity.email()); this.replyTo(oIdentity.replyTo()); this.bcc(oIdentity.bcc()); - this.owner(this.id === AccountStore.email()); + this.owner(this.id === ''); + } + else + { + this.id = Utils.fakeMd5(); + } + }; + + IdentityPopupView.prototype.onHide = function () + { + this.clearPopup(); + }; + + IdentityPopupView.prototype.setSignature = function (sSignature) + { + if (this.editor) + { + if (':HTML:' === sSignature.substr(0, 6)) + { + this.editor.setHtml(sSignature.substr(6), false); + } + else + { + this.editor.setPlain(sSignature, false); + } } }; IdentityPopupView.prototype.onFocus = function () { + if (!this.editor && this.signatureDom()) + { + var self = this; + this.editor = new HtmlEditor(self.signatureDom(), function () { + self.signature( + (self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData() + ); + }, function () { + self.setSignature(self.signature()); + }); + } + else + { + this.setSignature(this.signature()); + } + if (!this.owner()) { this.email.focused(true); diff --git a/dev/View/User/AbstractSystemDropDown.js b/dev/View/User/AbstractSystemDropDown.js index f62df413c..6fbd735b8 100644 --- a/dev/View/User/AbstractSystemDropDown.js +++ b/dev/View/User/AbstractSystemDropDown.js @@ -74,7 +74,7 @@ { if (this.capaAdditionalAccounts()) { - require('Knoin/Knoin').showScreenPopup(require('View/Popup/AddAccount')); + require('Knoin/Knoin').showScreenPopup(require('View/Popup/Account')); } }; diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index bc4a3cbf4..847d14dba 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -186,6 +186,7 @@ this.viewTo = ko.observable(''); this.viewCc = ko.observable(''); this.viewBcc = ko.observable(''); + this.viewReplyTo = ko.observable(''); this.viewDate = ko.observable(''); this.viewSize = ko.observable(''); this.viewMoment = ko.observable(''); @@ -267,6 +268,7 @@ this.viewTo(oMessage.toToLine(false)); this.viewCc(oMessage.ccToLine(false)); this.viewBcc(oMessage.bccToLine(false)); + this.viewReplyTo(oMessage.replyToToLine(false)); this.viewDate(oMessage.fullFormatDateValue()); this.viewSize(oMessage.friendlySize()); this.viewMoment(oMessage.momentDate()); diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php index a4fee9941..c6ae86ee5 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php @@ -232,11 +232,11 @@ abstract class NetClient $this->bSecure = \MailSo\Net\Enumerations\ConnectionSecurityType::UseSSL( $this->iConnectedPort, $this->iSecurityType); - $this->sConnectedHost = \in_array(\strtolower(\substr($this->sConnectedHost, 0, 6)), array('ssl://', 'tcp://')) ? - \substr($this->sConnectedHost, 6) : $this->sConnectedHost; - - $this->sConnectedHost = ($this->bSecure ? 'ssl://' : 'tcp://').$this->sConnectedHost; -// $this->sConnectedHost = ($this->bSecure ? 'ssl://' : '').$this->sConnectedHost; + if (!\preg_match('/^[a-z0-9._]{2,8}:\/\//i', $this->sConnectedHost)) + { + $this->sConnectedHost = ($this->bSecure ? 'ssl://' : 'tcp://').$this->sConnectedHost; +// $this->sConnectedHost = ($this->bSecure ? 'ssl://' : '').$this->sConnectedHost; + } if (!$this->bSecure && \MailSo\Net\Enumerations\ConnectionSecurityType::SSL === $this->iSecurityType) { @@ -307,21 +307,29 @@ abstract class NetClient } } - /** - * @param {int} $iCryptoType = STREAM_CRYPTO_METHOD_TLS_CLIENT - */ - public function EnableCrypto($iCryptoType = STREAM_CRYPTO_METHOD_TLS_CLIENT) + public function EnableCrypto() { + $bError = true; if (\is_resource($this->rConnect) && \MailSo\Base\Utils::FunctionExistsAndEnabled('stream_socket_enable_crypto')) { - if (!@\stream_socket_enable_crypto($this->rConnect, true, $iCryptoType)) + switch (true) { - $this->writeLogException( - new \MailSo\Net\Exceptions\Exception('Cannot enable STARTTLS. [type='.$iCryptoType.']'), - \MailSo\Log\Enumerations\Type::ERROR, true); + case defined('STREAM_CRYPTO_METHOD_ANY_CLIENT') && + @\stream_socket_enable_crypto($this->rConnect, true, STREAM_CRYPTO_METHOD_ANY_CLIENT): + case @\stream_socket_enable_crypto($this->rConnect, true, STREAM_CRYPTO_METHOD_TLS_CLIENT): + case @\stream_socket_enable_crypto($this->rConnect, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT): + $bError = false; + break; } } + + if ($bError) + { + $this->writeLogException( + new \MailSo\Net\Exceptions\Exception('Cannot enable STARTTLS.'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } } /** diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index efd5fe1a6..5196bb7b9 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -1521,9 +1521,6 @@ class Actions $aResult['UseThreads'] = (bool) $oConfig->Get('defaults', 'mail_use_threads', false); $aResult['ReplySameFolder'] = (bool) $oConfig->Get('defaults', 'mail_reply_same_folder', false); $aResult['ContactsAutosave'] = (bool) $oConfig->Get('defaults', 'contacts_autosave', true); - $aResult['DefaultIdentityID'] = ''; - $aResult['DisplayName'] = ''; - $aResult['ReplyTo'] = ''; $aResult['Signature'] = ''; $aResult['EnableTwoFactor'] = false; $aResult['ParentEmail'] = ''; @@ -1557,12 +1554,14 @@ class Actions $aResult['MPP'] = (int) $oSettings->GetConf('MPP', $aResult['MPP']); $aResult['SoundNotification'] = (bool) $oSettings->GetConf('SoundNotification', $aResult['SoundNotification']); $aResult['DesktopNotifications'] = (bool) $oSettings->GetConf('DesktopNotifications', $aResult['DesktopNotifications']); - $aResult['Layout'] = (int) $oSettings->GetConf('Layout', $aResult['Layout']); $aResult['UseCheckboxesInList'] = (bool) $oSettings->GetConf('UseCheckboxesInList', $aResult['UseCheckboxesInList']); + $aResult['Layout'] = (int) $oSettings->GetConf('Layout', $aResult['Layout']); $aResult['UseThreads'] = (bool) $oSettingsLocal->GetConf('UseThreads', $aResult['UseThreads']); $aResult['ReplySameFolder'] = (bool) $oSettingsLocal->GetConf('ReplySameFolder', $aResult['ReplySameFolder']); + $aResult['Signature'] = $oSettingsLocal->GetConf('Signature', $aResult['Signature']); + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::USER_BACKGROUND, $oAccount)) { $aResult['UserBackgroundName'] = (string) $oSettings->GetConf('UserBackgroundName', $aResult['UserBackgroundName']); @@ -1574,11 +1573,6 @@ class Actions // } } - $aResult['DefaultIdentityID'] = $oSettingsLocal->GetConf('DefaultIdentityID', $oAccount ? $oAccount->Email() : $aResult['DefaultIdentityID']); - $aResult['DisplayName'] = $oSettingsLocal->GetConf('DisplayName', $aResult['DisplayName']); - $aResult['ReplyTo'] = $oSettingsLocal->GetConf('ReplyTo', $aResult['ReplyTo']); - $aResult['Signature'] = $oSettingsLocal->GetConf('Signature', $aResult['Signature']); - $aResult['EnableTwoFactor'] = !!$oSettings->GetConf('EnableTwoFactor', $aResult['EnableTwoFactor']); $aResult['ParentEmail'] = $oAccount->ParentEmail(); @@ -2088,7 +2082,11 @@ class Actions 'accounts' ); - $aAccounts = $sAccounts ? @\unserialize($sAccounts) : array(); + if ('' !== $sAccounts && '{' === \substr($sAccounts, 0, 1)) + { + $aAccounts = @\json_decode($sAccounts, true); + } + if (\is_array($aAccounts) && 0 < \count($aAccounts)) { if (1 === \count($aAccounts)) @@ -2135,31 +2133,47 @@ class Actions { $aSubIdentities = array(); - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - if ($oSettingsLocal) + $sData = $this->StorageProvider(true)->Get($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'identities' + ); + + if ('' !== $sData && '[' === \substr($sData, 0, 1)) { - $sData = $oSettingsLocal->GetConf('Identities', ''); - if ('' !== $sData && '[' === \substr($sData, 0, 1)) - { - $aSubIdentities = @\json_decode($sData, true); - $aSubIdentities = \is_array($aSubIdentities) ? $aSubIdentities : array(); - } + $aSubIdentities = @\json_decode($sData, true); } - if (0 < \count($aSubIdentities)) + $bHasAccountIdentity = false; + + if (\is_array($aSubIdentities) && 0 < \count($aSubIdentities)) { foreach ($aSubIdentities as $aItem) { - if (isset($aItem['Id'], $aItem['Email'], $aItem['Name'], $aItem['ReplyTo'], $aItem['Bcc']) && - $aItem['Id'] !== $oAccount->Email()) - { - $oItem = \RainLoop\Model\Identity::NewInstance($aItem['Id'], $aItem['Email'], - $aItem['Name'], $aItem['ReplyTo'], $aItem['Bcc']); + $oItem = \RainLoop\Model\Identity::NewInstance(); + $oItem->FromJSON($aItem); - $aIdentities[] = $oItem; + if ($oItem && $oItem->Validate()) + { + if ('' === $oItem->Id()) + { + $oItem->SetEmail($oAccount->Email()); + $bHasAccountIdentity = true; + + \array_unshift($aIdentities, $oItem); + } + else + { + \array_push($aIdentities, $oItem); + } } } } + + if (!$bHasAccountIdentity) + { + \array_unshift($aIdentities, + \RainLoop\Model\Identity::NewInstanceFromAccount($oAccount)); + } } return $aIdentities; @@ -2167,61 +2181,35 @@ class Actions /** * @param \RainLoop\Model\Account $oAccount + * @param string $sID + * @param bool $bFirstOnEmpty = false * - * @return array + * @return \RainLoop\Model\Identity */ - public function GetIdentitiesNew($oAccount) + public function GetIdentityByID($oAccount, $sID, $bFirstOnEmpty = false) { - $aIdentities = array(); - if ($oAccount) + $aIdentities = $this->GetIdentities($oAccount); + if (\is_array($aIdentities)) { - $oAccountIdentity = \RainLoop\Model\Identity::NewInstance('', $oAccount->Email()); - - $aSubIdentities = array(); - - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - if ($oSettingsLocal) + foreach ($aIdentities as $oIdentity) { - $sData = $oSettingsLocal->GetConf('Identities', ''); - if ('' !== $sData && '[' === \substr($sData, 0, 1)) + if ($oIdentity && $sID === $oIdentity->Id()) { - $aSubIdentities = @\json_decode($sData, true); - $aSubIdentities = \is_array($aSubIdentities) ? $aSubIdentities : array(); + return $oIdentity; } } - - if (0 < \count($aSubIdentities)) - { - foreach ($aSubIdentities as $aItem) - { - if (isset($aItem['Id'], $aItem['Email'])) - { - if (0 < \strlen($aItem['Id'])) - { - $oItem = \RainLoop\Model\Identity::NewInstance($aItem['Id'], $aItem['Email']); - } - else - { - $oItem = $oAccountIdentity; - } - - $oItem->SetName(isset($aItem['Name']) ? $aItem['Name'] : ''); - $oItem->SetReplyTo(isset($aItem['ReplyTo']) ? $aItem['ReplyTo'] : ''); - $oItem->SetBcc(isset($aItem['Bcc']) ? $aItem['Bcc'] : ''); - $oItem->SetSignature(isset($aItem['Signature']) ? $aItem['Signature'] : ''); - - if ('' !== $oItem->Id()) - { - \array_push($aIdentities, $oItem); - } - } - } - } - - \array_unshift($aIdentities, $oAccountIdentity); } - return $aIdentities; + return $bFirstOnEmpty && \is_array($aIdentities) && isset($aIdentities[0]) ? $aIdentities[0] : null; + } + /** + * @param \RainLoop\Model\Account $oAccount + * + * @return \RainLoop\Model\Identity + */ + public function GetAccountIdentity($oAccount) + { + return $this->GetIdentityByID($oAccount, '', true); } /** @@ -2246,7 +2234,7 @@ class Actions $this->StorageProvider()->Put($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts', - @\serialize($aAccounts) + @\json_encode($aAccounts) ); } } @@ -2259,20 +2247,17 @@ class Actions */ public function SetIdentities($oAccount, $aIdentities = array()) { - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - if ($oSettingsLocal) + $aResult = array(); + foreach ($aIdentities as $oItem) { - $aResult = array(); - foreach ($aIdentities as $oItem) - { - $aResult[] = $oItem->ToSimpleJSON(false); - } - - $oSettingsLocal->SetConf('Identities', @\json_encode($aResult)); - return $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal); + $aResult[] = $oItem->ToSimpleJSON(false); } - return false; + return $this->StorageProvider(true)->Put($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'identities', + @\json_encode($aResult) + ); } /** @@ -2443,55 +2428,26 @@ class Actions { $oAccount = $this->getAccountFromToken(); - if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES, $oAccount)) + $oIdentity = \RainLoop\Model\Identity::NewInstance(); + if (!$oIdentity->FromJSON($this->GetActionParams(), true)) { - return $this->FalseResponse(__FUNCTION__); + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument); } - $sId = \trim($this->GetActionParam('Id', '')); - $sEmail = \trim($this->GetActionParam('Email', '')); - $sName = \trim($this->GetActionParam('Name', '')); - $sReplyTo = \trim($this->GetActionParam('ReplyTo', '')); - $sBcc = \trim($this->GetActionParam('Bcc', '')); + $aIdentitiesForSave = array(); - if (empty($sEmail)) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); - } - - $oEditIdentity = null; $aIdentities = $this->GetIdentities($oAccount); - if (0 < \strlen($sId)) + foreach ($aIdentities as $oItem) { - foreach ($aIdentities as &$oItem) + if ($oItem && $oItem->Id() !== $oIdentity->Id()) { - if ($oItem && $sId === $oItem->Id()) - { - $oEditIdentity =& $oItem; - break; - } + $aIdentitiesForSave[] = $oItem; } } - else - { - $sId = \md5($sEmail.\microtime(true)); - } - if (!$oEditIdentity) - { - $aIdentities[] = \RainLoop\Model\Identity::NewInstance($sId, $sEmail, $sName, $sReplyTo, $sBcc); - } - else - { - $oEditIdentity - ->SetEmail($sEmail) - ->SetName($sName) - ->SetReplyTo($sReplyTo) - ->SetBcc($sBcc) - ; - } + $aIdentitiesForSave[] = $oIdentity; - return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aIdentities)); + return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aIdentitiesForSave)); } /** @@ -2503,11 +2459,6 @@ class Actions { $oAccount = $this->getAccountFromToken(); - if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - $sId = \trim($this->GetActionParam('IdToDelete', '')); if (empty($sId)) { @@ -2569,15 +2520,9 @@ class Actions } } - $mIdentities = false; - if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES, $oAccount)) - { - $mIdentities = $this->GetIdentities($oAccount); - } - return $this->DefaultResponse(__FUNCTION__, array( 'Accounts' => $mAccounts, - 'Identities' => $mIdentities + 'Identities' => $this->GetIdentities($oAccount) )); } @@ -2663,33 +2608,6 @@ class Actions )); } - /** - * @return array - * - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoAccountsAndIdentitiesNew() - { - $oAccount = $this->getAccountFromToken(); - - $mAccounts = false; - if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) - { - $mAccounts = $this->GetAccounts($oAccount); - $mAccounts = \array_keys($mAccounts); - - foreach ($mAccounts as $iIndex => $sName) - { - $mAccounts[$iIndex] = \MailSo\Base\Utils::IdnToUtf8($sName); - } - } - - return $this->DefaultResponse(__FUNCTION__, array( - 'Accounts' => $mAccounts, - 'Identities' => $this->GetIdentitiesNew($oAccount) - )); - } - /** * @param \RainLoop\Model\Account $oAccount */ @@ -2879,9 +2797,6 @@ class Actions case \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS: $this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_accounts', 'bool'); break; - case \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES: - $this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_identities', 'bool'); - break; case \RainLoop\Enumerations\Capa::TWO_FACTOR: $this->setConfigFromParams($oConfig, $sParamName, 'security', 'allow_two_factor_auth', 'bool'); break; @@ -2984,7 +2899,6 @@ class Actions }); $this->setCapaFromParams($oConfig, 'CapaAdditionalAccounts', \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS); - $this->setCapaFromParams($oConfig, 'CapaAdditionalIdentities', \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES); $this->setCapaFromParams($oConfig, 'CapaTwoFactorAuth', \RainLoop\Enumerations\Capa::TWO_FACTOR); $this->setCapaFromParams($oConfig, 'CapaOpenPGP', \RainLoop\Enumerations\Capa::OPEN_PGP); $this->setCapaFromParams($oConfig, 'CapaGravatar', \RainLoop\Enumerations\Capa::GRAVATAR); @@ -4461,9 +4375,6 @@ class Actions $this->setSettingsFromParams($oSettingsLocal, 'UseThreads', 'bool'); $this->setSettingsFromParams($oSettingsLocal, 'ReplySameFolder', 'bool'); - $this->setSettingsFromParams($oSettingsLocal, 'DefaultIdentityID', 'string'); - $this->setSettingsFromParams($oSettingsLocal, 'DisplayName', 'string'); - $this->setSettingsFromParams($oSettingsLocal, 'ReplyTo', 'string'); $this->setSettingsFromParams($oSettingsLocal, 'Signature', 'string'); return $this->DefaultResponse(__FUNCTION__, @@ -5204,10 +5115,11 @@ class Actions */ private function buildMessage($oAccount, $bWithDraftInfo = true) { - $sFrom = $this->GetActionParam('From', ''); + $sIdentityID = $this->GetActionParam('IdentityID', ''); $sTo = $this->GetActionParam('To', ''); $sCc = $this->GetActionParam('Cc', ''); $sBcc = $this->GetActionParam('Bcc', ''); + $sReplyTo = $this->GetActionParam('ReplyTo', ''); $sSubject = $this->GetActionParam('Subject', ''); $bTextIsHtml = '1' === $this->GetActionParam('TextIsHtml', '0'); $bReadReceiptRequest = '1' === $this->GetActionParam('ReadReceiptRequest', '0'); @@ -5224,26 +5136,23 @@ class Actions $oMessage->SetXMailer('RainLoop/'.APP_VERSION); - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - - if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES, $oAccount)) + $oFromIdentity = $this->GetIdentityByID($oAccount, $sIdentityID); + if ($oFromIdentity) { - $oMessage->SetFrom(\MailSo\Mime\Email::Parse($sFrom)); + $oMessage->SetFrom(\MailSo\Mime\Email::NewInstance( + $oFromIdentity->Email(), $oFromIdentity->Name())); } else { - $sDisplayName = \trim($oSettingsLocal->GetConf('DisplayName', '')); - $sReplyTo = \trim($oSettingsLocal->GetConf('ReplyTo', '')); + $oMessage->SetFrom(\MailSo\Mime\Email::Parse($oAccount->Email())); + } - $oMessage->SetFrom(\MailSo\Mime\Email::NewInstance($oAccount->Email(), $sDisplayName)); - - if (!empty($sReplyTo)) + if (!empty($sReplyTo)) + { + $oReplyTo = \MailSo\Mime\EmailCollection::NewInstance($sReplyTo); + if ($oReplyTo && 0 < $oReplyTo->Count()) { - $oReplyTo = \MailSo\Mime\EmailCollection::NewInstance($sReplyTo); - if ($oReplyTo && $oReplyTo->Count()) - { - $oMessage->SetReplyTo($oReplyTo); - } + $oMessage->SetReplyTo($oReplyTo); } } @@ -5380,7 +5289,9 @@ class Actions $sSubject = $this->GetActionParam('Subject', ''); $sText = $this->GetActionParam('Text', ''); - if (empty($sReadReceipt) || empty($sSubject) || empty($sText)) + $oIdentity = $this->GetAccountIdentity($oAccount); + + if (empty($sReadReceipt) || empty($sSubject) || empty($sText) || !$oIdentity) { throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); } @@ -5390,13 +5301,9 @@ class Actions $oMessage->SetXMailer('RainLoop/'.APP_VERSION); - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - - $sDisplayName = \trim($oSettingsLocal->GetConf('DisplayName', '')); - $sReplyTo = \trim($oSettingsLocal->GetConf('ReplyTo', '')); - - $oMessage->SetFrom(\MailSo\Mime\Email::NewInstance($oAccount->Email(), $sDisplayName)); + $oMessage->SetFrom(\MailSo\Mime\Email::NewInstance($oIdentity->Email(), $oIdentity->Name())); + $sReplyTo = $oIdentity->ReplyTo(); if (!empty($sReplyTo)) { $oReplyTo = \MailSo\Mime\EmailCollection::NewInstance($sReplyTo); @@ -7374,11 +7281,6 @@ class Actions $aResult[] = \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS; } - if ($oConfig->Get('webmail', 'allow_identities', true)) - { - $aResult[] = \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES; - } - if ($oConfig->Get('security', 'allow_two_factor_auth', false) && ($bAdmin || ($oAccount && !$oAccount->IsAdditionalAccount()))) { @@ -8284,6 +8186,14 @@ class Actions $this->aCurrentActionParams[$sKey] : $mDefault; } + /** + * @return mixed + */ + public function GetActionParams() + { + return $this->aCurrentActionParams; + } + /** * @param string $sKey * diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php index b0d731c8f..5f8dad390 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php @@ -15,5 +15,4 @@ class Capa const FILTERS = 'FILTERS'; const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS'; const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS'; - const ADDITIONAL_IDENTITIES = 'ADDITIONAL_IDENTITIES'; } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php index f658660c1..0d10cd6a2 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php @@ -30,35 +30,36 @@ class Identity private $sBcc; /** - * @param string $sId - * @param string $sEmail - * @param string $sName - * @param string $sReplyTo - * @param string $sBcc + * @param string $sId = '' + * @param string $sEmail = '' * * @return void */ - protected function __construct($sId, $sEmail, $sName, $sReplyTo, $sBcc) + protected function __construct($sId = '', $sEmail = '') { $this->sId = $sId; - $this->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true); - $this->sName = \trim($sName); - $this->sReplyTo = \trim($sReplyTo); - $this->sBcc = \trim($sBcc); + $this->sEmail = $sEmail; + $this->sName = ''; + $this->sReplyTo = ''; + $this->sBcc = ''; } /** - * @param string $sId - * @param string $sEmail - * @param string $sName = '' - * @param string $sReplyTo = '' - * @param string $sBcc = '' + * @return \RainLoop\Model\Identity + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param \RainLoop\Model\Account $oAccount * * @return \RainLoop\Model\Identity */ - public static function NewInstance($sId, $sEmail, $sName = '', $sReplyTo = '', $sBcc = '') + public static function NewInstanceFromAccount(\RainLoop\Model\Account $oAccount) { - return new self($sId, $sEmail, $sName, $sReplyTo, $sBcc); + return new self('', $oAccount->Email()); } /** @@ -69,18 +70,6 @@ class Identity return $this->sId; } - /** - * @param string $sId - * - * @return \RainLoop\Model\Identity - */ - public function SetId($sId) - { - $this->sId = $sId; - - return $this; - } - /** * @return string */ @@ -96,7 +85,7 @@ class Identity */ public function SetEmail($sEmail) { - $this->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true); + $this->sEmail = $sEmail; return $this; } @@ -109,18 +98,6 @@ class Identity return $this->sName; } - /** - * @param string $sName - * - * @return \RainLoop\Model\Identity - */ - public function SetName($sName) - { - $this->sName = $sName; - - return $this; - } - /** * @return string */ @@ -129,18 +106,6 @@ class Identity return $this->sReplyTo; } - /** - * @param string $sReplyTo - * - * @return \RainLoop\Model\Identity - */ - public function SetReplyTo($sReplyTo) - { - $this->sReplyTo = $sReplyTo; - - return $this; - } - /** * @return string */ @@ -150,15 +115,25 @@ class Identity } /** - * @param string $sBcc + * @param array $aData + * @param bool $bAjax = false * - * @return \RainLoop\Model\Identity + * @return bool */ - public function SetBcc($sBcc) + public function FromJSON($aData, $bAjax = false) { - $this->sBcc = $sBcc; + if (isset($aData['Id'], $aData['Email']) && !empty($aData['Email'])) + { + $this->sId = $aData['Id']; + $this->sEmail = $bAjax ? \MailSo\Base\Utils::IdnToAscii($aData['Email'], true) : $aData['Email']; + $this->sName = isset($aData['Name']) ? $aData['Name'] : ''; + $this->sReplyTo = !empty($aData['ReplyTo']) ? $aData['ReplyTo'] : ''; + $this->sBcc = !empty($aData['Bcc']) ? $aData['Bcc'] : ''; - return $this; + return true; + } + + return false; } /** @@ -176,4 +151,12 @@ class Identity 'Bcc' => $this->Bcc() ); } + + /** + * @return bool + */ + public function Validate() + { + return !empty($this->sEmail); + } } diff --git a/rainloop/v/0.0.0/app/templates/Index.html b/rainloop/v/0.0.0/app/templates/Index.html index c3232f395..7eed16e6d 100644 --- a/rainloop/v/0.0.0/app/templates/Index.html +++ b/rainloop/v/0.0.0/app/templates/Index.html @@ -12,7 +12,6 @@