diff --git a/met-api/sample.env b/met-api/sample.env index a93566cb2..11673abe9 100644 --- a/met-api/sample.env +++ b/met-api/sample.env @@ -146,4 +146,8 @@ EPIC_JWT_OIDC_ISSUER= EPIC_KC_CLIENT_ID= EPIC_MILESTONE= EPIC_KEYCLOAK_SERVICE_ACCOUNT_ID= -EPIC_KEYCLOAK_SERVICE_ACCOUNT_SECRET= \ No newline at end of file +EPIC_KEYCLOAK_SERVICE_ACCOUNT_SECRET= + +# If enabled, all emails will be send only to the internal email address set in constant INTERNAL_EMAIL_DOMAIN +# such as `@gov.bc.ca` . Mainly used for dev and test environments. +SEND_EMAIL_INTERNAL_ONLY=false \ No newline at end of file diff --git a/met-api/src/met_api/config.py b/met-api/src/met_api/config.py index c15bd8f3b..0cb3b9f5e 100644 --- a/met-api/src/met_api/config.py +++ b/met-api/src/met_api/config.py @@ -169,6 +169,10 @@ def SQLALCHEMY_DATABASE_URI(self) -> str: # Adjust this value based on security considerations. CORS_MAX_AGE = os.getenv('CORS_MAX_AGE', None) # Default: 0 seconds + # If enabled, Emails will be send onlt to the internal email address set in constant INTERNAL_EMAIL_DOMAIN + # such as `@gov.bc.ca` . Mainly used for dev and test environments. + SEND_EMAIL_INTERNAL_ONLY = env_truthy('SEND_EMAIL_INTERNAL_ONLY', default=False) + EPIC_CONFIG = { 'ENABLED': env_truthy('EPIC_INTEGRATION_ENABLED'), 'JWT_OIDC_ISSUER': os.getenv('EPIC_JWT_OIDC_ISSUER'), diff --git a/met-api/src/met_api/utils/notification.py b/met-api/src/met_api/utils/notification.py index 27a2e96e4..0c420845e 100644 --- a/met-api/src/met_api/utils/notification.py +++ b/met-api/src/met_api/utils/notification.py @@ -4,9 +4,13 @@ import re import requests + +from http import HTTPStatus from flask import current_app from met_api.models.tenant import Tenant from met_api.services.rest_service import RestService +from met_api.constants.email_verification import INTERNAL_EMAIL_DOMAIN +from met_api.exceptions.business_exception import BusinessException def get_tenant_site_url(tenant_id, path=''): @@ -28,6 +32,9 @@ def send_email(subject, email, html_body, args, template_id): if not email or not is_valid_email(email): return + if not is_allowed_email(email): + raise ValueError('The email provided is not allowed in this environement.') + sender = current_app.config['EMAIL_TEMPLATES']['FROM_ADDRESS'] service_account_token = RestService.get_service_account_token() send_email_endpoint = current_app.config.get('NOTIFICATIONS_EMAIL_ENDPOINT') @@ -53,3 +60,9 @@ def is_valid_email(email: str): if email: return re.match(r'[^@]+@[^@]+\.[^@]+', email) is not None return False + + +def is_allowed_email(email: str): + """Return if the email is allowed or not if send_email_internal_only is enabled.""" + send_email_internal_only = current_app.config.get('SEND_EMAIL_INTERNAL_ONLY') + return not send_email_internal_only or (email and email.endswith(INTERNAL_EMAIL_DOMAIN)) diff --git a/openshift/api.dc.yml b/openshift/api.dc.yml index 395bd8230..4a3b19029 100644 --- a/openshift/api.dc.yml +++ b/openshift/api.dc.yml @@ -226,6 +226,7 @@ objects: KEYCLOAK_REALMNAME: ${KEYCLOAK_REALMNAME} KEYCLOAK_BASE_URL: ${KEYCLOAK_BASE_URL} KEYCLOAK_ADMIN_TOKEN_URL: ${KEYCLOAK_ADMIN_TOKEN_URL} + SEND_EMAIL_INTERNAL_ONLY: ${SEND_EMAIL_INTERNAL_ONLY} - kind: Secret apiVersion: v1 type: Opaque @@ -404,6 +405,10 @@ parameters: description: "Keycloak url to get admin token" required: true value: '' + - name: SEND_EMAIL_INTERNAL_ONLY + description: "Send Email only to internal email ids" + required: false + value: '' - name: CDOGS_BASE_URL description: "Base url to access CDOGS" required: true