Bug: [FEATURE] Use newtype pattern for email addresses



### Feature Description

This issue covers one of the problems mentioned in #119, about using [the newtype pattern](https://rust-unofficial.github.io/patterns/patterns/behavioural/newtype.html) for email addresses. The requirement is that email addresses must be validated once during construction/deserialization and should never be validated again. This would also eliminate the validation being performed at the time of masking email addresses (specifically line 97 in the snippet):

https://github.com/juspay/hyperswitch/blob/d107b44fd356f172ef7c9535567d266a6301e43d/crates/common_utils/src/pii.rs#L87-L109

Please also include unit tests in your PR.

_For external contributors, clarify any questions you may have, and let us know that you're interested in picking this up. We'll assign this issue to you to reduce duplication of effort on the same task._

### Possible Implementation

You can use a newtype like so:

```rust
use masking::Secret;

struct Email(Secret<String>);

let email = Email::from_str("..."); // You can use the `FromStr` trait for this purpose
```

For validating emails, the existing regex validation should suffice. Also, implement `Serialize`, `Deserialize` and `masking::Strategy` for `Email`.

### Have you spent some time to check if this feature request has been raised before?

- [X] I checked and didn't find similar issue

### Have you read the Contributing Guidelines?

- [X] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

None
diff --git a/Cargo.lock b/Cargo.lock
index 321e402c34a..82cc4015a53 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1305,6 +1305,7 @@ version = "0.1.0"
 dependencies = [
  "async-trait",
  "bytes",
+ "diesel",
  "error-stack",
  "fake",
  "futures",
diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs
index 52524aea8c3..6e00b5778bb 100644
--- a/crates/api_models/src/admin.rs
+++ b/crates/api_models/src/admin.rs
@@ -228,7 +228,7 @@ pub struct MerchantDetails {
 
     /// The merchant's primary email address
     #[schema(value_type = Option<String>, max_length = 255, example = "johndoe@test.com")]
-    pub primary_email: Option<Secret<String, pii::Email>>,
+    pub primary_email: Option<pii::Email>,
 
     /// The merchant's secondary contact name
     #[schema(value_type = Option<String>, max_length= 255, example = "John Doe2")]
@@ -240,7 +240,7 @@ pub struct MerchantDetails {
 
     /// The merchant's secondary email address
     #[schema(value_type = Option<String>, max_length = 255, example = "johndoe2@test.com")]
-    pub secondary_email: Option<Secret<String, pii::Email>>,
+    pub secondary_email: Option<pii::Email>,
 
     /// The business website of the merchant
     #[schema(max_length = 255, example = "www.example.com")]
diff --git a/crates/api_models/src/customers.rs b/crates/api_models/src/customers.rs
index a48be2e9dad..b95d1758a4d 100644
--- a/crates/api_models/src/customers.rs
+++ b/crates/api_models/src/customers.rs
@@ -19,7 +19,7 @@ pub struct CustomerRequest {
     pub name: Option<String>,
     /// The customer's email address
     #[schema(value_type = Option<String>,max_length = 255, example = "JonTest@test.com")]
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<pii::Email>,
     /// The customer's phone number
     #[schema(value_type = Option<String>,max_length = 255, example = "9999999999")]
     pub phone: Option<Secret<String>>,
@@ -59,7 +59,7 @@ pub struct CustomerResponse {
     pub name: Option<String>,
     /// The customer's email address
     #[schema(value_type = Option<String>,max_length = 255, example = "JonTest@test.com")]
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<pii::Email>,
     /// The customer's phone number
     #[schema(value_type = Option<String>,max_length = 255, example = "9999999999")]
     pub phone: Option<Secret<String>>,
diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index de0cd91e527..3740c996ed3 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -1,6 +1,6 @@
 use std::num::NonZeroI64;
 
-use common_utils::pii;
+use common_utils::{pii, pii::Email};
 use masking::{PeekInterface, Secret};
 use router_derive::Setter;
 use time::PrimitiveDateTime;
@@ -102,7 +102,7 @@ pub struct PaymentsRequest {
 
     /// description: The customer's email address
     #[schema(max_length = 255, value_type = Option<String>, example = "johntest@test.com")]
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
 
     /// description: The customer's name
     #[schema(value_type = Option<String>, max_length = 255, example = "John Test")]
@@ -258,7 +258,7 @@ pub struct VerifyRequest {
     // and is later passed in the struct
     pub merchant_id: Option<String>,
     pub customer_id: Option<String>,
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub name: Option<Secret<String>>,
     pub phone: Option<Secret<String>>,
     pub phone_country_code: Option<String>,
@@ -443,7 +443,7 @@ pub enum PayLaterData {
     KlarnaRedirect {
         /// The billing email
         #[schema(value_type = String)]
-        billing_email: Secret<String, pii::Email>,
+        billing_email: Email,
         // The billing country code
         #[schema(value_type = CountryAlpha2, example = "US")]
         billing_country: api_enums::CountryAlpha2,
@@ -459,7 +459,7 @@ pub enum PayLaterData {
     AfterpayClearpayRedirect {
         /// The billing email
         #[schema(value_type = String)]
-        billing_email: Secret<String, pii::Email>,
+        billing_email: Email,
         /// The billing name
         #[schema(value_type = String)]
         billing_name: Secret<String>,
@@ -617,7 +617,7 @@ pub enum BankRedirectData {
     },
     OnlineBankingFinland {
         // Shopper Email
-        email: Option<Secret<String, pii::Email>>,
+        email: Option<Email>,
     },
     OnlineBankingPoland {
         // Issuer banks
@@ -669,7 +669,7 @@ pub struct BankDebitBilling {
     pub name: Secret<String>,
     /// The billing email for bank debits
     #[schema(value_type = String, example = "example@example.com")]
-    pub email: Secret<String, pii::Email>,
+    pub email: Email,
     /// The billing address for bank debits
     pub address: Option<AddressDetails>,
 }
@@ -1072,7 +1072,7 @@ pub struct PaymentsResponse {
 
     /// description: The customer's email address
     #[schema(max_length = 255, value_type = Option<String>, example = "johntest@test.com")]
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
 
     /// description: The customer's name
     #[schema(value_type = Option<String>, max_length = 255, example = "John Test")]
@@ -1212,7 +1212,7 @@ pub struct VerifyResponse {
     // pub status: enums::VerifyStatus,
     pub client_secret: Option<Secret<String>>,
     pub customer_id: Option<String>,
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub name: Option<Secret<String>>,
     pub phone: Option<Secret<String>>,
     pub mandate_id: Option<String>,
diff --git a/crates/common_utils/Cargo.toml b/crates/common_utils/Cargo.toml
index a8f24cb6603..ae31147d5b7 100644
--- a/crates/common_utils/Cargo.toml
+++ b/crates/common_utils/Cargo.toml
@@ -8,20 +8,9 @@ readme = "README.md"
 license = "Apache-2.0"
 
 [features]
-signals = [
-    "dep:signal-hook-tokio",
-    "dep:signal-hook",
-    "dep:tokio",
-    "dep:router_env",
-    "dep:futures"
-]
-async_ext = [
-    "dep:futures",
-    "dep:async-trait"
-]
-logs = [
-    "dep:router_env"
-]
+signals = ["dep:signal-hook-tokio", "dep:signal-hook", "dep:tokio", "dep:router_env", "dep:futures"]
+async_ext = ["dep:futures", "dep:async-trait"]
+logs = ["dep:router_env"]
 
 [dependencies]
 async-trait = { version = "0.1.68", optional = true }
@@ -46,6 +35,7 @@ md5 = "0.7.0"
 # First party crates
 masking = { version = "0.1.0", path = "../masking" }
 router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"], optional = true }
+diesel = "2.0.3"
 
 [target.'cfg(not(target_os = "windows"))'.dependencies]
 signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"], optional = true }
diff --git a/crates/common_utils/src/pii.rs b/crates/common_utils/src/pii.rs
index 14f8a260b48..f56df89b25e 100644
--- a/crates/common_utils/src/pii.rs
+++ b/crates/common_utils/src/pii.rs
@@ -1,13 +1,25 @@
 //! Personal Identifiable Information protection.
 
-use std::{convert::AsRef, fmt};
+use std::{convert::AsRef, fmt, str::FromStr};
 
-use masking::{Strategy, WithType};
+use diesel::{
+    backend,
+    backend::Backend,
+    deserialize,
+    deserialize::FromSql,
+    prelude::*,
+    serialize::{Output, ToSql},
+    sql_types, AsExpression,
+};
+use masking::{Secret, Strategy, WithType};
 
-use crate::validation::validate_email;
+use crate::{errors::ValidationError, validation::validate_email};
+
+/// A string constant representing a redacted or masked value.
+pub const REDACTED: &str = "Redacted";
 
 /// Type alias for serde_json value which has Secret Information
-pub type SecretSerdeValue = masking::Secret<serde_json::Value>;
+pub type SecretSerdeValue = Secret<serde_json::Value>;
 
 /// Card number
 #[derive(Debug)]
@@ -87,26 +99,73 @@ where
     }
 }
 
-/// Email address
+/// Strategy for masking Email
 #[derive(Debug)]
-pub struct Email;
+pub struct EmailStrategy;
 
-impl<T> Strategy<T> for Email
+impl<T> Strategy<T> for EmailStrategy
 where
-    T: AsRef<str>,
+    T: AsRef<str> + std::fmt::Debug,
 {
     fn fmt(val: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let val_str: &str = val.as_ref();
-        let is_valid = validate_email(val_str);
-
-        if is_valid.is_err() {
-            return WithType::fmt(val, f);
+        match val_str.split_once('@') {
+            Some((a, b)) => write!(f, "{}@{}", "*".repeat(a.len()), b),
+            None => WithType::fmt(val, f),
         }
+    }
+}
+/// Email address
+#[derive(
+    serde::Serialize,
+    serde::Deserialize,
+    Debug,
+    Clone,
+    PartialEq,
+    Eq,
+    Default,
+    Queryable,
+    AsExpression,
+)]
+#[diesel(sql_type = diesel::sql_types::Text)]
+pub struct Email(Secret<String, EmailStrategy>);
+
+impl<DB> FromSql<sql_types::Text, DB> for Email
+where
+    DB: Backend,
+    String: FromSql<sql_types::Text, DB>,
+{
+    fn from_sql(bytes: backend::RawValue<'_, DB>) -> deserialize::Result<Self> {
+        let val = String::from_sql(bytes)?;
+        Ok(Self::from_str(val.as_str())?)
+    }
+}
+
+impl<DB> ToSql<sql_types::Text, DB> for Email
+where
+    DB: Backend,
+    String: ToSql<sql_types::Text, DB>,
+{
+    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
+        self.0.to_sql(out)
+    }
+}
 
-        if let Some((a, b)) = val_str.split_once('@') {
-            write!(f, "{}@{}", "*".repeat(a.len()), b)
-        } else {
-            WithType::fmt(val, f)
+impl FromStr for Email {
+    type Err = ValidationError;
+
+    fn from_str(email: &str) -> Result<Self, Self::Err> {
+        if email.eq(REDACTED) {
+            return Ok(Self(Secret::new(email.to_string())));
+        }
+        match validate_email(email) {
+            Ok(_) => {
+                let secret = Secret::<String, EmailStrategy>::new(email.to_string());
+                Ok(Self(secret))
+            }
+            Err(_) => Err(ValidationError::InvalidValue {
+                message: "Invalid email address format".into(),
+            }),
         }
     }
 }
@@ -139,9 +198,12 @@ where
 
 #[cfg(test)]
 mod pii_masking_strategy_tests {
-    use masking::Secret;
+    use std::str::FromStr;
+
+    use masking::{ExposeInterface, Secret};
 
     use super::{CardNumber, ClientSecret, Email, IpAddress};
+    use crate::pii::{EmailStrategy, REDACTED};
 
     #[test]
     fn test_valid_card_number_masking() {
@@ -152,7 +214,7 @@ mod pii_masking_strategy_tests {
     #[test]
     fn test_invalid_card_number_masking() {
         let secret: Secret<String, CardNumber> = Secret::new("1234567890".to_string());
-        assert_eq!("*** alloc::string::String ***", format!("{secret:?}",));
+        assert_eq!("*** alloc::string::String ***", format!("{secret:?}"));
     }
 
     /*
@@ -174,19 +236,46 @@ mod pii_masking_strategy_tests {
 
     #[test]
     fn test_valid_email_masking() {
-        let secret: Secret<String, Email> = Secret::new("myemail@gmail.com".to_string());
-        assert_eq!("*******@gmail.com", format!("{secret:?}"));
+        let secret: Secret<String, EmailStrategy> = Secret::new("example@test.com".to_string());
+        assert_eq!("*******@test.com", format!("{secret:?}"));
+
+        let secret: Secret<String, EmailStrategy> = Secret::new("username@gmail.com".to_string());
+        assert_eq!("********@gmail.com", format!("{secret:?}"));
     }
 
     #[test]
     fn test_invalid_email_masking() {
-        let secret: Secret<String, Email> = Secret::new("myemailgmail.com".to_string());
+        let secret: Secret<String, EmailStrategy> = Secret::new("myemailgmail.com".to_string());
         assert_eq!("*** alloc::string::String ***", format!("{secret:?}"));
 
-        let secret: Secret<String, Email> = Secret::new("myemail@gmail@com".to_string());
+        let secret: Secret<String, EmailStrategy> = Secret::new("myemail$gmail.com".to_string());
         assert_eq!("*** alloc::string::String ***", format!("{secret:?}"));
     }
 
+    #[test]
+    fn test_valid_newtype_email() {
+        let email_check: Result<Email, crate::errors::ValidationError> =
+            Email::from_str("example@abc.com");
+        assert!(email_check.is_ok());
+    }
+
+    #[test]
+    fn test_invalid_newtype_email() {
+        let email_check: Result<Email, crate::errors::ValidationError> =
+            Email::from_str("example@abc@com");
+        assert!(email_check.is_err());
+    }
+
+    #[test]
+    fn test_redacted_email() {
+        let email_result = Email::from_str(REDACTED);
+        assert!(email_result.is_ok());
+        if let Ok(email) = email_result {
+            let secret_value = email.0.expose();
+            assert_eq!(secret_value.as_str(), REDACTED);
+        }
+    }
+
     #[test]
     fn test_valid_ip_addr_masking() {
         let secret: Secret<String, IpAddress> = Secret::new("123.23.1.78".to_string());
diff --git a/crates/router/src/compatibility/stripe/customers/types.rs b/crates/router/src/compatibility/stripe/customers/types.rs
index b2ffb923c00..5d969d88cc7 100644
--- a/crates/router/src/compatibility/stripe/customers/types.rs
+++ b/crates/router/src/compatibility/stripe/customers/types.rs
@@ -1,14 +1,14 @@
 use std::{convert::From, default::Default};
 
 use api_models::payment_methods as api_types;
-use common_utils::{date_time, pii};
+use common_utils::{date_time, pii, pii::Email};
 use serde::{Deserialize, Serialize};
 
 use crate::{logger, types::api};
 
 #[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
 pub struct CreateCustomerRequest {
-    pub email: Option<masking::Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub invoice_prefix: Option<String>,
     pub name: Option<String>,
     pub phone: Option<masking::Secret<String>>,
@@ -20,7 +20,7 @@ pub struct CreateCustomerRequest {
 #[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
 pub struct CustomerUpdateRequest {
     pub description: Option<String>,
-    pub email: Option<masking::Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub phone: Option<masking::Secret<String, masking::WithType>>,
     pub name: Option<String>,
     pub address: Option<masking::Secret<serde_json::Value>>,
@@ -33,7 +33,7 @@ pub struct CreateCustomerResponse {
     pub object: String,
     pub created: u64,
     pub description: Option<String>,
-    pub email: Option<masking::Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub metadata: Option<pii::SecretSerdeValue>,
     pub name: Option<String>,
     pub phone: Option<masking::Secret<String, masking::WithType>>,
diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs
index 648170e5cf9..0046ae3eb17 100644
--- a/crates/router/src/compatibility/stripe/payment_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs
@@ -7,7 +7,7 @@ use crate::{
     compatibility::stripe::refunds::types as stripe_refunds,
     consts,
     core::errors,
-    pii::{self, PeekInterface},
+    pii::{self, Email, PeekInterface},
     types::{
         api::{admin, enums as api_enums},
         transformers::{ForeignFrom, ForeignInto},
@@ -17,7 +17,7 @@ use crate::{
 #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
 pub struct StripeBillingDetails {
     pub address: Option<payments::AddressDetails>,
-    pub email: Option<pii::Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub name: Option<String>,
     pub phone: Option<pii::Secret<String>>,
 }
@@ -133,7 +133,7 @@ pub struct StripePaymentIntentRequest {
     pub customer: Option<String>,
     pub description: Option<String>,
     pub payment_method_data: Option<StripePaymentMethodData>,
-    pub receipt_email: Option<pii::Secret<String, pii::Email>>,
+    pub receipt_email: Option<Email>,
     pub return_url: Option<url::Url>,
     pub setup_future_usage: Option<api_enums::FutureUsage>,
     pub shipping: Option<Shipping>,
@@ -299,7 +299,7 @@ pub struct StripePaymentIntentResponse {
     #[serde(with = "common_utils::custom_serde::iso8601::option")]
     pub capture_on: Option<time::PrimitiveDateTime>,
     pub payment_token: Option<String>,
-    pub email: Option<masking::Secret<String, common_utils::pii::Email>>,
+    pub email: Option<Email>,
     pub phone: Option<masking::Secret<String>>,
     pub statement_descriptor_suffix: Option<String>,
     pub statement_descriptor_name: Option<String>,
diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs
index 87f77220426..0279e36ac89 100644
--- a/crates/router/src/compatibility/stripe/setup_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs
@@ -12,7 +12,7 @@ use crate::{
 #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
 pub struct StripeBillingDetails {
     pub address: Option<payments::AddressDetails>,
-    pub email: Option<pii::Secret<String, pii::Email>>,
+    pub email: Option<pii::Email>,
     pub name: Option<String>,
     pub phone: Option<pii::Secret<String>>,
 }
@@ -114,7 +114,7 @@ pub struct StripeSetupIntentRequest {
     pub customer: Option<String>,
     pub description: Option<String>,
     pub payment_method_data: Option<StripePaymentMethodData>,
-    pub receipt_email: Option<pii::Secret<String, pii::Email>>,
+    pub receipt_email: Option<pii::Email>,
     pub return_url: Option<url::Url>,
     pub setup_future_usage: Option<api_enums::FutureUsage>,
     pub shipping: Option<Shipping>,
diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs
index 72ae3d0e5d1..e55e09bb076 100644
--- a/crates/router/src/connector/adyen/transformers.rs
+++ b/crates/router/src/connector/adyen/transformers.rs
@@ -105,7 +105,7 @@ pub struct AdyenPaymentRequest<'a> {
     store_payment_method: Option<bool>,
     shopper_name: Option<ShopperName>,
     shopper_locale: Option<String>,
-    shopper_email: Option<Secret<String, Email>>,
+    shopper_email: Option<Email>,
     telephone_number: Option<Secret<String>>,
     billing_address: Option<Address>,
     delivery_address: Option<Address>,
diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs
index 85377cc3fbf..a72d00ab41d 100644
--- a/crates/router/src/connector/cybersource/transformers.rs
+++ b/crates/router/src/connector/cybersource/transformers.rs
@@ -81,14 +81,14 @@ pub struct BillTo {
     administrative_area: Secret<String>,
     postal_code: Secret<String>,
     country: api_enums::CountryAlpha2,
-    email: Secret<String, pii::Email>,
+    email: pii::Email,
     phone_number: Secret<String>,
 }
 
 // for cybersource each item in Billing is mandatory
 fn build_bill_to(
     address_details: &payments::Address,
-    email: Secret<String, pii::Email>,
+    email: pii::Email,
     phone_number: Secret<String>,
 ) -> Result<BillTo, error_stack::Report<errors::ConnectorError>> {
     let address = address_details
diff --git a/crates/router/src/connector/dlocal/transformers.rs b/crates/router/src/connector/dlocal/transformers.rs
index c54fa3b31cf..f33b0b43c29 100644
--- a/crates/router/src/connector/dlocal/transformers.rs
+++ b/crates/router/src/connector/dlocal/transformers.rs
@@ -15,7 +15,7 @@ use crate::{
 #[derive(Debug, Default, Eq, PartialEq, Serialize)]
 pub struct Payer {
     pub name: Option<Secret<String>>,
-    pub email: Option<Secret<String, Email>>,
+    pub email: Option<Email>,
     pub document: Secret<String>,
 }
 
diff --git a/crates/router/src/connector/multisafepay/transformers.rs b/crates/router/src/connector/multisafepay/transformers.rs
index 34663924739..c5b71e6a266 100644
--- a/crates/router/src/connector/multisafepay/transformers.rs
+++ b/crates/router/src/connector/multisafepay/transformers.rs
@@ -105,7 +105,7 @@ pub struct Customer {
     pub state: Option<String>,
     pub country: Option<String>,
     pub phone: Option<String>,
-    pub email: Option<Secret<String, Email>>,
+    pub email: Option<Email>,
     pub user_agent: Option<String>,
     pub referrer: Option<String>,
     pub reference: Option<String>,
@@ -121,7 +121,7 @@ pub struct GatewayInfo {
     pub flexible_3d: Option<bool>,
     pub moto: Option<bool>,
     pub term_url: Option<String>,
-    pub email: Option<Secret<String, Email>>,
+    pub email: Option<Email>,
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs
index b80c599db21..06a11724c5b 100644
--- a/crates/router/src/connector/nuvei/transformers.rs
+++ b/crates/router/src/connector/nuvei/transformers.rs
@@ -66,7 +66,7 @@ pub struct NuveiPaymentsRequest {
     pub amount: String,
     pub currency: storage_models::enums::Currency,
     /// This ID uniquely identifies your consumer/user in your system.
-    pub user_token_id: Option<Secret<String, Email>>,
+    pub user_token_id: Option<Email>,
     pub client_unique_id: String,
     pub transaction_type: TransactionType,
     pub is_rebilling: Option<String>,
@@ -183,7 +183,7 @@ pub enum AlternativePaymentMethodType {
 #[derive(Debug, Clone, Default, Serialize, Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct BillingAddress {
-    pub email: Option<Secret<String, Email>>,
+    pub email: Email,
     pub first_name: Option<Secret<String>>,
     pub last_name: Option<Secret<String>>,
     pub country: api_models::enums::CountryAlpha2,
@@ -497,7 +497,7 @@ impl<F>
         let (billing_address, bank_id) = match (&payment_method, redirect) {
             (AlternativePaymentMethodType::Expresscheckout, _) => (
                 Some(BillingAddress {
-                    email: Some(item.request.get_email()?),
+                    email: item.request.get_email()?,
                     country: item.get_billing_country()?,
                     ..Default::default()
                 }),
@@ -505,7 +505,7 @@ impl<F>
             ),
             (AlternativePaymentMethodType::Giropay, _) => (
                 Some(BillingAddress {
-                    email: Some(item.request.get_email()?),
+                    email: item.request.get_email()?,
                     country: item.get_billing_country()?,
                     ..Default::default()
                 }),
@@ -517,7 +517,7 @@ impl<F>
                     Some(BillingAddress {
                         first_name: Some(address.get_first_name()?.clone()),
                         last_name: Some(address.get_last_name()?.clone()),
-                        email: Some(item.request.get_email()?),
+                        email: item.request.get_email()?,
                         country: item.get_billing_country()?,
                     }),
                     None,
@@ -532,7 +532,7 @@ impl<F>
                     Some(BillingAddress {
                         first_name: Some(address.get_first_name()?.clone()),
                         last_name: Some(address.get_last_name()?.clone()),
-                        email: Some(item.request.get_email()?),
+                        email: item.request.get_email()?,
                         country: item.get_billing_country()?,
                     }),
                     Some(NuveiBIC::try_from(bank_name)?),
diff --git a/crates/router/src/connector/shift4/transformers.rs b/crates/router/src/connector/shift4/transformers.rs
index 4baf9882d1d..6931a91d1ea 100644
--- a/crates/router/src/connector/shift4/transformers.rs
+++ b/crates/router/src/connector/shift4/transformers.rs
@@ -76,7 +76,7 @@ pub struct PaymentMethod {
 #[derive(Debug, Serialize)]
 pub struct Billing {
     name: Option<Secret<String>>,
-    email: Option<Secret<String, pii::Email>>,
+    email: Option<pii::Email>,
     address: Option<Address>,
 }
 
diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs
index 6d203610ac8..2fbcdfbda5b 100644
--- a/crates/router/src/connector/stripe/transformers.rs
+++ b/crates/router/src/connector/stripe/transformers.rs
@@ -1,6 +1,6 @@
 use api_models::{self, enums as api_enums, payments};
 use base64::Engine;
-use common_utils::{errors::CustomResult, pii};
+use common_utils::{errors::CustomResult, pii, pii::Email};
 use error_stack::{IntoReport, ResultExt};
 use masking::{ExposeInterface, ExposeOptionInterface, Secret};
 use serde::{Deserialize, Serialize};
@@ -168,7 +168,7 @@ pub struct StripeTokenResponse {
 #[derive(Debug, Eq, PartialEq, Serialize)]
 pub struct CustomerRequest {
     pub description: Option<String>,
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub phone: Option<Secret<String>>,
     pub name: Option<String>,
 }
@@ -177,7 +177,7 @@ pub struct CustomerRequest {
 pub struct StripeCustomerResponse {
     pub id: String,
     pub description: Option<String>,
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub phone: Option<Secret<String>>,
     pub name: Option<String>,
 }
@@ -1512,7 +1512,7 @@ pub struct StripeShippingAddress {
 #[derive(Debug, Default, Eq, PartialEq, Serialize)]
 pub struct StripeBillingAddress {
     #[serde(rename = "payment_method_data[billing_details][email]")]
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     #[serde(rename = "payment_method_data[billing_details][address][country]")]
     pub country: Option<api_enums::CountryAlpha2>,
     #[serde(rename = "payment_method_data[billing_details][name]")]
diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs
index c3cbbc1090d..1a11e39d79e 100644
--- a/crates/router/src/connector/trustpay/transformers.rs
+++ b/crates/router/src/connector/trustpay/transformers.rs
@@ -130,7 +130,7 @@ pub struct PaymentRequestCards {
     #[serde(rename = "billing[postcode]")]
     pub billing_postcode: Secret<String>,
     #[serde(rename = "customer[email]")]
-    pub customer_email: Option<Secret<String, Email>>,
+    pub customer_email: Option<Email>,
     #[serde(rename = "customer[ipAddress]")]
     pub customer_ip_address: Option<std::net::IpAddr>,
     #[serde(rename = "browser[acceptHeader]")]
diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs
index c2c05df8b7a..e33139a9d35 100644
--- a/crates/router/src/connector/utils.rs
+++ b/crates/router/src/connector/utils.rs
@@ -155,7 +155,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
 
 pub trait PaymentsAuthorizeRequestData {
     fn is_auto_capture(&self) -> Result<bool, Error>;
-    fn get_email(&self) -> Result<Secret<String, Email>, Error>;
+    fn get_email(&self) -> Result<Email, Error>;
     fn get_browser_info(&self) -> Result<types::BrowserInformation, Error>;
     fn get_order_details(&self) -> Result<OrderDetails, Error>;
     fn get_card(&self) -> Result<api::Card, Error>;
@@ -174,7 +174,7 @@ impl PaymentsAuthorizeRequestData for types::PaymentsAuthorizeData {
             Some(_) => Err(errors::ConnectorError::CaptureMethodNotSupported.into()),
         }
     }
-    fn get_email(&self) -> Result<Secret<String, Email>, Error> {
+    fn get_email(&self) -> Result<Email, Error> {
         self.email.clone().ok_or_else(missing_field_err("email"))
     }
     fn get_browser_info(&self) -> Result<types::BrowserInformation, Error> {
diff --git a/crates/router/src/connector/worldline/transformers.rs b/crates/router/src/connector/worldline/transformers.rs
index 4b34d054315..cc7fc20079b 100644
--- a/crates/router/src/connector/worldline/transformers.rs
+++ b/crates/router/src/connector/worldline/transformers.rs
@@ -60,7 +60,7 @@ pub struct BillingAddress {
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct ContactDetails {
-    pub email_address: Option<Secret<String, Email>>,
+    pub email_address: Option<Email>,
     pub mobile_phone_number: Option<Secret<String>>,
 }
 
@@ -202,7 +202,7 @@ fn get_address(
 
 fn build_customer_info(
     payment_address: &types::PaymentAddress,
-    email: &Option<Secret<String, Email>>,
+    email: &Option<Email>,
 ) -> Result<Customer, error_stack::Report<errors::ConnectorError>> {
     let (billing, address) =
         get_address(payment_address).ok_or(errors::ConnectorError::MissingRequiredField {
diff --git a/crates/router/src/connector/zen/transformers.rs b/crates/router/src/connector/zen/transformers.rs
index c273743b24d..c8de11c556a 100644
--- a/crates/router/src/connector/zen/transformers.rs
+++ b/crates/router/src/connector/zen/transformers.rs
@@ -1,5 +1,6 @@
 use std::net::IpAddr;
 
+use common_utils::pii::Email;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
 
@@ -56,7 +57,7 @@ pub enum ZenPaymentChannels {
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct ZenCustomerDetails {
-    email: Secret<String, pii::Email>,
+    email: Email,
     ip: IpAddr,
 }
 
diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs
index 345245ab84f..09fd6af83fa 100644
--- a/crates/router/src/core/customers.rs
+++ b/crates/router/src/core/customers.rs
@@ -1,4 +1,6 @@
-use common_utils::ext_traits::ValueExt;
+use std::str::FromStr;
+
+use common_utils::{ext_traits::ValueExt, pii::Email};
 use error_stack::ResultExt;
 use router_env::{instrument, tracing};
 use storage_models::errors as storage_errors;
@@ -13,7 +15,7 @@ use crate::{
     routes::{metrics, AppState},
     services,
     types::{
-        api::customers::{self, CustomerRequestExt},
+        api::customers,
         storage::{self, enums},
     },
 };
@@ -24,9 +26,8 @@ pub const REDACTED: &str = "Redacted";
 pub async fn create_customer(
     db: &dyn StorageInterface,
     merchant_account: storage::MerchantAccount,
-    customer_data: customers::CustomerRequest,
+    mut customer_data: customers::CustomerRequest,
 ) -> RouterResponse<customers::CustomerResponse> {
-    let mut customer_data = customer_data.validate()?;
     let customer_id = &customer_data.customer_id;
     let merchant_id = &merchant_account.merchant_id;
     customer_data.merchant_id = merchant_id.to_owned();
@@ -201,7 +202,7 @@ pub async fn delete_customer(
 
     let updated_customer = storage::CustomerUpdate::Update {
         name: Some(REDACTED.to_string()),
-        email: Some(REDACTED.to_string().into()),
+        email: Email::from_str(REDACTED).ok(),
         phone: Some(REDACTED.to_string().into()),
         description: Some(REDACTED.to_string()),
         phone_country_code: Some(REDACTED.to_string()),
@@ -232,7 +233,6 @@ pub async fn update_customer(
     merchant_account: storage::MerchantAccount,
     update_customer: customers::CustomerRequest,
 ) -> RouterResponse<customers::CustomerResponse> {
-    let update_customer = update_customer.validate()?;
     //Add this in update call if customer can be updated anywhere else
     db.find_customer_by_customer_id_merchant_id(
         &update_customer.customer_id,
diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs
index 426fae223d8..a12070f7fab 100644
--- a/crates/router/src/core/payment_methods/transformers.rs
+++ b/crates/router/src/core/payment_methods/transformers.rs
@@ -1,4 +1,6 @@
-use common_utils::ext_traits::StringExt;
+use std::str::FromStr;
+
+use common_utils::{ext_traits::StringExt, pii::Email};
 use error_stack::ResultExt;
 #[cfg(feature = "kms")]
 use external_services::kms;
@@ -83,7 +85,7 @@ pub struct AddCardRequest<'a> {
     pub card_exp_month: Secret<String>,
     pub card_exp_year: Secret<String>,
     pub merchant_id: &'a str,
-    pub email_address: Option<Secret<String, pii::Email>>,
+    pub email_address: Option<Email>,
     pub name_on_card: Option<Secret<String>>,
     pub nickname: Option<String>,
 }
@@ -396,9 +398,12 @@ pub fn mk_add_card_request(
         card_exp_month: card.card_exp_month.clone(),
         card_exp_year: card.card_exp_year.clone(),
         merchant_id: locker_id,
-        email_address: Some("dummy@gmail.com".to_string().into()), //
-        name_on_card: Some("John Doe".to_string().into()),         // [#256]
-        nickname: Some("router".to_string()),                      //
+        email_address: match Email::from_str("dummy@gmail.com") {
+            Ok(email) => Some(email),
+            Err(_) => None,
+        }, //
+        name_on_card: Some("John Doe".to_string().into()), // [#256]
+        nickname: Some("router".to_string()),              //
     };
     let body = utils::Encode::<AddCardRequest<'_>>::url_encode(&add_card_req)
         .change_context(errors::VaultError::RequestEncodingFailed)?;
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 93c3b8f6da0..34d3e2aa060 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -7,8 +7,10 @@ pub mod transformers;
 use std::{fmt::Debug, marker::PhantomData, time::Instant};
 
 use api_models::payments::Metadata;
+use common_utils::pii::Email;
 use error_stack::{IntoReport, ResultExt};
 use futures::future::join_all;
+use masking::Secret;
 use router_env::{instrument, tracing};
 use time;
 
@@ -28,7 +30,7 @@ use crate::{
         payment_methods::vault,
     },
     db::StorageInterface,
-    logger, pii,
+    logger,
     routes::AppState,
     scheduler::utils as pt_utils,
     services::{self, api::Authenticate},
@@ -824,8 +826,8 @@ where
     pub payment_method_data: Option<api::PaymentMethodData>,
     pub refunds: Vec<storage::Refund>,
     pub sessions_token: Vec<api::SessionToken>,
-    pub card_cvc: Option<pii::Secret<String>>,
-    pub email: Option<masking::Secret<String, pii::Email>>,
+    pub card_cvc: Option<Secret<String>>,
+    pub email: Option<Email>,
     pub creds_identifier: Option<String>,
     pub pm_token: Option<String>,
     pub connector_customer_id: Option<String>,
@@ -834,9 +836,9 @@ where
 #[derive(Debug, Default)]
 pub struct CustomerDetails {
     pub customer_id: Option<String>,
-    pub name: Option<masking::Secret<String, masking::WithType>>,
-    pub email: Option<masking::Secret<String, pii::Email>>,
-    pub phone: Option<masking::Secret<String, masking::WithType>>,
+    pub name: Option<Secret<String, masking::WithType>>,
+    pub email: Option<Email>,
+    pub phone: Option<Secret<String, masking::WithType>>,
     pub phone_country_code: Option<String>,
 }
 
diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs
index 0c4c243a351..37efb5d0570 100644
--- a/crates/router/src/core/payments/operations/payment_session.rs
+++ b/crates/router/src/core/payments/operations/payment_session.rs
@@ -14,8 +14,7 @@ use crate::{
         payments::{self, helpers, operations, PaymentData},
     },
     db::StorageInterface,
-    logger, pii,
-    pii::Secret,
+    logger,
     routes::AppState,
     types::{
         api::{self, PaymentIdTypeExt},
@@ -153,7 +152,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest>
                 payment_attempt,
                 currency,
                 amount,
-                email: None::<Secret<String, pii::Email>>,
+                email: None,
                 mandate_id: None,
                 token: None,
                 setup_mandate: None,
diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs
index c5892806876..5a4fd81bb2b 100644
--- a/crates/router/src/core/payments/operations/payment_start.rs
+++ b/crates/router/src/core/payments/operations/payment_start.rs
@@ -12,8 +12,6 @@ use crate::{
         payments::{helpers, operations, CustomerDetails, PaymentAddress, PaymentData},
     },
     db::StorageInterface,
-    pii,
-    pii::Secret,
     routes::AppState,
     types::{
         api::{self, PaymentIdTypeExt},
@@ -124,7 +122,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsStartRequest> f
                 payment_intent,
                 currency,
                 amount,
-                email: None::<Secret<String, pii::Email>>,
+                email: None,
                 mandate_id: None,
                 connector_response,
                 setup_mandate: None,
diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs
index a799c9245b6..390dd379e64 100644
--- a/crates/router/src/types.rs
+++ b/crates/router/src/types.rs
@@ -190,7 +190,7 @@ pub struct RouterData<Flow, Request, Response> {
 pub struct PaymentsAuthorizeData {
     pub payment_method_data: payments::PaymentMethodData,
     pub amount: i64,
-    pub email: Option<masking::Secret<String, Email>>,
+    pub email: Option<Email>,
     pub currency: storage_enums::Currency,
     pub confirm: bool,
     pub statement_descriptor_suffix: Option<String>,
@@ -233,7 +233,7 @@ pub struct AuthorizeSessionTokenData {
 #[derive(Debug, Clone)]
 pub struct ConnectorCustomerData {
     pub description: Option<String>,
-    pub email: Option<masking::Secret<String, Email>>,
+    pub email: Option<Email>,
     pub phone: Option<masking::Secret<String>>,
     pub name: Option<String>,
 }
@@ -247,7 +247,7 @@ pub struct PaymentMethodTokenizationData {
 pub struct CompleteAuthorizeData {
     pub payment_method_data: Option<payments::PaymentMethodData>,
     pub amount: i64,
-    pub email: Option<masking::Secret<String, Email>>,
+    pub email: Option<Email>,
     pub currency: storage_enums::Currency,
     pub confirm: bool,
     pub statement_descriptor_suffix: Option<String>,
diff --git a/crates/router/src/types/api/customers.rs b/crates/router/src/types/api/customers.rs
index 6cd0edd7e14..904e223c126 100644
--- a/crates/router/src/types/api/customers.rs
+++ b/crates/router/src/types/api/customers.rs
@@ -1,39 +1,14 @@
 use api_models::customers;
 pub use api_models::customers::{CustomerDeleteResponse, CustomerId, CustomerRequest};
-use error_stack::ResultExt;
 use serde::Serialize;
 
-use crate::{
-    core::errors::{self, RouterResult},
-    newtype,
-    pii::PeekInterface,
-    types::storage,
-    utils::{self, ValidateCall},
-};
+use crate::{newtype, types::storage};
 
 newtype!(
     pub CustomerResponse = customers::CustomerResponse,
     derives = (Debug, Clone, Serialize)
 );
 
-pub(crate) trait CustomerRequestExt: Sized {
-    fn validate(self) -> RouterResult<Self>;
-}
-
-impl CustomerRequestExt for CustomerRequest {
-    fn validate(self) -> RouterResult<Self> {
-        self.email
-            .as_ref()
-            .validate_opt(|email| utils::validate_email(email.peek()))
-            .change_context(errors::ApiErrorResponse::InvalidDataFormat {
-                field_name: "email".to_string(),
-                expected_format: "valid email address".to_string(),
-            })?;
-
-        Ok(self)
-    }
-}
-
 impl From<storage::Customer> for CustomerResponse {
     fn from(cust: storage::Customer) -> Self {
         customers::CustomerResponse {
diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs
index 3395f6a7ead..297a27ff662 100644
--- a/crates/router/tests/connectors/cybersource.rs
+++ b/crates/router/tests/connectors/cybersource.rs
@@ -1,3 +1,6 @@
+use std::str::FromStr;
+
+use common_utils::pii::Email;
 use masking::Secret;
 use router::types::{
     self, api,
@@ -58,7 +61,7 @@ fn get_default_payment_info() -> Option<utils::PaymentInfo> {
 fn get_default_payment_authorize_data() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         currency: storage::enums::Currency::USD,
-        email: Some(Secret::new("abc@gmail.com".to_string())),
+        email: Some(Email::from_str("abc@gmail.com").unwrap()),
         ..PaymentAuthorizeType::default().0
     })
 }
diff --git a/crates/router/tests/connectors/zen.rs b/crates/router/tests/connectors/zen.rs
index 11af6514d9e..4130a73990c 100644
--- a/crates/router/tests/connectors/zen.rs
+++ b/crates/router/tests/connectors/zen.rs
@@ -1,4 +1,7 @@
+use std::str::FromStr;
+
 use api_models::payments::OrderDetails;
+use common_utils::pii::Email;
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -304,7 +307,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
                     product_name: "test".to_string(),
                     quantity: 1,
                 }),
-                email: Some(Secret::new("test@gmail.com".to_string())),
+                email: Some(Email::from_str("test@gmail.com").unwrap()),
                 webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()),
                 ..utils::PaymentAuthorizeType::default().0
             }),
@@ -338,7 +341,7 @@ async fn should_fail_payment_for_empty_card_number() {
                     product_name: "test".to_string(),
                     quantity: 1,
                 }),
-                email: Some(Secret::new("test@gmail.com".to_string())),
+                email: Some(Email::from_str("test@gmail.com").unwrap()),
                 webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()),
                 ..utils::PaymentAuthorizeType::default().0
             }),
@@ -367,7 +370,7 @@ async fn should_fail_payment_for_incorrect_cvc() {
                     product_name: "test".to_string(),
                     quantity: 1,
                 }),
-                email: Some(Secret::new("test@gmail.com".to_string())),
+                email: Some(Email::from_str("test@gmail.com").unwrap()),
                 webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()),
                 ..utils::PaymentAuthorizeType::default().0
             }),
@@ -401,7 +404,7 @@ async fn should_fail_payment_for_invalid_exp_month() {
                     product_name: "test".to_string(),
                     quantity: 1,
                 }),
-                email: Some(Secret::new("test@gmail.com".to_string())),
+                email: Some(Email::from_str("test@gmail.com").unwrap()),
                 webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()),
                 ..utils::PaymentAuthorizeType::default().0
             }),
@@ -435,7 +438,7 @@ async fn should_fail_payment_for_incorrect_expiry_year() {
                     product_name: "test".to_string(),
                     quantity: 1,
                 }),
-                email: Some(Secret::new("test@gmail.com".to_string())),
+                email: Some(Email::from_str("test@gmail.com").unwrap()),
                 webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()),
                 ..utils::PaymentAuthorizeType::default().0
             }),
diff --git a/crates/storage_models/src/customers.rs b/crates/storage_models/src/customers.rs
index 6f9bb379ba8..ea4154bdd60 100644
--- a/crates/storage_models/src/customers.rs
+++ b/crates/storage_models/src/customers.rs
@@ -1,4 +1,4 @@
-use common_utils::pii;
+use common_utils::{pii, pii::Email};
 use diesel::{AsChangeset, Identifiable, Insertable, Queryable};
 use masking::Secret;
 use time::PrimitiveDateTime;
@@ -11,7 +11,7 @@ pub struct CustomerNew {
     pub customer_id: String,
     pub merchant_id: String,
     pub name: Option<String>,
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub phone: Option<Secret<String>>,
     pub description: Option<String>,
     pub phone_country_code: Option<String>,
@@ -26,7 +26,7 @@ pub struct Customer {
     pub customer_id: String,
     pub merchant_id: String,
     pub name: Option<String>,
-    pub email: Option<Secret<String, pii::Email>>,
+    pub email: Option<Email>,
     pub phone: Option<Secret<String>>,
     pub phone_country_code: Option<String>,
     pub description: Option<String>,
@@ -40,7 +40,7 @@ pub struct Customer {
 pub enum CustomerUpdate {
     Update {
         name: Option<String>,
-        email: Option<Secret<String, pii::Email>>,
+        email: Option<Email>,
         phone: Option<Secret<String>>,
         description: Option<String>,
         phone_country_code: Option<String>,
@@ -56,7 +56,7 @@ pub enum CustomerUpdate {
 #[diesel(table_name = customers)]
 pub struct CustomerUpdateInternal {
     name: Option<String>,
-    email: Option<Secret<String, pii::Email>>,
+    email: Option<Email>,
     phone: Option<Secret<String>>,
     description: Option<String>,
     phone_country_code: Option<String>,

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [x] Enhancement
- [ ] Refactoring
- [ ] Dependency updates

## Description
<!-- Describe your changes in detail -->
- This fixes #608 
- Added testcases

### Additional Changes

- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!-- 
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless its an obvious bug or documentation fix
that will have little conversation).
-->
#608 


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
- ran `cargo test`
- Added 2 unit testcases for validation of implemented code
- ![img](https://user-images.githubusercontent.com/44920607/229088949-12df2834-8778-44fc-94a5-fbaadbe3d6ad.png)


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed submitted code
- [x] I added unit tests for my changes where possible
- [x] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
