Skip to content

Commit

Permalink
feat(mailviewer): Add sender/domain blocking functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
castaway committed Sep 12, 2024
1 parent f2ae262 commit 6538960
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 7 deletions.
9 changes: 9 additions & 0 deletions src/app/common/mailaddressinfo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ describe('MailAddressInfo', () => {
expect(ma.name).toBe('Test');
expect(ma.address).toBe('[email protected]');
expect(ma.nameAndAddress).toBe('"Test" <[email protected]>');
expect(ma.domain).toBe('runbox.com');
});
it('Parse single email address', () => {
const ma = MailAddressInfo.parse('[email protected]');
expect(ma[0].name).toBe(null);
expect(ma[0].address).toBe('[email protected]');
expect(ma[0].nameAndAddress).toBe('[email protected]');
expect(ma[0].domain).toBe('runbox.com');
});
it('Parse full single address', () => {
const ma = MailAddressInfo.parse('"Test" <[email protected]>');
Expand Down Expand Up @@ -68,4 +70,11 @@ describe('MailAddressInfo', () => {
expect(ma_list[1].address).toBe('[email protected]');
expect(ma_list[1].nameAndAddress).toBe('"Test2" <[email protected]>');
});
it('Parse multi-level domain', () => {
const ma_list = MailAddressInfo.parse('"Fred B" <[email protected]>');
expect(ma_list[0].name).toBe('Fred B');
expect(ma_list[0].address).toBe('[email protected]');
expect(ma_list[0].nameAndAddress).toBe('"Fred B" <[email protected]>');
expect(ma_list[0].domain).toBe('foo.bar.baz.tld');
});
});
2 changes: 2 additions & 0 deletions src/app/common/mailaddressinfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@

export class MailAddressInfo {
nameAndAddress: string;
domain: string;

constructor(public name: string, public address: string) {
this.nameAndAddress = name ? `"${name}" <${address}>` : address;
this.domain = address.split('@')[1];
}

public static parse(mailaddr: string): MailAddressInfo[] {
Expand Down
1 change: 1 addition & 0 deletions src/app/mailviewer/messageactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ export interface MessageActions {
forward(useHTML?: boolean);
markSeen(seen_flag_value?: number);
trainSpam(params: any);
blockSender(param: String)
}

4 changes: 4 additions & 0 deletions src/app/mailviewer/rmm6messageactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,8 @@ export class RMM6MessageActions implements MessageActions {
trainSpam() {
throw new Error('Method not implemented.');
}

blockSender() {
throw new Error('Method not implemented.');
}
}
12 changes: 12 additions & 0 deletions src/app/mailviewer/rmm7messageactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,18 @@ export class RMM7MessageActions implements MessageActions {
});
}

blockSender(param) {
const msg = `Blocking sender: ${param}`;
const snackBarRef = this.snackBar.open(msg);
this.rmmapi.blockSender(param).subscribe((res) => {
if ( res.status === 'error' ) {
snackBarRef.dismiss();
this.snackBar.open('There was an error with Sender blocking functionality. Please try again.', 'Dismiss');
}
});
snackBarRef.dismiss();
}

// Update mailviewer menu flag icon after flagging?
flag() {
this.updateMessages({
Expand Down
28 changes: 24 additions & 4 deletions src/app/mailviewer/singlemailviewer.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,37 @@
<mat-icon svgIcon="alert-octagon-outline"></mat-icon>
</button>
</ng-container>
<a *ngIf="morebuttonindex>8" mat-icon-button
<button mat-icon-button *ngIf="morebuttonindex>8" matTooltip="Block Sender/Domain" [matMenuTriggerFor]="blockSenderMenu">
<mat-icon svgIcon="block"></mat-icon>
</button>
<a *ngIf="morebuttonindex>9" mat-icon-button
matTooltip="View source" [href]="'/rest/v1/email/'+messageId+'/raw'" target="_blank">
<mat-icon svgIcon="code-tags"></mat-icon>
</a>
<button mat-icon-button *ngIf="mailContentHTML && morebuttonindex>9" matTooltip="HTML settings" [matMenuTriggerFor]="htmlSettingsMenu">
<button mat-icon-button *ngIf="mailContentHTML && morebuttonindex>10" matTooltip="HTML settings" [matMenuTriggerFor]="htmlSettingsMenu">
<mat-icon svgIcon="cog"></mat-icon>
</button>
<a *ngIf="mailContentHTML && morebuttonindex>10" mat-icon-button
<a *ngIf="mailContentHTML && morebuttonindex>11" mat-icon-button
matTooltip="Original HTML" [href]="'/rest/v1/email/'+messageId+'/html'" target="_blank">
<mat-icon svgIcon="alert"></mat-icon>
</a>
<button mat-icon-button *ngIf="morebuttonindex < 11" [matMenuTriggerFor]="moreMailActionsMenu" matTooltip="More message actions">
<button mat-icon-button *ngIf="morebuttonindex < 12" [matMenuTriggerFor]="moreMailActionsMenu" matTooltip="More message actions">
<mat-icon svgIcon="dots-vertical"></mat-icon>
</button>

<mat-menu #blockSenderMenu>
<button mat-menu-item (click)="messageActionsHandler.blockSender(mailObj.from[0].address)">
Block Sender Email
</button>
<button mat-menu-item (click)="messageActionsHandler.blockSender(mailObj.from[0].domain)">
Block Sender Domain
</button>
<a mat-menu-item
[href]="'/mail/rules'" target="rmm6">
Manage Blocking Rules
</a>
</mat-menu>

<mat-menu #htmlSettingsMenu="matMenu">
<mat-radio-group
style="display: inline-flex; flex-direction: column"
Expand Down Expand Up @@ -153,6 +169,10 @@
<span>Not spam</span>
</button>
</ng-container>
<button mat-menu-item *ngIf="morebuttonindex<9" [matMenuTriggerFor]="blockSenderMenu">
<mat-icon svgIcon="block"></mat-icon>
<span>Block Sender/Domain</span>
</button>
<a *ngIf="morebuttonindex<9" mat-menu-item
[href]="'/rest/v1/email/'+messageId+'/raw'" target="_blank">
<mat-icon svgIcon="code-tags"></mat-icon>
Expand Down
6 changes: 5 additions & 1 deletion src/app/mailviewer/singlemailviewer.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ describe('SingleMailViewerComponent', () => {
mid: messageId,
headers: {
from: {
value: '[email protected]'
value: [{ 'address': '[email protected]',
'name': 'Testy' }]
},
date: new Date(2016, 0, 1).toJSON(),
subject: 'Test subject'
Expand Down Expand Up @@ -200,6 +201,9 @@ describe('SingleMailViewerComponent', () => {
trainSpam(params: any) {
throw new Error('Method not implemented.');
}
blockSender(param: any) {
throw new Error('Method not implemented.');
}
};
fixture.autoDetectChanges();
});
Expand Down
3 changes: 2 additions & 1 deletion src/app/mailviewer/singlemailviewer.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { ShowHTMLDialogComponent } from '../dialog/htmlconfirm.dialog';
import { MessageTableRowTool} from '../messagetable/messagetablerow';
import { PreferencesService } from '../common/preferences.service';
// import { ShowImagesDialogComponent } from '../dialog/imagesconfirm.dialog';
import { MailAddressInfo } from '../common/mailaddressinfo';

// const DOMPurify = require('dompurify');
const showHtmlDecisionKey = 'rmm7showhtmldecision';
Expand Down Expand Up @@ -399,7 +400,7 @@ export class SingleMailViewerComponent implements OnInit, DoCheck, AfterViewInit
throw res;
}
res.subject = res.headers.subject;
res.from = res.headers.from.value;
res.from = res.headers.from.value.map(f => new MailAddressInfo(f.name,f.address));
res.to = res.headers.to ? res.headers.to.value : '';
res.cc = res.headers.cc ? res.headers.cc.value : '';

Expand Down
2 changes: 1 addition & 1 deletion src/app/rmmapi/messagecache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { MessageContents } from './rbwebmail';

export class MessageCache {
db: Dexie;
message_version = 5;
message_version = 6;

constructor(userId: number) {
// REMOVE THIS CODE AFTER 06-2024, delete old message caches
Expand Down
4 changes: 4 additions & 0 deletions src/app/rmmapi/rbwebmail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,10 @@ export class RunboxWebmailAPI {
return this.http.post('/rest/v1/spam/', JSON.stringify(params));
}

public blockSender(param): Observable<any> {
return this.http.post('/rest/v1/rules/block_sender', JSON.stringify({'sender': param}));
}

// Moves to Trash if not already in Trash
// Deletes if currently in Trash
public deleteMessages(messageIds: number[]): Observable<any> {
Expand Down

0 comments on commit 6538960

Please sign in to comment.