5th Practical Class:
Sending Emails with SMTP!
Overview
Currently, your Quacker application uses a ConsoleMailerAdapter that only logs emails to the console. In this practical class, we'll replace it with a real SMTP adapter that can send actual emails through services like Gmail, SendGrid, or any SMTP provider.
We'll also learn how to create and compile beautiful email templates using MJML (Mailjet Markup Language). MJML is a markup language designed to reduce the pain of coding responsive emails. It abstracts away the complexity of responsive HTML emails and generates clean, responsive HTML that works across all email clients. Think of it as "Bootstrap for emails" - you write simple, semantic markup and MJML converts it to email-compatible HTML with all the necessary table layouts and inline styles.
Current Email Setup
The application currently has a console-based email system that logs emails instead of sending them:
This is registered in the :
Setting Up SMTP Provider
1. Configure SMTP Environment Variables
First, you need to add SMTP configuration to your file. The application already has the necessary configuration fields ready in service:
Note for Gmail users: You'll need to generate an app-specific password. Go to Google Account Settings → 2-Step Verification → App passwords.
Popular SMTP Providers Configuration Examples
Provider | SMTP_HOST | SMTP_PORT | SMTP_SECURE |
|---|---|---|---|
Gmail | smtp.gmail.com | 587 | false |
SendGrid | smtp.sendgrid.net | 587 | false |
Outlook | smtp-mail.outlook.com | 587 | false |
Mailgun | smtp.mailgun.org | 587 | false |
2. Fix EmailModule Type Issue
Before we proceed, there's a TypeScript type issue in the EmailModule that needs to be fixed. Update the to use instead of :
Important: This change from to is necessary to avoid TypeScript errors when injecting services like into the factory function.
3. Understanding the SMTP Configuration Interface
The SMTP adapter requires a specific configuration interface:
4. Replace Console Mailer with SMTP Adapter
Now we need to update the to use the SMTP adapter instead of the console mailer:
That's it! Your application will now send real emails through SMTP instead of just logging them to the console.
Important: Set the "from" address
The SMTP adapter ships with a placeholder sender. Update it to a valid address you control (ideally your domain) to avoid rejections and spam flags by providers.
Using EmailService in Your Modules
Important: Module Import Requirements
To use in any module, you need to import the into that module. The email configuration is not global by default, so each module that needs to send emails must explicitly import the .
Example: Adding Email Support to a Module
If you want to use in a module (e.g., ), you need to:
- Import in your module
- Import to access the Config service
- Configure EmailModule with the same factory function
- Inject into your services
Then in your service:
Alternative: Creating a Shared Email Module
To avoid duplicating the email configuration in every module, you can create a shared email module that's configured once and imported everywhere:
Then import in any module that needs email functionality:
Working with Email Templates
The application uses MJML (Mailjet Markup Language) for creating responsive email templates. MJML is a framework that makes it easy to create beautiful, responsive emails that work across all email clients.
Understanding the Email Flow
Creating a New Email Template
Let's create a welcome email template as an example:
Step 1: Create the MJML Template
Create a new file :
Step 2: Compile MJML to HTML
Run this command from the backend directory to compile your MJML template:
This generates an HTML file that's responsive and works across all email clients.
Step 3: Use the Template in Your Code
Now you can use this template in your application. Here's an example of sending a welcome email:
Existing Email Templates
The application already includes two email templates that are used by BetterAuth:
1. Email Verification Template
- MJML file:
- HTML file:
- Variables: - The verification link
- Used by: BetterAuth when a new user registers
2. Password Reset Template
- MJML file:
- HTML file:
- Variables:
- - The user's name
- - The password reset link
- Used by: BetterAuth when a user requests a password reset
Using Emails with BetterAuth
BetterAuth automatically sends emails in these scenarios:
- User Registration: Sends a verification email when is true
- Password Reset: Sends a reset link when user requests password reset
- Email Change: Can send verification for email changes (if configured)
The email sending is configured in the BetterAuth provider:
If you want to require verification of the user and not signing up immediately, follow Better Auth documentation from this part: https://www.better-auth.com/docs/concepts/email#2-require-email-verification
Testing Your Email Setup
1. Test SMTP Connection
You can create a simple test endpoint to verify your SMTP configuration. First, make sure to import in your :
Then add the test endpoint to your controller:
Then test it by visiting:
2. Test Registration Flow
- Register a new user through your frontend or GraphQL playground
- Check if the verification email is received
- Click the verification link to confirm it works
3. Test Password Reset
- Request a password reset for an existing user
- Check if the reset email is received
- Verify the reset link works correctly
Troubleshooting
Common Issues and Solutions
-
"Invalid login" or authentication errors
- Double-check your SMTP credentials
- For Gmail, ensure you're using an app-specific password
- Some providers require enabling "Less secure app access"
-
Connection timeout
- Check if your firewall allows outbound connections on the SMTP port
- Try different port numbers (587, 465, 25)
- Verify the SMTP_HOST is correct
-
Emails going to spam
- Use a proper "from" address that matches your domain
- Add SPF, DKIM, and DMARC records to your domain
- Avoid spam trigger words in subject and content
-
Template not found errors
- Ensure you've compiled MJML to HTML
- Check the file paths in
- Verify the template files exist in
Development Tips
Using Mailtrap for Development
Mailtrap is a great service for testing emails in development without sending real emails:
Email Preview Tools
You can use the MJML online editor at mjml.io/try-it-live to preview your templates before compiling them.
Conditional Email Sending
You might want to use different email adapters based on the environment:
Summary
You should now be able to:
- ✅ Configure SMTP providers for sending real emails
- ✅ Replace the console mailer with an SMTP adapter
- ✅ Create beautiful responsive email templates with MJML
- ✅ Compile MJML templates to HTML
- ✅ Use Handlebars variables in email templates
- ✅ Send emails through BetterAuth for user verification and password reset
- ✅ Test your email configuration
- ✅ Troubleshoot common email issues