Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#744 Added mail service for resend #772

Merged
merged 20 commits into from
Jan 29, 2025
Merged

#744 Added mail service for resend #772

merged 20 commits into from
Jan 29, 2025

Conversation

cl3vy
Copy link
Contributor

@cl3vy cl3vy commented Nov 13, 2024

#744 Added MailService Interface and ResendMailService implementation (#744)

This PR introduces a new ResendMailService implementation of the MailService interface, enabling email functionality for participant confirmations and event communications using Resend. This includes both generic email sending and tailored participant-specific emails for successful confirmations and pending confirmations, with support for HTML templates to enhance the email presentation.

resolves #744

Key Features

  1. send_email: A general-purpose email method that sends to a specified recipient with options for both text and HTML bodies.
  2. send_participant_successful_confirmation_email: Sends a confirmation email to participants after successful acceptance into the event, including participant details, team name, and an invite link.
  3. send_participant_confirmation_email: Notifies participants of required action to confirm their application, including a confirmation link and participant details.
  4. HTML Template Integration: Supports HTML email templates with placeholders.

Notes

  • The email service uses Resend as the backend, with the API key pulled from the .env.

How to verify:

  • Will add these later.

@IvanObreshkov
Copy link
Collaborator

IvanObreshkov commented Nov 13, 2024

Resolve the comments, the tests will be done in another PR

Copy link
Collaborator

@Isak-Bego Isak-Bego left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall good job! As Ivan has mentioned a couple of fixes regarding the error handling using the Result pattern. We also need to address the async method send_mail and make sure that it is not blocking the flow of the program. If you can give it a quick test of the whole workflow and see if it works.

@cl3vy cl3vy closed this Nov 14, 2024
@cl3vy cl3vy reopened this Nov 14, 2024
Still havent made the methods return Result objects will do that on another push
Still havent made the methods return Result objects will do that on another push
I wanted to test sending email, It worked, forgot to remove it in the last push
Fixing them because they were had None as their return type
raise NotImplementedError()

@abstractmethod
async def send_participant_successful_registration_email(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this have to do with the mailing service?

You should have a concrete method which is handling the send operation and then you can create multiple different mailing services by extending the base concrete class which would handle the different business domains such as HackathonMailService which will be implementing the send_participant_successful_registration_email

Copy link
Member

@asynchroza asynchroza Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's perfectly fine to have an interface/abstract class for the MailService but you generally don't need it as we don't expect to have different mailing clients - only resend.

Copy link
Member

@asynchroza asynchroza Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MailService to be a concrete class with a concrete send method.

HackathonMailService to extend MailService and implement all domain specific methods. No abstraction is needed whatsoever.

Copy link
Member

@asynchroza asynchroza Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you and @IvanObreshkov have adhered to the pattern with the base abstraction class so that possibly you can implement other clients in the future but you shouldn't be coupling domain specific implementations with the service.

Copy link
Collaborator

@Isak-Bego Isak-Bego Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's perfectly fine to have an interface/abstract class for the MailService but you generally don't need it as we don't expect to have different mailing clients - only resend.

@asynchroza We want to have an abstract class so that we have a well defined interface for sending email which is independent of the mailing service we are using. It is true that for this year we are going to use Resend, however thinking about the future we want to be able to swap the mailing client without causing other necessary changes in our code base.
As I believe in your understanding of this matter, I think you meant that we are over complicating it. Which to be honest for someone who has taken a simple course in object oriented programming should not be a problem to understand

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And when we say ResendMailService we mean ResendHackathonMailService if we want to look at it in that way.

Copy link
Member

@asynchroza asynchroza Jan 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the project's sole focus is on the "hackathon" domain. However, this doesn't mean the team lacks plans for future expansion. In fact, two years ago, we had an admin panel specifically designed for managing events and hubbers.

From a clean code perspective, if we were to strictly adhere to all guidelines, MailClient would ideally be an interface implemented by specific clients such as GMail, Outlook, and Resend. The HackathonMailingService would then follow the dependency injection pattern by accepting an instance of MailClient.

const mailClient = ResendMailClient();
const hackathonMailingService = HackathonMailingService(mailClient);

My suggestion to define MailClient as a concrete implementation, mimicing the facade pattern, was aimed at reducing your workload. I find it unlikely that The Hub will be using multiple mailing clients simultaneously. Therefore, having a single concrete MailClient with a send_mail method (protected if base is inherited, public if used in DI), shared across all MailService classes, represents the most efficient and extensible solution for the effort invested.

HackathonMailingService extends MailClient {
   func send_verification_email() {
       this->send_emai(...)
   }
}

or

HackathonMailingService {
   HackathonMailingService(emailClient) {
      this->emailClient = emailClient;
   }
   
   func send_verification_email() {
       this->emailClient.send_emai()
   }
}

var emailClient := MailClient();
var hackathonMailingService = HackathonMailingService(emailClient);

Copy link
Member

@asynchroza asynchroza Jan 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And when we say ResendMailService we mean ResendHackathonMailService if we want to look at it in that way.

This way of structure in your classes already makes it too convoluted and in turn making it hard to extend or replace in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, it's up to you how you approach the problem. If it works, it works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, will take a look at implementing what you said.

Copy link
Contributor Author

@cl3vy cl3vy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need a second eye on this commit @Isak-Bego , @IvanObreshkov , @asynchroza

Copy link
Collaborator

@Isak-Bego Isak-Bego left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks Good To Me!

@cl3vy cl3vy merged commit 1392ba0 into main Jan 29, 2025
1 check passed
@cl3vy cl3vy deleted the 744-resend-mail-service branch January 29, 2025 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feature: add resend for sending emails
4 participants