diff --git a/mxgo/api.py b/mxgo/api.py index e5db0f4..6a49f1d 100644 --- a/mxgo/api.py +++ b/mxgo/api.py @@ -135,9 +135,9 @@ async def lifespan(_app: FastAPI): ALLOWED_ORIGINS_DEV = [ "http://localhost", - "http://localhost:8080", + "http://localhost:5173", "http://127.0.0.1", - "http://127.0.0.1:8080", + "http://127.0.0.1:5173", ] app.add_middleware( @@ -1044,7 +1044,7 @@ async def _handle_post_creation_action( logger.info(f"User {user_email} is not whitelisted. Triggering verification.") try: - await whitelist.trigger_automatic_verification(user_email) + await whitelist.trigger_newsletter_verification(user_email) except Exception as e: logger.error(f"Error triggering whitelist verification for {user_email}: {e}") return False diff --git a/mxgo/whitelist.py b/mxgo/whitelist.py index 8494f90..45c4eb4 100644 --- a/mxgo/whitelist.py +++ b/mxgo/whitelist.py @@ -256,6 +256,164 @@ async def send_verification_email(email: str, verification_token: str) -> bool: return True +async def trigger_newsletter_verification(email: str) -> bool: + """ + Automatically trigger email verification for non-whitelisted newsletter users. + + This function is a variant of trigger_automatic_verification but uses + Knowsletter branding for the verification email. + + Args: + email: The email address to verify. + + Returns: + bool: True if the verification process was successfully triggered, False otherwise. + + """ + try: + if not supabase: + init_supabase() + + verification_token = str(uuid.uuid4()) + current_time = datetime.now(timezone.utc).isoformat() + + existing_response = supabase.table("whitelisted_emails").select("*").eq("email", email).execute() + + if hasattr(existing_response, "data") and len(existing_response.data) > 0: + update_response = ( + supabase.table("whitelisted_emails") + .update({"verification_token": verification_token, "verified": False, "updated_at": current_time}) + .eq("email", email) + .execute() + ) + if not (hasattr(update_response, "data") and len(update_response.data) > 0): + logger.error(f"Failed to update verification token for {email}") + return False + else: + insert_response = ( + supabase.table("whitelisted_emails") + .insert( + { + "email": email, + "verified": False, + "verification_token": verification_token, + "created_at": current_time, + "updated_at": current_time, + } + ) + .execute() + ) + if not (hasattr(insert_response, "data") and len(insert_response.data) > 0): + logger.error(f"Failed to insert verification record for {email}") + return False + + verification_sent = await send_newsletter_verification_email(email, verification_token) + + if verification_sent: + logger.info(f"Successfully triggered newsletter verification for {email}") + else: + logger.error(f"Failed to send newsletter verification email to {email}") + + return verification_sent # noqa: TRY300 + except Exception as e: + logger.error(f"Error triggering newsletter verification for {email}: {e}") + return False + + +async def send_newsletter_verification_email(email: str, verification_token: str) -> bool: + """ + Send verification email using SES email sender with 'Knowsletter' branding. + This is a branded version of the standard send_verification_email function. + """ + try: + # Get the origin URL for verification links + origin = os.getenv("FRONTEND_URL", "https://mxgo.ai") + verification_url = f"{origin}/verify?token={verification_token}" + + subject = "Verify your email for Knowsletter" + sender_email = "knowsletter@mxgo.ai" + + text_content = f"""Welcome to Knowsletter by MXGo.ai! + +To activate your newsletter subscription and start receiving updates, please verify your email address by clicking the link below: + +{verification_url} + +This verification link will expire in 24 hours for security reasons. + +If you didn't request this verification, you can safely ignore this email. + +Best regards, +The Knowsletter Team + +--- +Knowsletter by MXGo.ai - Curated news, powered by AI +https://mxgo.ai""" + + html_content = f""" + + + + Verify your email - Knowsletter by MXGo.ai + + + +
+
+

Welcome to Knowsletter by MXGo.ai!

+
+
+

Verify your email address

+

To activate your newsletter subscription and start receiving updates, please verify your email address by clicking the button below:

+ +
+ Verify Email for Knowsletter +
+ +

Or copy and paste this link into your browser:

+

{verification_url}

+ +
+ ⏰ Important: This verification link will expire in 24 hours for security reasons. +
+ +

If you didn't request this verification, you can safely ignore this email.

+ +

Best regards,
+ The Knowsletter Team

+
+ +
+ +""" + + # Initialize email sender and send verification email + email_sender = EmailSender() + response = await email_sender.send_email( + to_address=email, subject=subject, body_text=text_content, body_html=html_content, sender_email=sender_email + ) + + logger.info( + f"Knowsletter verification email sent successfully to {email}: {response.get('MessageId', 'Unknown')}" + ) + return True # noqa: TRY300 + + except Exception as e: + logger.error(f"Error sending Knowsletter verification email to {email}: {e}") + return False + + def get_whitelist_signup_url() -> str: """ Get the URL where users can sign up to be whitelisted diff --git a/tests/test_api.py b/tests/test_api.py index 2c27d9f..5593187 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1313,7 +1313,7 @@ def test_create_newsletter_not_whitelisted(self, mock_dependencies, client_with_ mock_dependencies["is_whitelisted"].return_value = (False, False) jwt_token = generate_test_jwt(email="test@example.com", user_id="test_user_123") - with patch("mxgo.api.whitelist.trigger_automatic_verification", new_callable=AsyncMock) as mock_trigger_verify: + with patch("mxgo.api.whitelist.trigger_newsletter_verification", new_callable=AsyncMock) as mock_trigger_verify: response = client_with_patched_redis.post( "/create-newsletter", headers={"Authorization": f"Bearer {jwt_token}"},