diff --git a/src/app/compose/compose.component.ts b/src/app/compose/compose.component.ts
index e1aa9ecf2..1a669452b 100644
--- a/src/app/compose/compose.component.ts
+++ b/src/app/compose/compose.component.ts
@@ -138,7 +138,7 @@ export class ComposeComponent implements AfterViewInit, OnDestroy, OnInit {
this.draftDeskservice.fromsSubject.value[0].nameAndAddress : '';
} else {
this.model.from = from.nameAndAddress;
- if ( !this.has_pasted_signature && from.signature ) {
+ if ( !this.model.skipSignature && !this.has_pasted_signature && from.signature ) {
this.has_pasted_signature = true;
this.signature = from.signature;
// Sig is HTML, or Reply/Fwd Draft is HTML (contains .html)
diff --git a/src/app/compose/draftdesk.service.spec.ts b/src/app/compose/draftdesk.service.spec.ts
index 0b4f6bbff..daa0b26ec 100644
--- a/src/app/compose/draftdesk.service.spec.ts
+++ b/src/app/compose/draftdesk.service.spec.ts
@@ -17,7 +17,7 @@
// along with Runbox 7. If not, see
expect(draft.isUnsaved()).toBe(true);
done();
});
+ it('Send again: copies a sent HTML message into a new draft', (done) => {
+ const draft = DraftFormModel.sendAgain({
+ mid: 123,
+ from: [
+ {address: 'from@runbox.com', name: 'From'}
+ ],
+ to: [
+ {address: 'to@runbox.com', name: 'To'}
+ ],
+ cc: [
+ {address: 'cc@runbox.com', name: 'CC'}
+ ],
+ bcc: [
+ {address: 'bcc@runbox.com', name: 'BCC'}
+ ],
+ attachments: [
+ {cid: 'inline-image'}
+ ],
+ subject: 'Test subject',
+ rawtext: 'blabla\nabcde',
+ sanitized_html: '
blabla
abcde
' + }, + [ + Identity.fromObject({'email':'fallback@runbox.com'}), + Identity.fromObject({'email':'from@runbox.com'}) + ]); + + expect(draft.subject).toBe('Test subject'); + expect(draft.from).toBe('from@runbox.com'); + expect(draft.to[0].nameAndAddress).toBe('"To"blabla
abcde
'); + expect(draft.useHTML).toBe(true); + expect(draft.skipSignature).toBe(true); + expect(draft.attachments[0] instanceof ForwardedAttachment).toBeTrue(); + expect((draft.attachments[0] as ForwardedAttachment).messageId).toBe('123'); + expect(draft.isUnsaved()).toBe(true); + done(); + }); + it('Send again: falls back to the default identity for a non-matching sender', (done) => { + const draft = DraftFormModel.sendAgain({ + from: [ + {address: 'old-address@runbox.com', name: 'Old'} + ], + to: null, + attachments: [], + subject: 'Plain subject', + rawtext: 'plain body' + }, + [ Identity.fromObject({'email':'default@runbox.com'}) ]); + + expect(draft.subject).toBe('Plain subject'); + expect(draft.from).toBe('default@runbox.com'); + expect(draft.to).toEqual([]); + expect(draft.msg_body).toBe('plain body'); + expect(draft.useHTML).toBe(false); + expect(draft.isUnsaved()).toBe(true); + done(); + }); it('Reply: Address with object, single reply-to', (done) => { console.log('Reply test: Address with object, single reply-to'); // fromObj, identities, all (t/f), html (t/f) diff --git a/src/app/compose/draftdesk.service.ts b/src/app/compose/draftdesk.service.ts index 6f1efa0be..ede33a083 100644 --- a/src/app/compose/draftdesk.service.ts +++ b/src/app/compose/draftdesk.service.ts @@ -61,6 +61,7 @@ export class DraftFormModel { in_reply_to: string; reply_to_id: string = null; replying = false; + skipSignature = false; tags: string; useHTML = false; save = 'Save'; @@ -209,6 +210,40 @@ ${mailObj.sanitized_html}`; return ret; } + public static sendAgain(mailObj, froms: Identity[]): DraftFormModel { + const ret = new DraftFormModel(); + + if (froms.length > 0) { + const originalFrom = mailObj.from && mailObj.from[0] && mailObj.from[0].address + ? mailObj.from[0].address.toLowerCase() + : null; + ret.from = ( + froms.find(fromObj => fromObj.email.toLowerCase() === originalFrom) || froms[0] + ).email; + } else { + console.error('DraftDesk: No froms passed to sendAgain'); + } + + ret.subject = mailObj.subject; + ret.skipSignature = true; + ret.to = DraftFormModel.copyAddresses(mailObj.to); + ret.cc = DraftFormModel.copyAddresses(mailObj.cc); + ret.bcc = DraftFormModel.copyAddresses(mailObj.bcc); + ret.msg_body = mailObj.rawtext || (mailObj.text && mailObj.text.text) || ''; + ret.preview = DraftFormModel.trimmedPreview(ret.msg_body); + + if (mailObj.sanitized_html) { + ret.html = mailObj.sanitized_html; + ret.useHTML = true; + } + + ret.attachments = (mailObj.attachments || []).map((attachment, ndx) => + new ForwardedAttachment(String(mailObj.mid), ndx, attachment.cid) + ); + + return ret; + } + public isUnsaved(): boolean { if (this.mid <= -1) { return true; @@ -216,6 +251,12 @@ ${mailObj.sanitized_html}`; return false; } + private static copyAddresses(addresses): MailAddressInfo[] { + return Array.isArray(addresses) + ? addresses.map((addr) => new MailAddressInfo(addr.name, addr.address)) + : []; + } + private setFromForResponse(mailObj, froms: Identity[]): void { if (froms.length > 0) { this.from = ( diff --git a/src/app/mailviewer/messageactions.ts b/src/app/mailviewer/messageactions.ts index a8bdab9dc..d85e7f452 100644 --- a/src/app/mailviewer/messageactions.ts +++ b/src/app/mailviewer/messageactions.ts @@ -29,6 +29,7 @@ export interface MessageActions { reply(useHTML?: boolean); replyToAll(useHTML?: boolean); forward(useHTML?: boolean); + sendAgain(); markSeen(seen_flag_value?: number); trainSpam(params: any); blockSender(param: string) diff --git a/src/app/mailviewer/rmm6messageactions.ts b/src/app/mailviewer/rmm6messageactions.ts index fe6ae798c..16aa84cdf 100644 --- a/src/app/mailviewer/rmm6messageactions.ts +++ b/src/app/mailviewer/rmm6messageactions.ts @@ -57,6 +57,10 @@ export class RMM6MessageActions implements MessageActions { this.openCompose('/mail/forward?message=' + this.mailViewerComponent.messageId); } + sendAgain() { + this.snackBar.open('Not supported in RMM6 yet', null, {duration: 1000}); + } + markSeen(seen_flag_value = 1) { this.http.put('/rest/v1/email/' + this.mailViewerComponent.messageId, JSON.stringify( { seen_flag : seen_flag_value })) diff --git a/src/app/mailviewer/rmm7messageactions.ts b/src/app/mailviewer/rmm7messageactions.ts index 1da73102d..ccf1f6a7e 100644 --- a/src/app/mailviewer/rmm7messageactions.ts +++ b/src/app/mailviewer/rmm7messageactions.ts @@ -135,6 +135,16 @@ export class RMM7MessageActions implements MessageActions { }); } + public sendAgain() { + ProgressDialog.open(this.dialog); + this.draftDeskService.newDraft( + DraftFormModel.sendAgain(this.mailViewerComponent.mailObj, this.draftDeskService.fromsSubject.value) + ).then(() => { + this.mailViewerComponent.close('goToDraftDesk'); + ProgressDialog.close(); + }); + } + public markSeen(seen_flag_value = 1) { this.updateMessages({ messageIds: [this.mailViewerComponent.messageId], diff --git a/src/app/mailviewer/singlemailviewer.component.html b/src/app/mailviewer/singlemailviewer.component.html index 5eaf9debb..3ecde2ef9 100644 --- a/src/app/mailviewer/singlemailviewer.component.html +++ b/src/app/mailviewer/singlemailviewer.component.html @@ -36,7 +36,10 @@ -