[PM-1060] Added new forwarder (Forward Email <https://forwardemail.net>) (#4809)
* Added new forwarder (Forward Email <https://forwardemail.net>) * fix: fixed Basic authorization header * fix: fixed returned email value * feat: added verbose message for end-users (e.g. "Not Found" vs. "Domain does not exist on your account." (automatically localized with i18n for user) * fix: fixed Buffer.from to Utils.fromBufferToB64 * fix: fixed fromBufferToB64 to fromUtf8ToB64 * Remove try-catch to properly display api errors --------- Co-authored-by: Daniel James Smith <djsmith@web.de>
This commit is contained in:
parent
ba5e890e86
commit
d18b45a87e
|
@ -405,6 +405,28 @@
|
|||
/>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="usernameOptions.forwardedService === 'forwardemail'">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="forwardemail-accessToken">{{ "apiAccessToken" | i18n }}</label>
|
||||
<input
|
||||
id="forwardemail-accessToken"
|
||||
type="password"
|
||||
name="ForwardEmailAccessToken"
|
||||
[(ngModel)]="usernameOptions.forwardedForwardEmailApiToken"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="forwardemail-domain">{{ "domainName" | i18n }}</label>
|
||||
<input
|
||||
id="forwardemail-domain"
|
||||
type="text"
|
||||
name="ForwardEmailDomain"
|
||||
[(ngModel)]="usernameOptions.forwardedForwardEmailDomain"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box" *ngIf="usernameOptions.type === 'subaddress'">
|
||||
|
|
|
@ -432,6 +432,28 @@
|
|||
/>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="usernameOptions.forwardedService === 'forwardemail'">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="forwardemail-accessToken">{{ "apiAccessToken" | i18n }}</label>
|
||||
<input
|
||||
id="forwardemail-accessToken"
|
||||
type="password"
|
||||
name="ForwardEmailAccessToken"
|
||||
[(ngModel)]="usernameOptions.forwardedForwardEmailApiToken"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="forwardemail-domain">{{ "domainName" | i18n }}</label>
|
||||
<input
|
||||
id="forwardemail-domain"
|
||||
type="text"
|
||||
name="ForwardEmailDomain"
|
||||
[(ngModel)]="usernameOptions.forwardedForwardEmailDomain"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box" *ngIf="usernameOptions.type === 'subaddress'" [hidden]="!showOptions">
|
||||
|
|
|
@ -343,6 +343,28 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" *ngIf="usernameOptions.forwardedService === 'forwardemail'">
|
||||
<div class="form-group col-4">
|
||||
<label for="forwardemail-apikey">{{ "apiAccessToken" | i18n }}</label>
|
||||
<input
|
||||
id="forwardemail-apikey"
|
||||
class="form-control"
|
||||
type="password"
|
||||
[(ngModel)]="usernameOptions.forwardedForwardEmailApiToken"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="forwardemail-domain">{{ "domainName" | i18n }}</label>
|
||||
<input
|
||||
id="forwardemail-domain"
|
||||
class="form-control"
|
||||
type="text"
|
||||
[(ngModel)]="usernameOptions.forwardedForwardEmailDomain"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="row" *ngIf="usernameOptions.type === 'subaddress'">
|
||||
<div class="form-group col-4">
|
||||
|
|
|
@ -280,6 +280,7 @@ const devServer =
|
|||
https://quack.duckduckgo.com/api/email/addresses
|
||||
https://app.anonaddy.com/api/v1/aliases
|
||||
https://api.fastmail.com
|
||||
https://api.forwardemail.net
|
||||
http://localhost:5000
|
||||
;object-src
|
||||
'self'
|
||||
|
|
|
@ -242,6 +242,7 @@ export class GeneratorComponent implements OnInit {
|
|||
{ name: "Fastmail", value: "fastmail", validForSelfHosted: true },
|
||||
{ name: "Firefox Relay", value: "firefoxrelay", validForSelfHosted: false },
|
||||
{ name: "SimpleLogin", value: "simplelogin", validForSelfHosted: true },
|
||||
{ name: "Forward Email", value: "forwardemail", validForSelfHosted: true },
|
||||
];
|
||||
|
||||
this.usernameOptions = await this.usernameGenerationService.getOptions();
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import { ApiService } from "../../../../abstractions/api.service";
|
||||
import { Utils } from "../../../../misc/utils";
|
||||
|
||||
import { Forwarder } from "./forwarder";
|
||||
import { ForwarderOptions } from "./forwarder-options";
|
||||
|
||||
export class ForwardEmailForwarder implements Forwarder {
|
||||
async generate(apiService: ApiService, options: ForwarderOptions): Promise<string> {
|
||||
if (options.apiKey == null || options.apiKey === "") {
|
||||
throw "Invalid Forward Email API key.";
|
||||
}
|
||||
if (options.forwardemail?.domain == null || options.forwardemail.domain === "") {
|
||||
throw "Invalid Forward Email domain.";
|
||||
}
|
||||
const requestInit: RequestInit = {
|
||||
redirect: "manual",
|
||||
cache: "no-store",
|
||||
method: "POST",
|
||||
headers: new Headers({
|
||||
Authorization: "Basic " + Utils.fromUtf8ToB64(options.apiKey + ":"),
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
};
|
||||
const url = `https://api.forwardemail.net/v1/domains/${options.forwardemail.domain}/aliases`;
|
||||
requestInit.body = JSON.stringify({
|
||||
labels: options.website,
|
||||
description:
|
||||
(options.website != null ? "Website: " + options.website + ". " : "") +
|
||||
"Generated by Bitwarden.",
|
||||
});
|
||||
const request = new Request(url, requestInit);
|
||||
const response = await apiService.nativeFetch(request);
|
||||
if (response.status === 200 || response.status === 201) {
|
||||
const json = await response.json();
|
||||
return json?.name + "@" + (json?.domain?.name || options.forwardemail.domain);
|
||||
}
|
||||
if (response.status === 401) {
|
||||
throw "Invalid Forward Email API key.";
|
||||
}
|
||||
const json = await response.json();
|
||||
if (json?.message != null) {
|
||||
throw "Forward Email error:\n" + json.message;
|
||||
}
|
||||
if (json?.error != null) {
|
||||
throw "Forward Email error:\n" + json.error;
|
||||
}
|
||||
throw "Unknown Forward Email error occurred.";
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ export class ForwarderOptions {
|
|||
website: string;
|
||||
fastmail = new FastmailForwarderOptions();
|
||||
anonaddy = new AnonAddyForwarderOptions();
|
||||
forwardemail = new ForwardEmailForwarderOptions();
|
||||
}
|
||||
|
||||
export class FastmailForwarderOptions {
|
||||
|
@ -12,3 +13,7 @@ export class FastmailForwarderOptions {
|
|||
export class AnonAddyForwarderOptions {
|
||||
domain: string;
|
||||
}
|
||||
|
||||
export class ForwardEmailForwarderOptions {
|
||||
domain: string;
|
||||
}
|
||||
|
|
|
@ -5,3 +5,4 @@ export { FirefoxRelayForwarder } from "./firefox-relay-forwarder";
|
|||
export { Forwarder } from "./forwarder";
|
||||
export { ForwarderOptions } from "./forwarder-options";
|
||||
export { SimpleLoginForwarder } from "./simple-login-forwarder";
|
||||
export { ForwardEmailForwarder } from "./forward-email-forwarder";
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
DuckDuckGoForwarder,
|
||||
FastmailForwarder,
|
||||
FirefoxRelayForwarder,
|
||||
ForwardEmailForwarder,
|
||||
Forwarder,
|
||||
ForwarderOptions,
|
||||
SimpleLoginForwarder,
|
||||
|
@ -22,6 +23,7 @@ const DefaultOptions = {
|
|||
catchallType: "random",
|
||||
forwardedService: "",
|
||||
forwardedAnonAddyDomain: "anonaddy.me",
|
||||
forwardedForwardEmailDomain: "hideaddress.net",
|
||||
};
|
||||
|
||||
export class UsernameGenerationService implements UsernameGenerationServiceAbstraction {
|
||||
|
@ -137,6 +139,10 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr
|
|||
} else if (o.forwardedService === "duckduckgo") {
|
||||
forwarder = new DuckDuckGoForwarder();
|
||||
forwarderOptions.apiKey = o.forwardedDuckDuckGoToken;
|
||||
} else if (o.forwardedService === "forwardemail") {
|
||||
forwarder = new ForwardEmailForwarder();
|
||||
forwarderOptions.apiKey = o.forwardedForwardEmailApiToken;
|
||||
forwarderOptions.forwardemail.domain = o.forwardedForwardEmailDomain;
|
||||
}
|
||||
|
||||
if (forwarder == null) {
|
||||
|
|
Loading…
Reference in New Issue