]+><\/a>/g, '');
let encrypted;
switch (lineComposeType) {
case ComposeType.Reply:
case ComposeType.ReplyAll:
sFrom = message.fromToLine(false, true);
sText = '
' + i18n('COMPOSE/REPLY_MESSAGE_TITLE', { DATETIME: sDate, EMAIL: sFrom })
+ ':
'
+ sText.trim()
+ '
';
break;
case ComposeType.Forward:
sFrom = message.fromToLine(false, true);
sTo = message.toToLine(false, true);
sCc = message.ccToLine(false, true);
sText = '
' + i18n('COMPOSE/FORWARD_MESSAGE_TOP_TITLE') + '
'
+ i18n('GLOBAL/FROM') + ': ' + sFrom
+ '
'
+ i18n('GLOBAL/TO') + ': ' + sTo
+ (sCc.length ? '
' + i18n('GLOBAL/CC') + ': ' + sCc : '')
+ '
'
+ i18n('COMPOSE/FORWARD_MESSAGE_TOP_SENT')
+ ': '
+ encodeHtml(sDate)
+ '
'
+ i18n('GLOBAL/SUBJECT')
+ ': '
+ encodeHtml(sSubject)
+ '
'
+ sText.trim()
+ '
';
break;
case ComposeType.ForwardAsAttachment:
sText = '';
break;
default:
encrypted = PgpUserStore.isEncrypted(sText);
if (encrypted) {
sText = message.plain();
}
}
this.editor(editor => {
encrypted || editor.setHtml(sText);
if (encrypted
|| EditorDefaultType.Plain === SettingsUserStore.editorDefaultType()
|| !message.isHtml()
) {
editor.modePlain();
}
!encrypted || editor.setPlain(sText);
if (identity && ComposeType.Draft !== lineComposeType && ComposeType.EditAsNew !== lineComposeType) {
this.setSignatureFromIdentity(identity);
}
this.setFocusInPopup();
});
} else if (ComposeType.Empty === lineComposeType) {
this.subject(null != sCustomSubject ? '' + sCustomSubject : '');
sText = null != sCustomPlainText ? '' + sCustomPlainText : '';
this.editor(editor => {
editor.setHtml(sText);
if (isPlainEditor()) {
editor.modePlain();
}
if (identity) {
this.setSignatureFromIdentity(identity);
}
this.setFocusInPopup();
});
} else if (arrayLength(oMessageOrArray)) {
oMessageOrArray.forEach(item => this.addMessageAsAttachment(item));
this.editor(editor => {
if (isPlainEditor()) {
editor.setPlain('')
} else {
editor.setHtml('');
}
if (identity && ComposeType.Draft !== lineComposeType && ComposeType.EditAsNew !== lineComposeType) {
this.setSignatureFromIdentity(identity);
}
this.setFocusInPopup();
});
} else {
this.setFocusInPopup();
}
const downloads = this.getAttachmentsDownloadsForUpload();
if (arrayLength(downloads)) {
Remote.request('MessageUploadAttachments',
(iError, oData) => {
if (!iError) {
forEachObjectEntry(oData.Result, (tempName, id) => {
const attachment = this.getAttachmentById(id);
if (attachment) {
attachment.tempName(tempName);
attachment
.waiting(false)
.uploading(false)
.complete(true);
}
});
} else {
this.attachments.forEach(attachment => {
if (attachment && attachment.fromMessage) {
attachment
.waiting(false)
.uploading(false)
.complete(true)
.error(getUploadErrorDescByCode(UploadErrorCode.NoFileUploaded));
}
});
}
},
{
Attachments: downloads
},
999000
);
}
if (identity) {
this.currentIdentity(identity);
}
}
setFocusInPopup() {
setTimeout(() => {
if (!this.to()) {
this.to.focused(true);
} else if (!this.to.focused()) {
this.oEditor && this.oEditor.focus();
}
}, 100);
}
tryToClosePopup() {
if (AskPopupView.hidden()) {
if (this.bSkipNextHide || (this.isEmptyForm() && !this.draftUid())) {
this.close();
} else {
showScreenPopup(AskPopupView, [
i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'),
() => this.close()
]);
}
}
}
onBuild(dom) {
// initUploader
const oJua = new Jua({
action: serverRequest('Upload'),
clickElement: dom.querySelector('#composeUploadButton'),
dragAndDropElement: dom.querySelector('.b-attachment-place')
}),
attachmentSizeLimit = pInt(SettingsGet('AttachmentLimit'));
oJua
// .on('onLimitReached', (limit) => {
// alert(limit);
// })
.on('onDragEnter', () => {
this.dragAndDropOver(true);
})
.on('onDragLeave', () => {
this.dragAndDropOver(false);
})
.on('onBodyDragEnter', () => {
this.attachmentsArea();
this.dragAndDropVisible(true);
})
.on('onBodyDragLeave', () => {
this.dragAndDropVisible(false);
})
.on('onProgress', (id, loaded, total) => {
let item = this.getAttachmentById(id);
if (item) {
item.progress(Math.floor((loaded / total) * 100));
}
})
.on('onSelect', (sId, oData) => {
this.dragAndDropOver(false);
const
size = pInt(oData.Size, null),
attachment = new ComposeAttachmentModel(
sId,
oData.FileName ? oData.FileName.toString() : '',
size
);
this.addAttachment(attachment, 1, oJua);
if (0 < size && 0 < attachmentSizeLimit && attachmentSizeLimit < size) {
attachment
.waiting(false)
.uploading(true)
.complete(true)
.error(i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'));
return false;
}
return true;
})
.on('onStart', id => {
let item = this.getAttachmentById(id);
if (item) {
item
.waiting(false)
.uploading(true)
.complete(false);
}
})
.on('onComplete', (id, result, data) => {
const attachment = this.getAttachmentById(id),
response = (data && data.Result) || {},
errorCode = response.ErrorCode,
attachmentJson = result && response.Attachment;
let error = '';
if (null != errorCode) {
error = getUploadErrorDescByCode(errorCode);
} else if (!attachmentJson) {
error = i18n('UPLOAD/ERROR_UNKNOWN');
}
if (attachment) {
if (error) {
attachment
.waiting(false)
.uploading(false)
.complete(true)
.error(error + '\n' + response.ErrorMessage);
} else if (attachmentJson) {
attachment
.waiting(false)
.uploading(false)
.complete(true);
attachment.fileName(attachmentJson.Name);
attachment.size(attachmentJson.Size ? pInt(attachmentJson.Size) : 0);
attachment.tempName(attachmentJson.TempName ? attachmentJson.TempName : '');
attachment.isInline = false;
}
}
});
this.addAttachmentEnabled(true);
addShortcut('q', 'meta', ScopeCompose, ()=>false);
addShortcut('w', 'meta', ScopeCompose, ()=>false);
addShortcut('m', 'meta', ScopeCompose, () => {
this.identitiesDropdownTrigger(true);
return false;
});
addShortcut('arrowdown', 'meta', ScopeCompose, () => {
this.skipCommand();
return false;
});
addShortcut('s', 'meta', ScopeCompose, () => {
this.saveCommand();
return false;
});
addShortcut('save', '', ScopeCompose, () => {
this.saveCommand();
return false;
});
if (Settings.app('allowCtrlEnterOnCompose')) {
addShortcut('enter', 'meta', ScopeCompose, () => {
this.sendCommand();
return false;
});
}
addShortcut('mailsend', '', ScopeCompose, () => {
this.sendCommand();
return false;
});
addShortcut('escape,close', 'shift', ScopeCompose, () => {
this.tryToClosePopup();
return false;
});
this.editor(editor => editor[isPlainEditor()?'modePlain':'modeWysiwyg']());
}
/**
* @param {string} id
* @returns {?Object}
*/
getAttachmentById(id) {
return this.attachments.find(item => item && id === item.id);
}
/**
* @returns {Object}
*/
prepareAttachmentsForSendOrSave() {
const result = {};
this.attachments.forEach(item => {
if (item && item.complete() && item.tempName() && item.enabled()) {
result[item.tempName()] = [item.fileName(), item.isInline ? '1' : '0', item.CID, item.contentLocation];
}
});
return result;
}
/**
* @param {MessageModel} message
*/
addMessageAsAttachment(message) {
if (message) {
let temp = message.subject();
temp = '.eml' === temp.slice(-4).toLowerCase() ? temp : temp + '.eml';
const attachment = new ComposeAttachmentModel(message.requestHash, temp, message.size());
attachment.fromMessage = true;
attachment.complete(true);
this.addAttachment(attachment);
}
}
addAttachment(attachment, view, oJua) {
oJua || attachment.waiting(false).uploading(true);
attachment.cancel = () => {
this.attachments.remove(attachment);
oJua && oJua.cancel(attachment.id);
};
this.attachments.push(attachment);
view && this.attachmentsArea();
}
/**
* @param {string} url
* @param {string} name
* @param {number} size
* @returns {ComposeAttachmentModel}
*/
addAttachmentHelper(url, name, size) {
const attachment = new ComposeAttachmentModel(url, name, size);
this.addAttachment(attachment, 1);
return attachment;
}
/**
* @param {MessageModel} message
* @param {string} type
*/
prepareMessageAttachments(message, type) {
if (message) {
if (ComposeType.ForwardAsAttachment === type) {
this.addMessageAsAttachment(message);
} else {
message.attachments.forEach(item => {
let add = false;
switch (type) {
case ComposeType.Reply:
case ComposeType.ReplyAll:
break;
case ComposeType.Forward:
case ComposeType.Draft:
case ComposeType.EditAsNew:
add = true;
break;
// no default
}
if (add) {
const attachment = new ComposeAttachmentModel(
item.download,
item.fileName,
item.estimatedSize,
item.isInline(),
item.isLinked(),
item.cid,
item.contentLocation
);
attachment.fromMessage = true;
this.addAttachment(attachment);
}
});
}
}
}
/**
* @param {boolean=} includeAttachmentInProgress = true
* @returns {boolean}
*/
isEmptyForm(includeAttachmentInProgress = true) {
const withoutAttachment = includeAttachmentInProgress
? !this.attachments.length
: !this.attachments.some(item => item && item.complete());
return (
!this.to.length &&
!this.cc.length &&
!this.bcc.length &&
!this.replyTo.length &&
!this.subject.length &&
withoutAttachment &&
(!this.oEditor || !this.oEditor.getData())
);
}
reset() {
this.to('');
this.cc('');
this.bcc('');
this.replyTo('');
this.subject('');
this.requestDsn(SettingsUserStore.requestDsn());
this.requestReadReceipt(SettingsUserStore.requestReadReceipt());
this.markAsImportant(false);
this.bodyArea();
this.aDraftInfo = null;
this.sInReplyTo = '';
this.bFromDraft = false;
this.sReferences = '';
this.sendError(false);
this.sendSuccessButSaveError(false);
this.savedError(false);
this.savedTime(0);
this.emptyToError(false);
this.attachmentsInProcessError(false);
this.showCc(false);
this.showBcc(false);
this.showReplyTo(false);
this.pgpSign(SettingsUserStore.pgpSign());
this.pgpEncrypt(SettingsUserStore.pgpEncrypt());
this.attachments([]);
this.dragAndDropOver(false);
this.dragAndDropVisible(false);
this.draftsFolder('');
this.draftUid(0);
this.sending(false);
this.saving(false);
this.oEditor && this.oEditor.clear();
this.dropMailvelope();
}
/**
* @returns {Array}
*/
getAttachmentsDownloadsForUpload() {
return this.attachments.filter(item => item && !item.tempName()).map(
item => item.id
);
}
mailvelopeArea() {
if (!this.mailvelope) {
/**
* Creates an iframe with an editor for a new encrypted mail.
* The iframe will be injected into the container identified by selector.
* https://mailvelope.github.io/mailvelope/Editor.html
*/
let text = this.oEditor.getData(),
encrypted = PgpUserStore.isEncrypted(text),
size = SettingsGet('PhpUploadSizes')['post_max_size'],
quota = pInt(size);
switch (size.slice(-1)) {
case 'G': quota *= 1024; // fallthrough
case 'M': quota *= 1024; // fallthrough
case 'K': quota *= 1024;
}
// Issue: can't select signing key
// this.pgpSign(this.pgpSign() || confirm('Sign this message?'));
mailvelope.createEditorContainer('#mailvelope-editor', PgpUserStore.mailvelopeKeyring, {
// https://mailvelope.github.io/mailvelope/global.html#EditorContainerOptions
quota: Math.max(2048, (quota / 1024)) - 48, // (text + attachments) limit in kilobytes
armoredDraft: encrypted ? text : '', // Ascii Armored PGP Text Block
predefinedText: encrypted ? '' : (this.oEditor.isHtml() ? htmlToPlain(text) : text),
/*
quotedMail: '', // Ascii Armored PGP Text Block mail that should be quoted
quotedMailIndent: true, // if true the quoted mail will be indented (default: true)
quotedMailHeader: '', // header to be added before the quoted mail
keepAttachments: false, // add attachments of quotedMail to editor (default: false)
// Issue: can't select signing key
signMsg: this.pgpSign()
*/
}).then(editor => this.mailvelope = editor);
}
this.viewArea('mailvelope');
}
attachmentsArea() {
this.viewArea('attachments');
}
bodyArea() {
this.viewArea('body');
}
allRecipients() {
return [
// From/sender is also recipient (Sent mailbox)
// this.currentIdentity().email(),
this.from(),
this.to(),
this.cc(),
this.bcc()
].join(',').split(',').map(value => getEmail(value.trim())).validUnique();
}
initPgpEncrypt() {
const recipients = this.allRecipients();
PgpUserStore.hasPublicKeyForEmails(recipients).then(result => {
console.log({canPgpEncrypt:result});
this.canPgpEncrypt(result);
});
PgpUserStore.mailvelopeHasPublicKeyForEmails(recipients).then(result => {
console.log({canMailvelope:result});
this.canMailvelope(result);
if (!result) {
'mailvelope' === this.viewArea() && this.bodyArea();
// this.dropMailvelope();
}
});
}
togglePgpSign() {
this.pgpSign(!this.pgpSign()/* && this.canPgpSign()*/);
}
togglePgpEncrypt() {
this.pgpEncrypt(!this.pgpEncrypt()/* && this.canPgpEncrypt()*/);
}
}