Skip to content

Commit

Permalink
Support smtp server for node version (#143)
Browse files Browse the repository at this point in the history
  • Loading branch information
byn9826 authored Sep 6, 2024
1 parent 393a408 commit ec2ab18
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 18 deletions.
27 changes: 19 additions & 8 deletions docs/auth-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,10 @@ npm run node:start
```

## Mailer Setup
Melody Auth supports email-based features such as password reset, email verification and email MFA. To make sure these features works as expected, you need to set up SendGrid or Brevo integration and configure the necessary environment variables in your Cloudflare Worker.
Melody Auth supports email-based features such as password reset, email verification, and email MFA. To ensure these features work as expected, you need to configure either SendGrid, Brevo, or SMTP integration.

### Prerequisites
- A SendGrid/Brevo account
- SendGrid/Brevo API key
- Verified sender email address in SendGrid/Brevo
- For Cloudflare Workers or Node Version: SendGrid and Brevo integration are supported.
- For the Node version only: You can use an SMTP server.

### Configuration Steps (Cloudflare Production)

Expand All @@ -143,9 +141,20 @@ Melody Auth supports email-based features such as password reset, email verifica
3. Click "Save and deploy" to apply the changes.

### Configuration Steps (Cloudflare Local or Node)
Update environment variables in server/.dev.vars file accordingly.
Update the following environment variables in your server/.dev.vars file:
• ENVIRONMENT
• DEV_EMAIL_RECEIVER
• SENDGRID_API_KEY
• SENDGRID_SENDER_ADDRESS
• BREVO_API_KEY
• BREVO_SENDER_ADDRESS

### Environment Behavior
### Configuration Steps (SMTP with Node)
If you are using the Node version, you can configure the following environment variables in your server/.dev.vars file to use an SMTP server:
• SMTP_SENDER_NAME
• SMTP_CONNECTION_STRING

### Mailer Environment Behavior

- When `ENVIRONMENT` is set to "prod":
- Emails will be sent to the actual user email addresses.
Expand All @@ -155,7 +164,9 @@ Update environment variables in server/.dev.vars file accordingly.
- All emails will be redirected to the address specified in `DEV_EMAIL_RECEIVER`.
- This is useful for testing and development to avoid sending emails to real users.

- Priority Between SendGrid and Brevo:
- Priority Between SendGrid, Brevo and SMTP server:
- For node version, If SMTP_CONNECTION_STRING is defined, the SMTP server will always be used, regardless of SendGrid or Brevo settings.
- For Cloudflare (both prod and dev): SMTP_CONNECTION_STRING will be ignored.
- If both SendGrid and Brevo keys and sender addresses are provided, SendGrid will take precedence.

## Additional Configs
Expand Down
21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions server/.dev.vars.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ BREVO_SENDER_ADDRESS= # Put your Brevo sender address here

AUTH_SERVER_URL="http://localhost:8787" # The host url of your CF worker

# To run project with node, Postgres and Redis
# Config following env vars to run this project using node, Postgres and Redis, with the option to use an SMTP mailer server as well
# PG_CONNECTION_STRING=postgres://postgres:postgres@127.0.0.1:5432/melody-auth
# REDIS_CONNECTION_STRING=redis://username:password@127.0.0.1:6379
# REDIS_CONNECTION_STRING=redis://username:password@127.0.0.1:6379
# SMTP_SENDER_NAME=your_email_address
# SMTP_CONNECTION_STRING=smtp://username:password@smtp.mailserver.com:587
16 changes: 9 additions & 7 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"dev:secret:generate": "node ./src/scripts/generate-secret.cjs",
"node:dev": "tsx watch src/node.tsx",
"node:build": "tsc && tsc-alias",
"node:start": "node dist/src/node.js",
"node:start": "node dist/node.js",
"node:migration:apply": "knex --knexfile knexfile.cjs migrate:latest",
"node:secret:generate": "node ./src/scripts/generate-secret.cjs node",
"test:check:node": "TEST_MODE=node vitest run",
Expand All @@ -20,20 +20,21 @@
"swagger:generate": "node ./src/scripts/generate-swagger.cjs"
},
"dependencies": {
"@hono/node-server": "^1.12.2",
"@hono/swagger-ui": "^0.4.0",
"base32-decode": "^1.0.0",
"base32-encode": "^2.0.0",
"bcryptjs": "^2.4.3",
"class-validator": "^0.14.1",
"dotenv": "^16.4.5",
"hono": "^4.4.12",
"hono-sessions": "^0.5.8",
"toml": "^3.0.0",
"pg": "^8.12.0",
"knex": "^3.1.0",
"@hono/node-server": "^1.12.2",
"dotenv": "^16.4.5",
"ioredis": "^5.4.1",
"shared": "*"
"knex": "^3.1.0",
"nodemailer": "^6.9.15",
"pg": "^8.12.0",
"shared": "*",
"toml": "^3.0.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20240529.0",
Expand All @@ -50,6 +51,7 @@
"otplib": "^12.0.1",
"pg-mem": "^3.0.2",
"swagger-jsdoc": "^6.2.8",
"@types/nodemailer": "^6.4.15",
"tsc-alias": "^1.8.10",
"tsx": "^4.19.0",
"typescript": "^5.5.4",
Expand Down
1 change: 1 addition & 0 deletions server/src/adapters/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * as pgAdapter from 'adapters/pg'
export * as redisAdapter from 'adapters/redis'
export * as smtpAdapter from 'adapters/smtp'
9 changes: 9 additions & 0 deletions server/src/adapters/smtp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createTransport } from 'nodemailer'

export const fit = () => (
{
init: () => {
return createTransport(process.env.SMTP_CONNECTION_STRING)
},
}
)
4 changes: 4 additions & 0 deletions server/src/configs/type.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Hono } from 'hono'
import { BlankSchema } from 'hono/types'
import { Session } from 'hono-sessions'
import type {
Transporter, SentMessageInfo,
} from 'nodemailer'
import { oauthDto } from 'dtos'
import { typeConfig } from 'configs'
import { userModel } from 'models'
Expand All @@ -10,6 +13,7 @@ export type Locale = 'en' | 'fr'
export type Bindings = {
DB: D1Database;
KV: KVNamespace;
SMTP: { init: () => Transporter<SentMessageInfo> };
ENVIRONMENT: string;
DEV_EMAIL_RECEIVER: string;
SENDGRID_API_KEY: string;
Expand Down
3 changes: 2 additions & 1 deletion server/src/node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as dotenv from 'dotenv'
import toml from 'toml'
import { typeConfig } from 'configs'
import {
pgAdapter, redisAdapter,
pgAdapter, redisAdapter, smtpAdapter,
} from 'adapters'
import { loadRouters } from 'router'

Expand All @@ -32,6 +32,7 @@ app.use(
) => {
c.env.KV = redisAdapter.fit() as unknown as any
c.env.DB = pgAdapter.fit() as unknown as any
c.env.SMTP = smtpAdapter.fit()
await next()
},
)
Expand Down
11 changes: 11 additions & 0 deletions server/src/services/email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ export const sendEmail = async (

const receiver = environment === 'prod' ? receiverEmail : devEmailReceiver

if (c.env.SMTP) {
const transporter = c.env.SMTP.init()
const res = await transporter.sendMail({
from: process.env.SMTP_SENDER_NAME,
to: receiver,
subject,
html: emailBody,
})
return res?.accepted[0] === receiver
}

if (sendgridApiKey && sendgridSender) {
const res = await fetch(
'https://api.sendgrid.com/v3/mail/send',
Expand Down

0 comments on commit ec2ab18

Please sign in to comment.