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) {