snappymail/dev/Model/Message.js

1302 lines
32 KiB
JavaScript
Raw Normal View History

2014-09-05 06:49:03 +08:00
(function () {
2014-08-25 23:49:01 +08:00
'use strict';
2014-08-07 17:34:20 +08:00
var
2014-08-25 23:49:01 +08:00
window = require('window'),
_ = require('_'),
$ = require('$'),
2014-08-25 23:49:01 +08:00
ko = require('ko'),
moment = require('moment'),
2014-09-05 06:49:03 +08:00
Enums = require('Common/Enums'),
Utils = require('Common/Utils'),
Globals = require('Common/Globals'),
2014-10-06 02:37:31 +08:00
Links = require('Common/Links'),
2014-08-20 23:03:12 +08:00
EmailModel = require('Model/Email'),
2014-10-04 19:58:01 +08:00
AttachmentModel = require('Model/Attachment'),
AbstractModel = require('Knoin/AbstractModel')
2014-08-07 17:34:20 +08:00
;
2014-08-20 23:03:12 +08:00
/**
* @constructor
*/
function MessageModel()
2014-08-07 17:34:20 +08:00
{
2014-10-04 19:58:01 +08:00
AbstractModel.call(this, 'MessageModel');
2014-08-20 23:03:12 +08:00
this.folderFullNameRaw = '';
this.uid = '';
this.hash = '';
this.requestHash = '';
this.subject = ko.observable('');
this.subjectPrefix = ko.observable('');
this.subjectSuffix = ko.observable('');
this.size = ko.observable(0);
this.dateTimeStampInUTC = ko.observable(0);
this.priority = ko.observable(Enums.MessagePriority.Normal);
this.proxy = false;
this.fromEmailString = ko.observable('');
this.fromClearEmailString = ko.observable('');
this.toEmailsString = ko.observable('');
this.toClearEmailsString = ko.observable('');
this.senderEmailsString = ko.observable('');
this.senderClearEmailsString = ko.observable('');
this.emails = [];
this.from = [];
this.to = [];
this.cc = [];
this.bcc = [];
this.replyTo = [];
this.deliveredTo = [];
this.newForAnimation = ko.observable(false);
this.deleted = ko.observable(false);
this.unseen = ko.observable(false);
this.flagged = ko.observable(false);
this.answered = ko.observable(false);
this.forwarded = ko.observable(false);
this.isReadReceipt = ko.observable(false);
this.focused = ko.observable(false);
this.selected = ko.observable(false);
this.checked = ko.observable(false);
this.hasAttachments = ko.observable(false);
this.attachmentsMainType = ko.observable('');
2014-10-04 19:58:01 +08:00
2014-08-20 23:03:12 +08:00
this.moment = ko.observable(moment(moment.unix(0)));
2014-10-04 19:58:01 +08:00
2014-08-20 23:03:12 +08:00
this.attachmentIconClass = ko.computed(function () {
var sClass = '';
if (this.hasAttachments())
2014-08-07 17:34:20 +08:00
{
2014-08-20 23:03:12 +08:00
sClass = 'icon-attachment';
switch (this.attachmentsMainType())
{
case 'image':
sClass = 'icon-image';
break;
case 'archive':
sClass = 'icon-file-zip';
break;
case 'doc':
sClass = 'icon-file-text';
break;
// case 'pdf':
// sClass = 'icon-file-pdf';
// break;
}
2014-08-07 17:34:20 +08:00
}
2014-08-20 23:03:12 +08:00
return sClass;
}, this);
this.fullFormatDateValue = ko.computed(function () {
return MessageModel.calculateFullFromatDateValue(this.dateTimeStampInUTC());
}, this);
this.momentDate = Utils.createMomentDate(this);
this.momentShortDate = Utils.createMomentShortDate(this);
2014-10-04 19:58:01 +08:00
this.regDisposables(this.dateTimeStampInUTC.subscribe(function (iValue) {
2014-08-20 23:03:12 +08:00
var iNow = moment().unix();
this.moment(moment.unix(iNow < iValue ? iNow : iValue));
2014-10-04 19:58:01 +08:00
}, this));
2014-08-20 23:03:12 +08:00
this.body = null;
this.plainRaw = '';
this.isHtml = ko.observable(false);
this.hasImages = ko.observable(false);
this.attachments = ko.observableArray([]);
this.isPgpSigned = ko.observable(false);
this.isPgpEncrypted = ko.observable(false);
this.pgpSignedVerifyStatus = ko.observable(Enums.SignedVerifyStatus.None);
this.pgpSignedVerifyUser = ko.observable('');
this.priority = ko.observable(Enums.MessagePriority.Normal);
this.readReceipt = ko.observable('');
this.aDraftInfo = [];
this.sMessageId = '';
this.sInReplyTo = '';
this.sReferences = '';
this.parentUid = ko.observable(0);
this.threads = ko.observableArray([]);
this.threadsLen = ko.observable(0);
this.hasUnseenSubMessage = ko.observable(false);
this.hasFlaggedSubMessage = ko.observable(false);
this.lastInCollapsedThread = ko.observable(false);
this.lastInCollapsedThreadLoading = ko.observable(false);
this.threadsLenResult = ko.computed(function () {
var iCount = this.threadsLen();
return 0 === this.parentUid() && 0 < iCount ? iCount + 1 : '';
}, this);
2014-10-04 19:58:01 +08:00
this.regDisposables([this.attachmentIconClass, this.fullFormatDateValue, this.threadsLenResult]);
2014-08-07 17:34:20 +08:00
}
2014-10-04 19:58:01 +08:00
_.extend(MessageModel.prototype, AbstractModel.prototype);
2014-08-20 23:03:12 +08:00
/**
* @static
* @param {AjaxJsonMessage} oJsonMessage
* @return {?MessageModel}
*/
MessageModel.newInstanceFromJson = function (oJsonMessage)
{
var oMessageModel = new MessageModel();
return oMessageModel.initByJson(oJsonMessage) ? oMessageModel : null;
};
2014-08-07 17:34:20 +08:00
2014-08-20 23:03:12 +08:00
/**
* @static
* @param {number} iTimeStampInUTC
* @return {string}
*/
MessageModel.calculateFullFromatDateValue = function (iTimeStampInUTC)
{
return 0 < iTimeStampInUTC ? moment.unix(iTimeStampInUTC).format('LLL') : '';
};
2014-08-20 23:03:12 +08:00
/**
* @static
* @param {Array} aEmail
* @param {boolean=} bFriendlyView
* @param {boolean=} bWrapWithLink = false
* @return {string}
*/
MessageModel.emailsToLine = function (aEmail, bFriendlyView, bWrapWithLink)
{
2014-08-20 23:03:12 +08:00
var
aResult = [],
iIndex = 0,
iLen = 0
;
if (Utils.isNonEmptyArray(aEmail))
{
2014-08-20 23:03:12 +08:00
for (iIndex = 0, iLen = aEmail.length; iIndex < iLen; iIndex++)
{
2014-08-20 23:03:12 +08:00
aResult.push(aEmail[iIndex].toLine(bFriendlyView, bWrapWithLink));
}
}
2014-08-20 23:03:12 +08:00
return aResult.join(', ');
};
/**
* @static
* @param {Array} aEmail
* @return {string}
*/
MessageModel.emailsToLineClear = function (aEmail)
{
var
2014-08-20 23:03:12 +08:00
aResult = [],
iIndex = 0,
2014-08-20 23:03:12 +08:00
iLen = 0
;
2014-08-20 23:03:12 +08:00
if (Utils.isNonEmptyArray(aEmail))
{
2014-08-20 23:03:12 +08:00
for (iIndex = 0, iLen = aEmail.length; iIndex < iLen; iIndex++)
{
2014-08-20 23:03:12 +08:00
if (aEmail[iIndex] && aEmail[iIndex].email && '' !== aEmail[iIndex].name)
{
aResult.push(aEmail[iIndex].email);
}
}
}
2014-08-20 23:03:12 +08:00
return aResult.join(', ');
};
2014-08-20 23:03:12 +08:00
/**
* @static
* @param {?Array} aJsonEmails
* @return {Array.<EmailModel>}
*/
MessageModel.initEmailsFromJson = function (aJsonEmails)
{
var
iIndex = 0,
iLen = 0,
oEmailModel = null,
aResult = []
;
2014-08-20 23:03:12 +08:00
if (Utils.isNonEmptyArray(aJsonEmails))
2014-07-17 22:35:48 +08:00
{
2014-08-20 23:03:12 +08:00
for (iIndex = 0, iLen = aJsonEmails.length; iIndex < iLen; iIndex++)
{
oEmailModel = EmailModel.newInstanceFromJson(aJsonEmails[iIndex]);
if (oEmailModel)
{
aResult.push(oEmailModel);
}
}
2014-07-17 22:35:48 +08:00
}
2014-08-20 23:03:12 +08:00
return aResult;
};
2014-08-20 23:03:12 +08:00
/**
* @static
* @param {Array.<EmailModel>} aMessageEmails
* @param {Object} oLocalUnic
* @param {Array} aLocalEmails
*/
MessageModel.replyHelper = function (aMessageEmails, oLocalUnic, aLocalEmails)
{
if (aMessageEmails && 0 < aMessageEmails.length)
{
var
iIndex = 0,
iLen = aMessageEmails.length
;
for (; iIndex < iLen; iIndex++)
{
if (Utils.isUnd(oLocalUnic[aMessageEmails[iIndex].email]))
{
oLocalUnic[aMessageEmails[iIndex].email] = true;
aLocalEmails.push(aMessageEmails[iIndex]);
}
}
}
};
2014-08-20 23:03:12 +08:00
MessageModel.prototype.clear = function ()
{
this.folderFullNameRaw = '';
this.uid = '';
this.hash = '';
this.requestHash = '';
this.subject('');
this.subjectPrefix('');
this.subjectSuffix('');
this.size(0);
this.dateTimeStampInUTC(0);
this.priority(Enums.MessagePriority.Normal);
this.proxy = false;
this.fromEmailString('');
this.fromClearEmailString('');
this.toEmailsString('');
this.toClearEmailsString('');
this.senderEmailsString('');
this.senderClearEmailsString('');
this.emails = [];
this.from = [];
this.to = [];
this.cc = [];
this.bcc = [];
this.replyTo = [];
this.deliveredTo = [];
this.newForAnimation(false);
this.deleted(false);
this.unseen(false);
this.flagged(false);
this.answered(false);
this.forwarded(false);
this.isReadReceipt(false);
this.selected(false);
this.checked(false);
this.hasAttachments(false);
this.attachmentsMainType('');
this.body = null;
this.isHtml(false);
this.hasImages(false);
this.attachments([]);
this.isPgpSigned(false);
this.isPgpEncrypted(false);
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None);
this.pgpSignedVerifyUser('');
this.priority(Enums.MessagePriority.Normal);
this.readReceipt('');
this.aDraftInfo = [];
this.sMessageId = '';
this.sInReplyTo = '';
this.sReferences = '';
this.parentUid(0);
this.threads([]);
this.threadsLen(0);
this.hasUnseenSubMessage(false);
this.hasFlaggedSubMessage(false);
this.lastInCollapsedThread(false);
this.lastInCollapsedThreadLoading(false);
};
/**
* @return {string}
*/
MessageModel.prototype.friendlySize = function ()
{
return Utils.friendlySize(this.size());
};
2014-08-20 23:03:12 +08:00
MessageModel.prototype.computeSenderEmail = function ()
{
2014-08-22 23:08:56 +08:00
var
2014-10-18 21:43:44 +08:00
Data = require('Storage/User/Data'),
2014-08-22 23:08:56 +08:00
sSent = Data.sentFolder(),
sDraft = Data.draftFolder()
;
2014-08-22 23:08:56 +08:00
this.senderEmailsString(this.folderFullNameRaw === sSent || this.folderFullNameRaw === sDraft ?
this.toEmailsString() : this.fromEmailString());
2014-08-22 23:08:56 +08:00
this.senderClearEmailsString(this.folderFullNameRaw === sSent || this.folderFullNameRaw === sDraft ?
this.toClearEmailsString() : this.fromClearEmailString());
2014-08-20 23:03:12 +08:00
};
2014-08-20 23:03:12 +08:00
/**
* @param {AjaxJsonMessage} oJsonMessage
* @return {boolean}
*/
MessageModel.prototype.initByJson = function (oJsonMessage)
{
var bResult = false;
if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object'])
{
this.folderFullNameRaw = oJsonMessage.Folder;
this.uid = oJsonMessage.Uid;
this.hash = oJsonMessage.Hash;
this.requestHash = oJsonMessage.RequestHash;
this.proxy = !!oJsonMessage.ExternalProxy;
this.size(Utils.pInt(oJsonMessage.Size));
this.from = MessageModel.initEmailsFromJson(oJsonMessage.From);
this.to = MessageModel.initEmailsFromJson(oJsonMessage.To);
this.cc = MessageModel.initEmailsFromJson(oJsonMessage.Cc);
this.bcc = MessageModel.initEmailsFromJson(oJsonMessage.Bcc);
this.replyTo = MessageModel.initEmailsFromJson(oJsonMessage.ReplyTo);
this.deliveredTo = MessageModel.initEmailsFromJson(oJsonMessage.DeliveredTo);
this.subject(oJsonMessage.Subject);
if (Utils.isArray(oJsonMessage.SubjectParts))
{
this.subjectPrefix(oJsonMessage.SubjectParts[0]);
this.subjectSuffix(oJsonMessage.SubjectParts[1]);
}
else
{
this.subjectPrefix('');
this.subjectSuffix(this.subject());
}
this.dateTimeStampInUTC(Utils.pInt(oJsonMessage.DateTimeStampInUTC));
this.hasAttachments(!!oJsonMessage.HasAttachments);
this.attachmentsMainType(oJsonMessage.AttachmentsMainType);
this.fromEmailString(MessageModel.emailsToLine(this.from, true));
this.fromClearEmailString(MessageModel.emailsToLineClear(this.from));
this.toEmailsString(MessageModel.emailsToLine(this.to, true));
this.toClearEmailsString(MessageModel.emailsToLineClear(this.to));
this.parentUid(Utils.pInt(oJsonMessage.ParentThread));
this.threads(Utils.isArray(oJsonMessage.Threads) ? oJsonMessage.Threads : []);
this.threadsLen(Utils.pInt(oJsonMessage.ThreadsLen));
this.initFlagsByJson(oJsonMessage);
this.computeSenderEmail();
bResult = true;
}
return bResult;
};
2014-08-20 23:03:12 +08:00
/**
* @param {AjaxJsonMessage} oJsonMessage
* @return {boolean}
*/
MessageModel.prototype.initUpdateByMessageJson = function (oJsonMessage)
{
2014-08-20 23:03:12 +08:00
var
bResult = false,
2014-10-18 21:43:44 +08:00
Data = require('Storage/User/Data'),
2014-08-20 23:03:12 +08:00
iPriority = Enums.MessagePriority.Normal
;
2014-08-20 23:03:12 +08:00
if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object'])
{
iPriority = Utils.pInt(oJsonMessage.Priority);
this.priority(-1 < Utils.inArray(iPriority, [Enums.MessagePriority.High, Enums.MessagePriority.Low]) ?
iPriority : Enums.MessagePriority.Normal);
2014-08-20 23:03:12 +08:00
this.aDraftInfo = oJsonMessage.DraftInfo;
2014-08-20 23:03:12 +08:00
this.sMessageId = oJsonMessage.MessageId;
this.sInReplyTo = oJsonMessage.InReplyTo;
this.sReferences = oJsonMessage.References;
2014-08-20 23:03:12 +08:00
this.proxy = !!oJsonMessage.ExternalProxy;
2014-01-29 00:09:41 +08:00
2014-08-22 23:08:56 +08:00
if (Data.capaOpenPGP())
2014-08-20 23:03:12 +08:00
{
this.isPgpSigned(!!oJsonMessage.PgpSigned);
this.isPgpEncrypted(!!oJsonMessage.PgpEncrypted);
}
2014-08-20 23:03:12 +08:00
this.hasAttachments(!!oJsonMessage.HasAttachments);
this.attachmentsMainType(oJsonMessage.AttachmentsMainType);
2014-08-20 23:03:12 +08:00
this.foundedCIDs = Utils.isArray(oJsonMessage.FoundedCIDs) ? oJsonMessage.FoundedCIDs : [];
this.attachments(this.initAttachmentsFromJson(oJsonMessage.Attachments));
2014-01-04 08:20:07 +08:00
2014-08-20 23:03:12 +08:00
this.readReceipt(oJsonMessage.ReadReceipt || '');
2014-08-20 23:03:12 +08:00
this.computeSenderEmail();
2014-08-20 23:03:12 +08:00
bResult = true;
}
2014-08-20 23:03:12 +08:00
return bResult;
};
2014-08-20 23:03:12 +08:00
/**
* @param {(AjaxJsonAttachment|null)} oJsonAttachments
* @return {Array}
*/
MessageModel.prototype.initAttachmentsFromJson = function (oJsonAttachments)
{
2014-08-20 23:03:12 +08:00
var
iIndex = 0,
iLen = 0,
oAttachmentModel = null,
aResult = []
;
if (oJsonAttachments && 'Collection/AttachmentCollection' === oJsonAttachments['@Object'] &&
Utils.isNonEmptyArray(oJsonAttachments['@Collection']))
{
for (iIndex = 0, iLen = oJsonAttachments['@Collection'].length; iIndex < iLen; iIndex++)
{
oAttachmentModel = AttachmentModel.newInstanceFromJson(oJsonAttachments['@Collection'][iIndex]);
if (oAttachmentModel)
{
if ('' !== oAttachmentModel.cidWithOutTags && 0 < this.foundedCIDs.length &&
0 <= Utils.inArray(oAttachmentModel.cidWithOutTags, this.foundedCIDs))
{
oAttachmentModel.isLinked = true;
}
aResult.push(oAttachmentModel);
}
}
}
return aResult;
};
2014-08-20 23:03:12 +08:00
/**
* @param {AjaxJsonMessage} oJsonMessage
* @return {boolean}
*/
MessageModel.prototype.initFlagsByJson = function (oJsonMessage)
{
2014-08-20 23:03:12 +08:00
var bResult = false;
2014-08-20 23:03:12 +08:00
if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object'])
{
this.unseen(!oJsonMessage.IsSeen);
this.flagged(!!oJsonMessage.IsFlagged);
this.answered(!!oJsonMessage.IsAnswered);
this.forwarded(!!oJsonMessage.IsForwarded);
this.isReadReceipt(!!oJsonMessage.IsReadReceipt);
2014-08-20 23:03:12 +08:00
bResult = true;
}
2014-08-20 23:03:12 +08:00
return bResult;
};
2014-08-20 23:03:12 +08:00
/**
* @param {boolean} bFriendlyView
* @param {boolean=} bWrapWithLink = false
* @return {string}
*/
MessageModel.prototype.fromToLine = function (bFriendlyView, bWrapWithLink)
{
2014-08-20 23:03:12 +08:00
return MessageModel.emailsToLine(this.from, bFriendlyView, bWrapWithLink);
};
2014-08-20 23:03:12 +08:00
/**
* @param {boolean} bFriendlyView
* @param {boolean=} bWrapWithLink = false
* @return {string}
*/
MessageModel.prototype.toToLine = function (bFriendlyView, bWrapWithLink)
{
2014-08-20 23:03:12 +08:00
return MessageModel.emailsToLine(this.to, bFriendlyView, bWrapWithLink);
};
2014-08-20 23:03:12 +08:00
/**
* @param {boolean} bFriendlyView
* @param {boolean=} bWrapWithLink = false
* @return {string}
*/
MessageModel.prototype.ccToLine = function (bFriendlyView, bWrapWithLink)
{
2014-08-20 23:03:12 +08:00
return MessageModel.emailsToLine(this.cc, bFriendlyView, bWrapWithLink);
};
2014-08-20 23:03:12 +08:00
/**
* @param {boolean} bFriendlyView
* @param {boolean=} bWrapWithLink = false
* @return {string}
*/
MessageModel.prototype.bccToLine = function (bFriendlyView, bWrapWithLink)
{
2014-08-20 23:03:12 +08:00
return MessageModel.emailsToLine(this.bcc, bFriendlyView, bWrapWithLink);
};
2014-08-20 23:03:12 +08:00
/**
* @return string
*/
MessageModel.prototype.lineAsCcc = function ()
{
2014-08-20 23:03:12 +08:00
var aResult = [];
if (this.deleted())
{
aResult.push('deleted');
}
if (this.selected())
{
aResult.push('selected');
}
if (this.checked())
{
aResult.push('checked');
}
if (this.flagged())
{
aResult.push('flagged');
}
if (this.unseen())
{
aResult.push('unseen');
}
if (this.answered())
{
aResult.push('answered');
}
if (this.forwarded())
{
aResult.push('forwarded');
}
if (this.focused())
{
aResult.push('focused');
}
if (this.hasAttachments())
{
aResult.push('withAttachments');
switch (this.attachmentsMainType())
{
case 'image':
aResult.push('imageOnlyAttachments');
break;
case 'archive':
aResult.push('archiveOnlyAttachments');
break;
}
}
if (this.newForAnimation())
{
aResult.push('new');
}
if ('' === this.subject())
{
aResult.push('emptySubject');
}
if (0 < this.parentUid())
{
aResult.push('hasParentMessage');
}
if (0 < this.threadsLen() && 0 === this.parentUid())
{
aResult.push('hasChildrenMessage');
}
if (this.hasUnseenSubMessage())
{
aResult.push('hasUnseenSubMessage');
}
if (this.hasFlaggedSubMessage())
{
aResult.push('hasFlaggedSubMessage');
}
return aResult.join(' ');
};
2014-08-20 23:03:12 +08:00
/**
* @return {boolean}
*/
MessageModel.prototype.hasVisibleAttachments = function ()
{
2014-08-20 23:03:12 +08:00
return !!_.find(this.attachments(), function (oAttachment) {
return !oAttachment.isLinked;
});
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
/**
* @param {string} sCid
* @return {*}
*/
MessageModel.prototype.findAttachmentByCid = function (sCid)
{
var
oResult = null,
aAttachments = this.attachments()
;
if (Utils.isNonEmptyArray(aAttachments))
{
sCid = sCid.replace(/^<+/, '').replace(/>+$/, '');
oResult = _.find(aAttachments, function (oAttachment) {
return sCid === oAttachment.cidWithOutTags;
});
}
return oResult || null;
};
2014-08-20 23:03:12 +08:00
/**
* @param {string} sContentLocation
* @return {*}
*/
MessageModel.prototype.findAttachmentByContentLocation = function (sContentLocation)
{
var
oResult = null,
aAttachments = this.attachments()
;
if (Utils.isNonEmptyArray(aAttachments))
{
oResult = _.find(aAttachments, function (oAttachment) {
return sContentLocation === oAttachment.contentLocation;
});
}
return oResult || null;
};
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.messageId = function ()
{
return this.sMessageId;
};
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.inReplyTo = function ()
{
return this.sInReplyTo;
};
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.references = function ()
{
return this.sReferences;
};
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.fromAsSingleEmail = function ()
{
return Utils.isArray(this.from) && this.from[0] ? this.from[0].email : '';
};
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.viewLink = function ()
{
2014-10-06 02:37:31 +08:00
return Links.messageViewLink(this.requestHash);
2014-08-20 23:03:12 +08:00
};
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.downloadLink = function ()
{
2014-10-06 02:37:31 +08:00
return Links.messageDownloadLink(this.requestHash);
2014-08-20 23:03:12 +08:00
};
2014-08-20 23:03:12 +08:00
/**
* @param {Object} oExcludeEmails
* @return {Array}
*/
MessageModel.prototype.replyEmails = function (oExcludeEmails)
{
var
aResult = [],
oUnic = Utils.isUnd(oExcludeEmails) ? {} : oExcludeEmails
;
MessageModel.replyHelper(this.replyTo, oUnic, aResult);
if (0 === aResult.length)
{
MessageModel.replyHelper(this.from, oUnic, aResult);
}
return aResult;
};
2014-08-20 23:03:12 +08:00
/**
* @param {Object} oExcludeEmails
* @return {Array.<Array>}
*/
MessageModel.prototype.replyAllEmails = function (oExcludeEmails)
{
var
aToResult = [],
aCcResult = [],
oUnic = Utils.isUnd(oExcludeEmails) ? {} : oExcludeEmails
;
MessageModel.replyHelper(this.replyTo, oUnic, aToResult);
if (0 === aToResult.length)
{
MessageModel.replyHelper(this.from, oUnic, aToResult);
}
MessageModel.replyHelper(this.to, oUnic, aToResult);
MessageModel.replyHelper(this.cc, oUnic, aCcResult);
return [aToResult, aCcResult];
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.textBodyToString = function ()
2014-04-02 02:03:37 +08:00
{
2014-08-20 23:03:12 +08:00
return this.body ? this.body.html() : '';
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.attachmentsToStringLine = function ()
{
var aAttachLines = _.map(this.attachments(), function (oItem) {
return oItem.fileName + ' (' + oItem.friendlySize + ')';
});
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
return aAttachLines && 0 < aAttachLines.length ? aAttachLines.join(', ') : '';
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
/**
* @return {Object}
*/
MessageModel.prototype.getDataForWindowPopup = function ()
2014-04-02 02:03:37 +08:00
{
2014-08-20 23:03:12 +08:00
return {
'popupFrom': this.fromToLine(false),
'popupTo': this.toToLine(false),
'popupCc': this.ccToLine(false),
'popupBcc': this.bccToLine(false),
'popupSubject': this.subject(),
2014-09-05 00:00:11 +08:00
'popupIsHtml': this.isHtml(),
2014-08-20 23:03:12 +08:00
'popupDate': this.fullFormatDateValue(),
'popupAttachments': this.attachmentsToStringLine(),
'popupBody': this.textBodyToString()
};
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
/**
* @param {boolean=} bPrint = false
*/
MessageModel.prototype.viewPopupMessage = function (bPrint)
2014-04-02 02:03:37 +08:00
{
2014-08-20 23:03:12 +08:00
Utils.windowPopupKnockout(this.getDataForWindowPopup(), 'PopupsWindowSimpleMessage', this.subject(), function (oPopupWin) {
if (oPopupWin && oPopupWin.document && oPopupWin.document.body)
{
$('img.lazy', oPopupWin.document.body).each(function (iIndex, oImg) {
var
$oImg = $(oImg),
sOrig = $oImg.data('original'),
sSrc = $oImg.attr('src')
;
if (0 <= iIndex && sOrig && !sSrc)
{
$oImg.attr('src', sOrig);
}
});
if (bPrint)
{
window.setTimeout(function () {
oPopupWin.print();
}, 100);
}
}
});
};
2014-08-20 23:03:12 +08:00
MessageModel.prototype.printMessage = function ()
{
this.viewPopupMessage(true);
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
/**
* @returns {string}
*/
MessageModel.prototype.generateUid = function ()
{
return this.folderFullNameRaw + '/' + this.uid;
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
/**
* @param {MessageModel} oMessage
* @return {MessageModel}
*/
MessageModel.prototype.populateByMessageListItem = function (oMessage)
2014-04-02 02:03:37 +08:00
{
2014-08-20 23:03:12 +08:00
this.folderFullNameRaw = oMessage.folderFullNameRaw;
this.uid = oMessage.uid;
this.hash = oMessage.hash;
this.requestHash = oMessage.requestHash;
this.subject(oMessage.subject());
this.subjectPrefix(this.subjectPrefix());
this.subjectSuffix(this.subjectSuffix());
this.size(oMessage.size());
this.dateTimeStampInUTC(oMessage.dateTimeStampInUTC());
this.priority(oMessage.priority());
this.proxy = oMessage.proxy;
this.fromEmailString(oMessage.fromEmailString());
this.fromClearEmailString(oMessage.fromClearEmailString());
this.toEmailsString(oMessage.toEmailsString());
this.toClearEmailsString(oMessage.toClearEmailsString());
this.emails = oMessage.emails;
this.from = oMessage.from;
this.to = oMessage.to;
this.cc = oMessage.cc;
this.bcc = oMessage.bcc;
this.replyTo = oMessage.replyTo;
this.deliveredTo = oMessage.deliveredTo;
this.unseen(oMessage.unseen());
this.flagged(oMessage.flagged());
this.answered(oMessage.answered());
this.forwarded(oMessage.forwarded());
this.isReadReceipt(oMessage.isReadReceipt());
this.selected(oMessage.selected());
this.checked(oMessage.checked());
this.hasAttachments(oMessage.hasAttachments());
this.attachmentsMainType(oMessage.attachmentsMainType());
this.moment(oMessage.moment());
this.body = null;
this.priority(Enums.MessagePriority.Normal);
this.aDraftInfo = [];
this.sMessageId = '';
this.sInReplyTo = '';
this.sReferences = '';
this.parentUid(oMessage.parentUid());
this.threads(oMessage.threads());
this.threadsLen(oMessage.threadsLen());
this.computeSenderEmail();
return this;
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
MessageModel.prototype.showExternalImages = function (bLazy)
{
if (this.body && this.body.data('rl-has-images'))
{
var sAttr = '';
bLazy = Utils.isUnd(bLazy) ? false : bLazy;
this.hasImages(false);
this.body.data('rl-has-images', false);
sAttr = this.proxy ? 'data-x-additional-src' : 'data-x-src';
$('[' + sAttr + ']', this.body).each(function () {
if (bLazy && $(this).is('img'))
{
$(this)
.addClass('lazy')
.attr('data-original', $(this).attr(sAttr))
.removeAttr(sAttr)
;
}
else
{
$(this).attr('src', $(this).attr(sAttr)).removeAttr(sAttr);
}
});
sAttr = this.proxy ? 'data-x-additional-style-url' : 'data-x-style-url';
$('[' + sAttr + ']', this.body).each(function () {
var sStyle = Utils.trim($(this).attr('style'));
sStyle = '' === sStyle ? '' : (';' === sStyle.substr(-1) ? sStyle + ' ' : sStyle + '; ');
$(this).attr('style', sStyle + $(this).attr(sAttr)).removeAttr(sAttr);
});
if (bLazy)
{
$('img.lazy', this.body).addClass('lazy-inited').lazyload({
'threshold' : 400,
'effect' : 'fadeIn',
'skip_invisible' : false,
'container': $('.RL-MailMessageView .messageView .messageItem .content')[0]
});
2014-09-02 00:05:32 +08:00
Globals.$win.resize();
2014-08-20 23:03:12 +08:00
}
Utils.windowResize(500);
}
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
MessageModel.prototype.showInternalImages = function (bLazy)
{
if (this.body && !this.body.data('rl-init-internal-images'))
{
this.body.data('rl-init-internal-images', true);
bLazy = Utils.isUnd(bLazy) ? false : bLazy;
var self = this;
$('[data-x-src-cid]', this.body).each(function () {
var oAttachment = self.findAttachmentByCid($(this).attr('data-x-src-cid'));
if (oAttachment && oAttachment.download)
{
if (bLazy && $(this).is('img'))
{
$(this)
.addClass('lazy')
.attr('data-original', oAttachment.linkPreview());
}
else
{
$(this).attr('src', oAttachment.linkPreview());
}
}
});
$('[data-x-src-location]', this.body).each(function () {
var oAttachment = self.findAttachmentByContentLocation($(this).attr('data-x-src-location'));
if (!oAttachment)
{
oAttachment = self.findAttachmentByCid($(this).attr('data-x-src-location'));
}
if (oAttachment && oAttachment.download)
{
if (bLazy && $(this).is('img'))
{
$(this)
.addClass('lazy')
.attr('data-original', oAttachment.linkPreview());
}
else
{
$(this).attr('src', oAttachment.linkPreview());
}
}
});
$('[data-x-style-cid]', this.body).each(function () {
var
sStyle = '',
sName = '',
oAttachment = self.findAttachmentByCid($(this).attr('data-x-style-cid'))
;
if (oAttachment && oAttachment.linkPreview)
{
sName = $(this).attr('data-x-style-cid-name');
if ('' !== sName)
{
sStyle = Utils.trim($(this).attr('style'));
sStyle = '' === sStyle ? '' : (';' === sStyle.substr(-1) ? sStyle + ' ' : sStyle + '; ');
$(this).attr('style', sStyle + sName + ': url(\'' + oAttachment.linkPreview() + '\')');
}
}
});
if (bLazy)
{
(function ($oImg, oContainer) {
_.delay(function () {
$oImg.addClass('lazy-inited').lazyload({
'threshold' : 400,
'effect' : 'fadeIn',
'skip_invisible' : false,
'container': oContainer
});
}, 300);
}($('img.lazy', self.body), $('.RL-MailMessageView .messageView .messageItem .content')[0]));
}
Utils.windowResize(500);
}
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
MessageModel.prototype.storeDataToDom = function ()
{
if (this.body)
{
this.body.data('rl-is-html', !!this.isHtml());
this.body.data('rl-has-images', !!this.hasImages());
this.body.data('rl-plain-raw', this.plainRaw);
2014-10-18 21:43:44 +08:00
var Data = require('Storage/User/Data');
2014-08-22 23:08:56 +08:00
if (Data.capaOpenPGP())
2014-08-20 23:03:12 +08:00
{
this.body.data('rl-plain-pgp-signed', !!this.isPgpSigned());
this.body.data('rl-plain-pgp-encrypted', !!this.isPgpEncrypted());
this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus());
this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser());
}
}
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
MessageModel.prototype.storePgpVerifyDataToDom = function ()
{
2014-10-18 21:43:44 +08:00
var Data = require('Storage/User/Data');
2014-08-25 15:10:51 +08:00
if (this.body && Data.capaOpenPGP())
{
this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus());
this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser());
}
2014-08-20 23:03:12 +08:00
};
2014-04-02 02:03:37 +08:00
2014-08-20 23:03:12 +08:00
MessageModel.prototype.fetchDataToDom = function ()
{
2014-08-25 15:10:51 +08:00
if (this.body)
{
this.isHtml(!!this.body.data('rl-is-html'));
this.hasImages(!!this.body.data('rl-has-images'));
2014-08-20 23:03:12 +08:00
2014-08-25 15:10:51 +08:00
this.plainRaw = Utils.pString(this.body.data('rl-plain-raw'));
2014-08-20 23:03:12 +08:00
2014-10-18 21:43:44 +08:00
var Data = require('Storage/User/Data');
2014-08-25 15:10:51 +08:00
if (Data.capaOpenPGP())
{
this.isPgpSigned(!!this.body.data('rl-plain-pgp-signed'));
this.isPgpEncrypted(!!this.body.data('rl-plain-pgp-encrypted'));
this.pgpSignedVerifyStatus(this.body.data('rl-pgp-verify-status'));
this.pgpSignedVerifyUser(this.body.data('rl-pgp-verify-user'));
}
else
{
this.isPgpSigned(false);
this.isPgpEncrypted(false);
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None);
this.pgpSignedVerifyUser('');
}
}
2014-08-20 23:03:12 +08:00
};
2014-08-20 23:03:12 +08:00
MessageModel.prototype.verifyPgpSignedClearMessage = function ()
{
if (this.isPgpSigned())
{
var
aRes = [],
mPgpMessage = null,
2014-10-18 21:43:44 +08:00
Data = require('Storage/User/Data'),
2014-08-20 23:03:12 +08:00
sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '',
2014-08-22 23:08:56 +08:00
aPublicKeys = Data.findPublicKeysByEmail(sFrom),
2014-08-20 23:03:12 +08:00
oValidKey = null,
oValidSysKey = null,
sPlain = ''
;
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error);
this.pgpSignedVerifyUser('');
try
{
mPgpMessage = Data.openpgp.cleartext.readArmored(this.plainRaw);
2014-08-20 23:03:12 +08:00
if (mPgpMessage && mPgpMessage.getText)
{
this.pgpSignedVerifyStatus(
aPublicKeys.length ? Enums.SignedVerifyStatus.Unverified : Enums.SignedVerifyStatus.UnknownPublicKeys);
aRes = mPgpMessage.verify(aPublicKeys);
if (aRes && 0 < aRes.length)
{
oValidKey = _.find(aRes, function (oItem) {
return oItem && oItem.keyid && oItem.valid;
});
if (oValidKey)
{
2014-08-22 23:08:56 +08:00
oValidSysKey = Data.findPublicKeyByHex(oValidKey.keyid.toHex());
2014-08-20 23:03:12 +08:00
if (oValidSysKey)
{
sPlain = mPgpMessage.getText();
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success);
this.pgpSignedVerifyUser(oValidSysKey.user);
sPlain =
2014-09-02 00:05:32 +08:00
Globals.$div.empty().append(
2014-08-20 23:03:12 +08:00
$('<pre class="b-plain-openpgp signed verified"></pre>').text(sPlain)
).html()
;
2014-09-02 00:05:32 +08:00
Globals.$div.empty();
2014-08-20 23:03:12 +08:00
this.replacePlaneTextBody(sPlain);
}
}
}
}
}
catch (oExc) {}
this.storePgpVerifyDataToDom();
}
};
2014-08-20 23:03:12 +08:00
MessageModel.prototype.decryptPgpEncryptedMessage = function (sPassword)
{
if (this.isPgpEncrypted())
{
var
aRes = [],
mPgpMessage = null,
mPgpMessageDecrypted = null,
2014-10-18 21:43:44 +08:00
Data = require('Storage/User/Data'),
2014-08-20 23:03:12 +08:00
sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '',
2014-08-22 23:08:56 +08:00
aPublicKey = Data.findPublicKeysByEmail(sFrom),
oPrivateKey = Data.findSelfPrivateKey(sPassword),
2014-08-20 23:03:12 +08:00
oValidKey = null,
oValidSysKey = null,
sPlain = ''
;
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error);
this.pgpSignedVerifyUser('');
if (!oPrivateKey)
{
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.UnknownPrivateKey);
}
try
{
mPgpMessage = Data.openpgp.message.readArmored(this.plainRaw);
2014-08-20 23:03:12 +08:00
if (mPgpMessage && oPrivateKey && mPgpMessage.decrypt)
{
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Unverified);
mPgpMessageDecrypted = mPgpMessage.decrypt(oPrivateKey);
if (mPgpMessageDecrypted)
{
aRes = mPgpMessageDecrypted.verify(aPublicKey);
if (aRes && 0 < aRes.length)
{
oValidKey = _.find(aRes, function (oItem) {
return oItem && oItem.keyid && oItem.valid;
});
if (oValidKey)
{
2014-08-22 23:08:56 +08:00
oValidSysKey = Data.findPublicKeyByHex(oValidKey.keyid.toHex());
2014-08-20 23:03:12 +08:00
if (oValidSysKey)
{
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success);
this.pgpSignedVerifyUser(oValidSysKey.user);
}
}
}
sPlain = mPgpMessageDecrypted.getText();
sPlain =
2014-09-02 00:05:32 +08:00
Globals.$div.empty().append(
2014-08-20 23:03:12 +08:00
$('<pre class="b-plain-openpgp signed verified"></pre>').text(sPlain)
).html()
;
2014-09-02 00:05:32 +08:00
Globals.$div.empty();
2014-08-20 23:03:12 +08:00
this.replacePlaneTextBody(sPlain);
}
}
}
catch (oExc) {}
this.storePgpVerifyDataToDom();
}
};
2014-08-20 23:03:12 +08:00
MessageModel.prototype.replacePlaneTextBody = function (sPlain)
{
if (this.body)
{
this.body.html(sPlain).addClass('b-text-part plain');
}
};
2014-08-20 23:03:12 +08:00
/**
* @return {string}
*/
MessageModel.prototype.flagHash = function ()
{
return [this.deleted(), this.unseen(), this.flagged(), this.answered(), this.forwarded(),
this.isReadReceipt()].join('');
};
2014-08-20 23:03:12 +08:00
module.exports = MessageModel;
2014-09-05 06:49:03 +08:00
}());