Skip to content

Commit 9f6868a

Browse files
committed
+password changed email
1 parent 5d91432 commit 9f6868a

File tree

5 files changed

+123
-0
lines changed

5 files changed

+123
-0
lines changed

py/core/base/providers/email.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class EmailConfig(ProviderConfig):
1919
reset_password_template_id: Optional[str] = None
2020
frontend_url: Optional[str] = None
2121
sender_name: Optional[str] = None
22+
password_changed_template_id: Optional[str] = None
2223

2324
@property
2425
def supported_providers(self) -> list[str]:
@@ -74,3 +75,12 @@ async def send_password_reset_email(
7475
self, to_email: str, reset_token: str, *args, **kwargs
7576
) -> None:
7677
pass
78+
79+
@abstractmethod
80+
async def send_password_changed_email(
81+
self,
82+
to_email: str,
83+
*args,
84+
**kwargs,
85+
) -> None:
86+
pass

py/core/providers/auth/r2r_auth.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,14 @@ async def change_password(
392392
id=user.id,
393393
new_hashed_password=hashed_new_password,
394394
)
395+
396+
try:
397+
await self.email_provider.send_password_change_notification(
398+
user.email, {"first_name": user.name.split(" ")[0]}
399+
)
400+
except Exception as e:
401+
logger.error(f"Failed to send password change notification: {str(e)}")
402+
395403
return {"message": "Password changed successfully"}
396404

397405
async def request_password_reset(self, email: str) -> dict[str, str]:
@@ -447,9 +455,22 @@ async def confirm_password_reset(
447455
id=user_id,
448456
new_hashed_password=hashed_new_password,
449457
)
458+
450459
await self.database_provider.users_handler.remove_reset_token(
451460
id=user_id
452461
)
462+
463+
# Get the user information
464+
user = await self.database_provider.users_handler.get_user_by_id(
465+
id=user_id
466+
)
467+
logger.info(user)
468+
try:
469+
await self.email_provider.send_password_changed_email(
470+
user.email, {"first_name": user.name.split(" ")[0]}
471+
)
472+
except Exception as e:
473+
logger.error(f"Failed to send password change notification: {str(e)}")
453474
return {"message": "Password reset successfully"}
454475

455476
async def logout(self, token: str) -> dict[str, str]:

py/core/providers/email/console_mock.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,19 @@ async def send_password_reset_email(
5656
-----------------------------
5757
"""
5858
)
59+
60+
async def send_password_changed_email(
61+
self, to_email: str, *args, **kwargs
62+
) -> None:
63+
logger.info(
64+
f"""
65+
-------- Email Message --------
66+
To: {to_email}
67+
Subject: Your Password Has Been Changed
68+
Body:
69+
Your password has been successfully changed.
70+
71+
For security reasons, you will need to log in again on all your devices.
72+
-----------------------------
73+
"""
74+
)

py/core/providers/email/sendgrid.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ def __init__(self, config: EmailConfig):
3737
config.reset_password_template_id
3838
or os.getenv("SENDGRID_RESET_TEMPLATE_ID")
3939
)
40+
self.password_changed_template_id = (
41+
config.password_changed_template_id
42+
or os.getenv("SENDGRID_PASSWORD_CHANGED_TEMPLATE_ID")
43+
)
4044
self.client = SendGridAPIClient(api_key=self.api_key)
4145
self.sender_name = config.sender_name
4246

@@ -208,3 +212,46 @@ async def send_password_reset_email(
208212
)
209213
logger.error(error_msg)
210214
raise RuntimeError(error_msg) from e
215+
216+
async def send_password_changed_email(
217+
self,
218+
to_email: str,
219+
dynamic_template_data: Optional[dict] = None,
220+
*args,
221+
**kwargs
222+
) -> None:
223+
try:
224+
if hasattr(self, 'password_changed_template_id') and self.password_changed_template_id:
225+
await self.send_email(
226+
to_email=to_email,
227+
template_id=self.password_changed_template_id,
228+
dynamic_template_data=dynamic_template_data,
229+
)
230+
else:
231+
subject = "Your Password Has Been Changed"
232+
body = """
233+
Your password has been successfully changed.
234+
235+
If you did not make this change, please contact support immediately and secure your account.
236+
237+
For security reasons, you will need to log in again on all your devices.
238+
"""
239+
html_body = """
240+
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
241+
<h1>Password Changed Successfully</h1>
242+
<p>Your password has been successfully changed.</p>
243+
244+
<p>For security reasons, you will need to log in again on all your devices.</p>
245+
</div>
246+
"""
247+
# Move send_email inside the else block
248+
await self.send_email(
249+
to_email=to_email,
250+
subject=subject,
251+
html_body=html_body,
252+
body=body,
253+
)
254+
except Exception as e:
255+
error_msg = f"Failed to send password change notification to {to_email}: {str(e)}"
256+
logger.error(error_msg)
257+
raise RuntimeError(error_msg) from e

py/core/providers/email/smtp.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,32 @@ async def send_password_reset_email(
150150
body=body,
151151
html_body=html_body,
152152
)
153+
154+
async def send_password_changed_email(
155+
self,
156+
to_email: str,
157+
*args,
158+
**kwargs
159+
) -> None:
160+
body = """
161+
Your password has been successfully changed.
162+
163+
If you did not make this change, please contact support immediately and secure your account.
164+
165+
For security reasons, you will need to log in again on all your devices.
166+
"""
167+
168+
html_body = """
169+
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
170+
<h1>Password Changed Successfully</h1>
171+
<p>Your password has been successfully changed.</p>
172+
<p>For security reasons, you will need to log in again on all your devices.</p>
173+
</div>
174+
"""
175+
176+
await self.send_email(
177+
to_email=to_email,
178+
subject="Your Password Has Been Changed",
179+
body=body,
180+
html_body=html_body,
181+
)

0 commit comments

Comments
 (0)