# Email Redirection in Multi-Frontend Structure

This guide describes the configuration required to enable frontend-aware email redirection in a Commerce environment with multiple frontend domains. In multi-tenant or multi-regional setups, users must receive emails with redirect links that point to the appropriate frontend based on their original interaction. This feature ensures that all links in transactional emails are correctly generated per the frontend that initiated the request.

In a traditional setup, email templates generate links using a static domain or path. In projects supporting multiple frontends (e.g., UAE, Kuwait), this approach causes inconsistencies, potentially redirecting users to the wrong site. For example, a user interacting with `example.com/ae` might receive an email containing a link to `example.com/kw`.

With this feature, frontend identification is embedded in each request via a custom header. The backend reads this information and uses it to generate the correct domain and path in email templates.

## <mark style="color:red;">**How It Works**</mark>

1. **Frontend Identification**: Every API request includes an `x-frontend-id` header that specifies which frontend initiated the request.
2. **Backend Context Injection**: A custom account adapter captures this header and injects it into the template rendering context.
3. **Email Template Logic**: The email template uses this context or fallback values from the user profile to determine the appropriate domain path.
4. **URL Generation**: Email links are constructed dynamically, resulting in accurate redirection per user.

## <mark style="color:red;">**Commerce Configuration**</mark>

### <mark style="color:red;">**1. Custom Account Adapter**</mark>

To support frontend-aware context in all authentication operations (user registration, password reset, etc.), a custom account adapter must be used:

```py
ACCOUNT_ADAPTER = 'omnishop.users.allauth_adapter.CustomDefaultAccountAdapter'
```

The `CustomDefaultAccountAdapter` reads the `x-frontend-id` from incoming HTTP requests and passes it as `frontend_id` in the rendering context. This makes it available within email templates and other processes requiring frontend-aware logic.

{% hint style="warning" %}
If you already have a custom adapter, make sure it inherits from or incorporates the same logic as `CustomDefaultAccountAdapter`.
{% endhint %}

### <mark style="color:red;">**2. Valid Frontend IDs Setting**</mark>

The `VALID_FRONTEND_IDS` configuration defines all acceptable frontend identifiers used by the system. It prevents invalid or unknown frontend values from affecting link generation.

This setting is managed via dynamic settings and must follow the structure below:

```python
VALID_FRONTEND_IDS = [
    {"id": "1", "name": "Kuwait Frontend"},
    {"id": "2x", "name": "UAE Frontend"},
    // Additional frontend entries
]
```

**Field Definitions:**

* `id`: A unique string identifier (CharField) sent by the frontend in the `x-frontend-id` header. It is used for routing and URL generation.
* `name`: A human-readable name for distinguishing frontend entries in configuration UIs. Not used in logic.

{% hint style="warning" %}
If an unknown or undefined `id` is provided, the backend will treat the `frontend_id` as `None`, which may affect the resulting URL paths in email templates.
{% endhint %}

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-adbbbf30338f62e71dda98c6fbaf3962a12d1290%2Fimage.png?alt=media" alt="" width="375"><figcaption></figcaption></figure>

## <mark style="color:red;">**User Schema Configuration in Omnitron**</mark>

To persist the user’s frontend source, the `frontend_id` field must be added to the `user` schema in Omnitron. This allows email redirection logic to work even when the email is triggered by an external system (e.g., Omnitron).

### <mark style="color:red;">**Add**</mark><mark style="color:red;">**&#x20;**</mark><mark style="color:red;">**`frontend_id`**</mark><mark style="color:red;">**&#x20;**</mark><mark style="color:red;">**to the User Schema**</mark>

```bash
curl --location --request PUT 'https://{omnitron_url}/api/v1/remote/1/schema_types/user/' \
--header 'authorization: Token YOUR_API_TOKEN_HERE' \
--header 'Content-Type: application/json' \
--data '{
   "schema": {
       "frontend_id": {
           "required": false,
           "data_type": "text",
           "key": "frontend_id",
           "label": "Frontend ID"
       }
       // include the rest of the schema as-is
   }
}'
```

**Behavior:**

* When a user registers or makes an authenticated request from the frontend, the `x-frontend-id` value is automatically recorded in the user object under `user.attributes.frontend_id`.
* This value becomes available in all contexts where user attributes are accessible, such as email templates triggered outside of the Commerce backend.

## <mark style="color:red;">**Frontend Implementation**</mark>

Every frontend application that sends API requests to the backend must include the `x-frontend-id` HTTP header.

```makefile
x-frontend-id: 1
```

This value must match one of the defined entries in the `VALID_FRONTEND_IDS` list. If it does not, backend logic will treat the frontend as undefined for email redirection purposes.

**API Request Example:**

Here is an example password reset request from a frontend application:

```bash
curl --location 'https://{commerce_url}/users/password/reset/' \
--header 'x-frontend-id: 1' \
--header 'Content-Type: application/json' \
--data-raw '{
    "email": "example@example.com"
}'
```

In this request, `x-frontend-id: 1` indicates the request originates from the Kuwait frontend, and links in the email will be tailored accordingly.

## <mark style="color:red;">**Email Template Implementation**</mark>

To generate frontend-aware links in email templates, use both the incoming `frontend_id` from context and the fallback stored in `user.attributes.frontend_id`.

**Example Snippet:**

```python
{# Get frontend ID from context or fallback to user attribute #}
{% set x_frontend_id = frontend_id or user.attributes.get("frontend_id") %}

{# Define dynamic path based on frontend ID #}
{% if x_frontend_id == "1" %}
    {% set dynamic_path = "/frontend_id_1" %}
{% elif x_frontend_id == "2x" %}
    {% set dynamic_path = "/frontend_id_2" %}
{% else %}
   {% set dynamic_path = "/defualt" %}
{% endif %}

{# Construct the final confirmation URL #}
{% set confirm_url = "https://" + current_site.domain + dynamic_path + url('account_confirm_email', key=key) %}

<a href="{{ confirm_url }}">{{ confirm_url }}</a>
```

**Template Variables Explained:**

* `frontend_id`: Retrieved from the incoming request context, if available.
* `user.attributes.get("frontend_id")`: Fallback value stored in the user schema, typically used when the email is triggered by the other system (e.g., Omnitron).
* `dynamic_path`: A frontend-specific prefix that adjusts the final URL path. Dynamically determined based on the identified `frontend_id`.
  * If neither `frontend_id` from context nor `user.attributes.frontend_id` is available, a default path (`/default`) is applied to avoid broken URLs and ensure graceful degradation.
* `confirm_url`: Final redirect URL combining domain, path, and endpoint.

{% hint style="warning" %}
To ensure robustness and prevent misrouted or invalid links in email templates, a fallback block should be explicitly defined in the template logic as shown below:

```python
{% else %}
    {% set dynamic_path = "/default" %}
{% endif %}
```

{% endhint %}
