Skip to content

Commit

Permalink
feat: email service (#262)
Browse files Browse the repository at this point in the history
* feat: email service

* fix: pnpm-lock

* chore: removed sanitize
  • Loading branch information
hmbanan666 authored Oct 25, 2024
1 parent 291eb97 commit d3e7345
Show file tree
Hide file tree
Showing 12 changed files with 197 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
package: [website, food, food-db-migration]
package: [website, food, food-db-migration, email]
runs-on: ubuntu-latest
permissions:
packages: write
Expand Down
11 changes: 11 additions & 0 deletions apps/email/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SMTP server credentials
EMAIL_HOST=""
EMAIL_PORT=""
EMAIL_USER=""
EMAIL_PASS=""

# Email addresses: from and to
EMAIL_FROM="" # Name of the sender <info@yourdomain.com>

# TOKEN
EMAIL_TOKEN=""
3 changes: 3 additions & 0 deletions apps/email/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import config from '@next-orders/eslint/nuxt.mjs'

export default config
15 changes: 15 additions & 0 deletions apps/email/nitro.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// https://nitro.unjs.io/config
export default defineNitroConfig({
srcDir: 'server',
runtimeConfig: {
nitro: {
envPrefix: 'EMAIL_',
},
token: '',
host: '',
port: 0,
user: '',
pass: '',
from: '',
},
})
25 changes: 25 additions & 0 deletions apps/email/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@next-orders/email",
"type": "module",
"private": true,
"scripts": {
"build": "nitro build",
"dev": "nitro dev",
"prepare": "nitro prepare",
"preview": "node .output/server/index.mjs",
"clean": "turbo clean",
"clean:modules": "turbo clean:modules && rm -rf .turbo node_modules",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"typecheck": "nitro prepare",
"postinstall": "nitro prepare"
},
"dependencies": {
"nodemailer": "^6.9.15"
},
"devDependencies": {
"@next-orders/eslint": "workspace:*",
"@types/nodemailer": "^6.4.16",
"nitropack": "latest"
}
}
50 changes: 50 additions & 0 deletions apps/email/server/routes/[key].post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { createTransport } from 'nodemailer'

export default eventHandler(async (event) => {
try {
const logger = useLogger('email')
const { host, port, user, pass, from, token } = useRuntimeConfig(event)
const key = getRouterParam(event, 'token')

if (!token || token !== key) {
throw createError({
statusCode: 401,
statusMessage: 'Invalid token',
})
}

const body = await readBody(event)

if (!body?.to || !body?.subject || !body?.html) {
throw createError({
statusCode: 400,
statusMessage: 'Missing data',
})
}

const transporter = createTransport({
host,
port: Number(port),
secure: Number(port) === 465,
tls: {
rejectUnauthorized: false,
},
auth: { user, pass },
})

const info = await transporter.sendMail({
from,
to: body.to,
subject: body.subject,
text: body.html,
html: body.html,
})
logger.log('Response from SMTP server:', info?.accepted?.length > 0 ? 'SUCCESS' : 'FAILED', info?.response, info?.messageId)

return {
ok: true,
}
} catch (error) {
throw errorResolver(error)
}
})
17 changes: 17 additions & 0 deletions apps/email/server/utils/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { H3Error } from 'h3'

const logger = useLogger('error')

export function errorResolver(exception: unknown) {
if (exception instanceof H3Error) {
throw exception
}

// Ok, something intereresting happened
logger.error(exception)

return createError({
statusCode: 500,
statusMessage: 'Internal server error',
})
}
5 changes: 5 additions & 0 deletions apps/email/server/utils/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { consola } from 'consola'

export function useLogger(tag?: string) {
return tag ? consola.withTag(tag) : consola
}
4 changes: 4 additions & 0 deletions apps/email/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// https://nitro.unjs.io/guide/typescript
{
"extends": "./.nitro/types/tsconfig.json"
}
28 changes: 28 additions & 0 deletions docker/email/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
ARG NODE=node:22.10.0-alpine

################# Base builder ##############

FROM $NODE AS builder
WORKDIR /app

ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

COPY . .
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile \
&& pnpm build --filter @next-orders/email

################# App ##############

FROM $NODE
WORKDIR /app
COPY --from=builder /app/apps/food/.output .

ARG VERSION=nightly
ENV VERSION=${VERSION}
ENV NODE_ENV=production

EXPOSE 3000

CMD ["/app/server/index.mjs"]
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"dev": "dotenv -- turbo dev --parallel",
"dev:website": "dotenv -- pnpm --filter @next-orders/website dev",
"dev:food": "dotenv -- pnpm --filter @next-orders/food dev",
"dev:email": "dotenv -- pnpm --filter @next-orders/email dev",
"lint": "turbo lint --",
"lint:fix": "turbo lint:fix",
"clean": "turbo clean",
Expand Down
45 changes: 37 additions & 8 deletions pnpm-lock.yaml

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

0 comments on commit d3e7345

Please sign in to comment.