From d18b45a87ea07fc1daed74d3c54c3767fadc8746 Mon Sep 17 00:00:00 2001 From: titanism <101466223+titanism@users.noreply.github.com> Date: Fri, 9 Jun 2023 02:55:12 -0500 Subject: [PATCH] [PM-1060] Added new forwarder (Forward Email ) (#4809) * Added new forwarder (Forward Email ) * 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 --- .../popup/generator/generator.component.html | 22 +++++++++ .../src/app/tools/generator.component.html | 22 +++++++++ .../src/app/tools/generator.component.html | 22 +++++++++ apps/web/webpack.config.js | 1 + .../components/generator.component.ts | 1 + .../forward-email-forwarder.ts | 49 +++++++++++++++++++ .../email-forwarders/forwarder-options.ts | 5 ++ .../username/email-forwarders/index.ts | 1 + .../username/username-generation.service.ts | 6 +++ 9 files changed, 129 insertions(+) create mode 100644 libs/common/src/tools/generator/username/email-forwarders/forward-email-forwarder.ts diff --git a/apps/browser/src/tools/popup/generator/generator.component.html b/apps/browser/src/tools/popup/generator/generator.component.html index 3b07c3b2ce..83b2c6dee7 100644 --- a/apps/browser/src/tools/popup/generator/generator.component.html +++ b/apps/browser/src/tools/popup/generator/generator.component.html @@ -405,6 +405,28 @@ /> + +
+ + +
+
+ + +
+
diff --git a/apps/desktop/src/app/tools/generator.component.html b/apps/desktop/src/app/tools/generator.component.html index 423b47b3f7..adbe6df312 100644 --- a/apps/desktop/src/app/tools/generator.component.html +++ b/apps/desktop/src/app/tools/generator.component.html @@ -432,6 +432,28 @@ />
+ +
+ + +
+
+ + +
+
diff --git a/apps/web/src/app/tools/generator.component.html b/apps/web/src/app/tools/generator.component.html index 369812bc97..e2da0333e4 100644 --- a/apps/web/src/app/tools/generator.component.html +++ b/apps/web/src/app/tools/generator.component.html @@ -343,6 +343,28 @@ />
+
+
+ + +
+
+ + +
+
diff --git a/apps/web/webpack.config.js b/apps/web/webpack.config.js index 54899dca7b..0651603d56 100644 --- a/apps/web/webpack.config.js +++ b/apps/web/webpack.config.js @@ -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' diff --git a/libs/angular/src/tools/generator/components/generator.component.ts b/libs/angular/src/tools/generator/components/generator.component.ts index af88ae2475..9ef7318658 100644 --- a/libs/angular/src/tools/generator/components/generator.component.ts +++ b/libs/angular/src/tools/generator/components/generator.component.ts @@ -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(); diff --git a/libs/common/src/tools/generator/username/email-forwarders/forward-email-forwarder.ts b/libs/common/src/tools/generator/username/email-forwarders/forward-email-forwarder.ts new file mode 100644 index 0000000000..a1b525f8f4 --- /dev/null +++ b/libs/common/src/tools/generator/username/email-forwarders/forward-email-forwarder.ts @@ -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 { + 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."; + } +} diff --git a/libs/common/src/tools/generator/username/email-forwarders/forwarder-options.ts b/libs/common/src/tools/generator/username/email-forwarders/forwarder-options.ts index ef5311f0d7..0340eedca8 100644 --- a/libs/common/src/tools/generator/username/email-forwarders/forwarder-options.ts +++ b/libs/common/src/tools/generator/username/email-forwarders/forwarder-options.ts @@ -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; +} diff --git a/libs/common/src/tools/generator/username/email-forwarders/index.ts b/libs/common/src/tools/generator/username/email-forwarders/index.ts index a9a437225e..d102cc236e 100644 --- a/libs/common/src/tools/generator/username/email-forwarders/index.ts +++ b/libs/common/src/tools/generator/username/email-forwarders/index.ts @@ -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"; diff --git a/libs/common/src/tools/generator/username/username-generation.service.ts b/libs/common/src/tools/generator/username/username-generation.service.ts index 6f9af5cb35..3ff9884331 100644 --- a/libs/common/src/tools/generator/username/username-generation.service.ts +++ b/libs/common/src/tools/generator/username/username-generation.service.ts @@ -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) {