Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
2f25937a94
|
|||
|
658b8d4dd8
|
|||
|
df6381fd5e
|
|||
|
a11e5f2f3e
|
|||
|
7a8e484632
|
|||
|
1f771fb73f
|
|||
|
34c8f03571
|
|||
|
dfac4c0fe9
|
|||
|
9860014420
|
|||
|
bfce0c22c0
|
|||
|
828290d9ba
|
|||
|
96e3be543b
|
|||
|
c8781e3a3d
|
|||
|
22ab25045c
|
|||
|
2230259e4a
|
|||
|
57f3a910f6
|
|||
|
9076a9488e
|
@@ -6,6 +6,8 @@ EMAIL_FROM="noreply@lauf-fuer-kaya.de"
|
||||
EMAIL_REPLYTO="info@lauf-fuer-kaya.de"
|
||||
REDIS_URL=redis://localhost:6379
|
||||
FRONTEND_URL="https://run.lauf-fuer-kaya.de"
|
||||
DOCUMENT_SERVER_URL="https://documents.run.lauf-fuer-kaya.de"
|
||||
AUTHKEY=""
|
||||
EVENT_DATE="23.05.2025"
|
||||
EVENT_NAME="Lauf für Kaya! 2025"
|
||||
EVENT_NAME="Lauf für Kaya! 2025"
|
||||
NODE_ENV=production
|
||||
@@ -1,19 +1,4 @@
|
||||
steps:
|
||||
- name: build latest
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
repo: registry.odit.services/lfk/mailer
|
||||
tags:
|
||||
- latest
|
||||
registry: registry.odit.services
|
||||
platforms: linux/amd64,linux/arm64
|
||||
cache_from: registry.odit.services/lfk/mailer:dev
|
||||
username:
|
||||
from_secret: odit-registry-builder-username
|
||||
password:
|
||||
from_secret: odit-registry-builder-password
|
||||
when:
|
||||
branch: main
|
||||
- name: build dev
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
|
||||
16
Dockerfile
16
Dockerfile
@@ -1,21 +1,7 @@
|
||||
FROM oven/bun:1.1.36-slim
|
||||
# FROM oven/bun:1.0.25
|
||||
|
||||
FROM oven/bun:1.1.40-slim
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
|
||||
# Install dependencies
|
||||
COPY package.json .
|
||||
RUN bun i
|
||||
# COPY package.json bun.lockb ./
|
||||
# RUN bun install --frozen-lockfile
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Expose the application port
|
||||
EXPOSE 3000
|
||||
|
||||
# Start the application
|
||||
CMD ["bun", "run", "start"]
|
||||
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@odit/lfk-mailer",
|
||||
"version": "1.0.0",
|
||||
"version": "1.2.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@@ -11,11 +11,10 @@
|
||||
"@hono/node-server": "1.13.7",
|
||||
"@hono/swagger-ui": "0.5.0",
|
||||
"@hono/zod-openapi": "0.18.3",
|
||||
"@hono/zod-validator": "0.4.1",
|
||||
"bullmq": "5.34.0",
|
||||
"bwip-js": "4.5.1",
|
||||
"@hono/zod-validator": "0.4.2",
|
||||
"bullmq": "5.34.3",
|
||||
"handlebars": "4.7.8",
|
||||
"hono": "4.6.13",
|
||||
"hono": "4.6.14",
|
||||
"ioredis": "5.4.1",
|
||||
"nodemailer": "6.9.16",
|
||||
"zod": "3.24.1"
|
||||
@@ -23,6 +22,6 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "22.10.2",
|
||||
"@types/nodemailer": "6.4.17",
|
||||
"bun-types": "1.1.38"
|
||||
"bun-types": "1.1.40"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ import { createTransport } from "nodemailer";
|
||||
import { Queue, Worker, QueueEvents } from "bullmq";
|
||||
import { config } from "../config/env";
|
||||
import Redis from "ioredis";
|
||||
import { Attachment } from "nodemailer/lib/mailer";
|
||||
|
||||
interface EmailJob {
|
||||
to: string;
|
||||
subject: string;
|
||||
html: string;
|
||||
attachments: Attachment[];
|
||||
text: string;
|
||||
}
|
||||
|
||||
@@ -40,12 +42,13 @@ const worker = new Worker<EmailJob>(
|
||||
QUEUE_NAME,
|
||||
async (job) => {
|
||||
await transporter.sendMail({
|
||||
from: config.email.from,
|
||||
from: { address: config.email.from, name: "Lauf für Kaya!" },
|
||||
replyTo: config.email.replyTo,
|
||||
to: job.data.to,
|
||||
subject: job.data.subject,
|
||||
text: job.data.text,
|
||||
html: job.data.html,
|
||||
attachments: job.data.attachments,
|
||||
});
|
||||
},
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ import { z } from 'zod'
|
||||
import { EmailService } from '../services/email'
|
||||
import { getEmailTemplate } from '../templates'
|
||||
import { Language } from '../types'
|
||||
import { toBuffer } from 'bwip-js/node'
|
||||
import { Attachment } from 'nodemailer/lib/mailer'
|
||||
|
||||
const emailRouter = new Hono()
|
||||
const emailService = new EmailService()
|
||||
@@ -18,24 +18,12 @@ const sendEmailSchema = z.object({
|
||||
})
|
||||
|
||||
async function generateBarcodeDataURL(data) {
|
||||
const buffer = await toBuffer({
|
||||
bcid: 'code128',
|
||||
text: data,
|
||||
scale: 3,
|
||||
height: 10,
|
||||
includetext: true,
|
||||
textxalign: 'center',
|
||||
});
|
||||
|
||||
const base64Data = buffer.toString('base64');
|
||||
const dataURL = `data:image/png;base64,${base64Data}`;
|
||||
|
||||
return dataURL;
|
||||
return `${process.env.DOCUMENT_SERVER_URL}/v1/barcodes/code128/${data}`
|
||||
}
|
||||
|
||||
emailRouter.post('/', bearerAuth({ token: process.env.AUTHKEY }), zValidator('json', sendEmailSchema), async (c) => {
|
||||
let { to, templateName, language, data } = c.req.valid('json')
|
||||
|
||||
const attachments: Attachment[] = []
|
||||
try {
|
||||
const template = getEmailTemplate(templateName, language as Language)
|
||||
if (templateName === "welcome") {
|
||||
@@ -45,6 +33,12 @@ emailRouter.post('/', bearerAuth({ token: process.env.AUTHKEY }), zValidator('js
|
||||
} else {
|
||||
return c.json({ success: false, error: "required params 'data.name', 'data.link', 'data.barcode_content' not provided" }, 406)
|
||||
}
|
||||
const attachment: Attachment = {
|
||||
filename: 'invite.ics',
|
||||
content: `BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//ICS Generator//NONSGML ICS Generator//DE\nBEGIN:VEVENT\nUID:1742337822408-5ghrzyi@icsgenerator.local\nDTSTAMP:20250318T224342Z\nSUMMARY:Lauf für Kaya! 2025\nDTSTART:20250523T110000Z\nDTEND:20250523T160000Z\nDESCRIPTION:Der Lauf für Kaya! 2025 findet am 23.05.2025 auf dem Sportplatz des Gymnasium Herzogenaurach statt. Zur Anmeldung einfach zum Infozelt kommen.\nLOCATION:Sportplatz Gymnasium Herzogenaurach\nBEGIN:VALARM\nACTION:DISPLAY\nDESCRIPTION:Erinnerung: Lauf für Kaya! 2025\nTRIGGER:-PT1440M\nEND:VALARM\nEND:VEVENT\nEND:VCALENDAR`,
|
||||
contentType: 'text/calendar; method=REQUEST',
|
||||
}
|
||||
attachments.push(attachment)
|
||||
}
|
||||
if (templateName === "password-reset") {
|
||||
if (data.token) {
|
||||
@@ -58,6 +52,7 @@ emailRouter.post('/', bearerAuth({ token: process.env.AUTHKEY }), zValidator('js
|
||||
data.event_name = process.env.EVENT_NAME
|
||||
await emailService.sendEmail({
|
||||
to,
|
||||
attachments,
|
||||
subject: template.subject(data),
|
||||
html: template.html(data),
|
||||
text: template.text(data)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { emailQueue } from '../queues/email.queue'
|
||||
import { config } from '../config/env'
|
||||
import { Attachment } from 'nodemailer/lib/mailer'
|
||||
|
||||
interface EmailOptions {
|
||||
to: string
|
||||
subject: string
|
||||
html: string
|
||||
attachments: Attachment[]
|
||||
text: string
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user