-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[LLSC-20] Implement Skeleton Email Service (#6)
## Notion ticket link <!-- Please replace with your ticket's URL --> [Setup Basic Email System](https://www.notion.so/uwblueprintexecs/Setup-Basic-Email-System-11110f3fb1dc80a48e88ce63228b926c?pvs=4) <!-- Give a quick summary of the implementation details, provide design justifications if necessary --> ## Implementation description Setup a quick skeleton for email service with interfaces and classes defined. Will be implementing actual functionality in next pr. Created a test endpoint to ensure that implementation of skeleton classes is done properly just need to add actual logic. <!-- What should the reviewer do to verify your changes? Describe expected results and include screenshots when appropriate --> ## Steps to test 1. Can run backend properly 2. Hit the new test email API. Can check fast API docs for params/requirements <!-- Draw attention to the substantial parts of your PR or anything you'd like a second opinion on --> ## What should reviewers focus on? * Interface definitions other functionalities that we may ned ## Checklist - [x] My PR name is descriptive and in imperative tense - [x] My commit messages are descriptive and in imperative tense. My commits are atomic and trivial commits are squashed or fixup'd into non-trivial commits - [ ] I have run the appropriate linter(s) - [x] I have requested a review from the PL, as well as other devs who have background knowledge on this PR or who will be building on top of this PR
- Loading branch information
Showing
15 changed files
with
172 additions
and
25 deletions.
There are no files selected for viewing
Empty file.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
|
||
class IEmailService(ABC): | ||
""" | ||
Interface for the Email Service, defining the core email operations such as | ||
sending templated and custom emails. | ||
""" | ||
|
||
@abstractmethod | ||
def send_email(self, to: str, subject: str, body: str) -> dict: | ||
""" | ||
Sends an email with the given parameters. | ||
:param to: Recipient's email address | ||
:type to: str | ||
:param subject: Subject of the email | ||
:type subject: str | ||
:param body: HTML body content of the email | ||
:type body: str | ||
:return: Provider-specific metadata (like message ID, thread ID, label IDs) | ||
:rtype: dict | ||
:raises Exception: if email was not sent successfully | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def send_welcome_email(self, recipient: str, user_name: str) -> dict: | ||
""" | ||
Sends a welcome email to the specified user. | ||
:param recipient: Email address of the user | ||
:type recipient: str | ||
:param user_name: Name of the user | ||
:type user_name: str | ||
:return: Provider-specific metadata for the sent email | ||
:rtype: dict | ||
:raises Exception: if email was not sent successfully | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def send_password_reset_email(self, recipient: str, reset_link: str) -> dict: | ||
""" | ||
Sends a password reset email with the provided reset link. | ||
:param recipient: Email address of the user requesting the reset | ||
:type recipient: str | ||
:param reset_link: Password reset link | ||
:type reset_link: str | ||
:return: Provider-specific metadata for the sent email | ||
:rtype: dict | ||
:raises Exception: if email was not sent successfully | ||
""" | ||
pass | ||
|
||
@abstractmethod | ||
def send_notification_email(self, recipient: str, notification_text: str) -> dict: | ||
""" | ||
Sends a notification email to the user with the provided notification text. | ||
Examples of use case include matches completed and ready to view, new messages, | ||
meeting time scheduled, etc. | ||
:param recipient: Email address of the user | ||
:type recipient: str | ||
:param notification_text: The notification content | ||
:type notification_text: str | ||
:return: Provider-specific metadata for the sent email | ||
:rtype: dict | ||
:raises Exception: if email was not sent successfully | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
|
||
class IEmailServiceProvider(ABC): | ||
""" | ||
Interface for Email Providers that interact with external | ||
email services (e.g., Amazon SES). | ||
""" | ||
|
||
@abstractmethod | ||
def send_email( | ||
self, recipient: str, subject: str, body_html: str, body_text: str | ||
) -> dict: | ||
""" | ||
Sends an email using the provider's service. | ||
:param recipient: Email address of the recipient | ||
:type recipient: str | ||
:param subject: Subject of the email | ||
:type subject: str | ||
:param body_html: HTML body content of the email | ||
:type body_html: str | ||
:param body_text: Plain text content of the email | ||
:type body_text: str | ||
:return: Provider-specific metadata related to the sent email | ||
(like message ID, status, etc.) | ||
:rtype: dict | ||
:raises Exception: if the email fails to send | ||
""" | ||
pass |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from typing import Annotated | ||
|
||
from fastapi import APIRouter, Depends | ||
|
||
from app.interfaces.email_service import IEmailService | ||
from app.services.email.email_service import EmailService | ||
from app.services.email.email_service_provider import AmazonSESEmailProvider | ||
|
||
router = APIRouter( | ||
prefix="/email", | ||
tags=["email"], | ||
) | ||
|
||
|
||
def get_email_service() -> IEmailService: | ||
email_provider = AmazonSESEmailProvider(aws_access_key="", aws_secret_key="") | ||
return EmailService(email_provider) | ||
|
||
|
||
# TODO (Mayank, Nov 30th) - Remove test emails once email service is fully implemented | ||
@router.post("/send-test-email/") | ||
async def send_welcome_email( | ||
recipient: str, | ||
user_name: str, | ||
email_service: Annotated[IEmailService, Depends(get_email_service)], | ||
): | ||
email_service.send_welcome_email(recipient, user_name) | ||
return {"message": f"Welcome email sent to {user_name}!"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from app.interfaces.email_service import IEmailService | ||
from app.interfaces.email_service_provider import IEmailServiceProvider | ||
|
||
|
||
# TODO (Mayank, Nov 30th) - Implement the email service methods and use User object | ||
class EmailService(IEmailService): | ||
def __init__(self, provider: IEmailServiceProvider): | ||
self.provider = provider | ||
|
||
def send_email(self, to: str, subject: str, body: str) -> dict: | ||
pass | ||
|
||
def send_welcome_email(self, recipient: str, user_name: str) -> dict: | ||
pass | ||
|
||
def send_password_reset_email(self, recipient: str, reset_link: str) -> dict: | ||
pass | ||
|
||
def send_notification_email(self, recipient: str, notification_text: str) -> dict: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from app.interfaces.email_service_provider import IEmailServiceProvider | ||
|
||
|
||
class AmazonSESEmailProvider(IEmailServiceProvider): | ||
def __init__(self, aws_access_key: str, aws_secret_key: str): | ||
pass | ||
|
||
# TODO (Mayank, Nov 30th) - Create an email object to pass into this method | ||
def send_email( | ||
self, recipient: str, subject: str, body_html: str, body_text: str | ||
) -> dict: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<html> | ||
<body> | ||
<h1>Welcome, {user_name}!</h1> | ||
<p>We are glad to have you with us.</p> | ||
</body> | ||
</html> |
This file was deleted.
Oops, something went wrong.