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"
|
EMAIL_REPLYTO="info@lauf-fuer-kaya.de"
|
||||||
REDIS_URL=redis://localhost:6379
|
REDIS_URL=redis://localhost:6379
|
||||||
FRONTEND_URL="https://run.lauf-fuer-kaya.de"
|
FRONTEND_URL="https://run.lauf-fuer-kaya.de"
|
||||||
|
DOCUMENT_SERVER_URL="https://documents.run.lauf-fuer-kaya.de"
|
||||||
AUTHKEY=""
|
AUTHKEY=""
|
||||||
EVENT_DATE="23.05.2025"
|
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:
|
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
|
- name: build dev
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
settings:
|
settings:
|
||||||
|
|||||||
16
Dockerfile
16
Dockerfile
@@ -1,21 +1,7 @@
|
|||||||
FROM oven/bun:1.1.36-slim
|
FROM oven/bun:1.1.40-slim
|
||||||
# FROM oven/bun:1.0.25
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy package files
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
COPY package.json .
|
COPY package.json .
|
||||||
RUN bun i
|
RUN bun i
|
||||||
# COPY package.json bun.lockb ./
|
|
||||||
# RUN bun install --frozen-lockfile
|
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Expose the application port
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Start the application
|
|
||||||
CMD ["bun", "run", "start"]
|
CMD ["bun", "run", "start"]
|
||||||
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odit/lfk-mailer",
|
"name": "@odit/lfk-mailer",
|
||||||
"version": "1.0.0",
|
"version": "1.2.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -11,11 +11,10 @@
|
|||||||
"@hono/node-server": "1.13.7",
|
"@hono/node-server": "1.13.7",
|
||||||
"@hono/swagger-ui": "0.5.0",
|
"@hono/swagger-ui": "0.5.0",
|
||||||
"@hono/zod-openapi": "0.18.3",
|
"@hono/zod-openapi": "0.18.3",
|
||||||
"@hono/zod-validator": "0.4.1",
|
"@hono/zod-validator": "0.4.2",
|
||||||
"bullmq": "5.34.0",
|
"bullmq": "5.34.3",
|
||||||
"bwip-js": "4.5.1",
|
|
||||||
"handlebars": "4.7.8",
|
"handlebars": "4.7.8",
|
||||||
"hono": "4.6.13",
|
"hono": "4.6.14",
|
||||||
"ioredis": "5.4.1",
|
"ioredis": "5.4.1",
|
||||||
"nodemailer": "6.9.16",
|
"nodemailer": "6.9.16",
|
||||||
"zod": "3.24.1"
|
"zod": "3.24.1"
|
||||||
@@ -23,6 +22,6 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "22.10.2",
|
"@types/node": "22.10.2",
|
||||||
"@types/nodemailer": "6.4.17",
|
"@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 { Queue, Worker, QueueEvents } from "bullmq";
|
||||||
import { config } from "../config/env";
|
import { config } from "../config/env";
|
||||||
import Redis from "ioredis";
|
import Redis from "ioredis";
|
||||||
|
import { Attachment } from "nodemailer/lib/mailer";
|
||||||
|
|
||||||
interface EmailJob {
|
interface EmailJob {
|
||||||
to: string;
|
to: string;
|
||||||
subject: string;
|
subject: string;
|
||||||
html: string;
|
html: string;
|
||||||
|
attachments: Attachment[];
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,12 +42,13 @@ const worker = new Worker<EmailJob>(
|
|||||||
QUEUE_NAME,
|
QUEUE_NAME,
|
||||||
async (job) => {
|
async (job) => {
|
||||||
await transporter.sendMail({
|
await transporter.sendMail({
|
||||||
from: config.email.from,
|
from: { address: config.email.from, name: "Lauf für Kaya!" },
|
||||||
replyTo: config.email.replyTo,
|
replyTo: config.email.replyTo,
|
||||||
to: job.data.to,
|
to: job.data.to,
|
||||||
subject: job.data.subject,
|
subject: job.data.subject,
|
||||||
text: job.data.text,
|
text: job.data.text,
|
||||||
html: job.data.html,
|
html: job.data.html,
|
||||||
|
attachments: job.data.attachments,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { z } from 'zod'
|
|||||||
import { EmailService } from '../services/email'
|
import { EmailService } from '../services/email'
|
||||||
import { getEmailTemplate } from '../templates'
|
import { getEmailTemplate } from '../templates'
|
||||||
import { Language } from '../types'
|
import { Language } from '../types'
|
||||||
import { toBuffer } from 'bwip-js/node'
|
import { Attachment } from 'nodemailer/lib/mailer'
|
||||||
|
|
||||||
const emailRouter = new Hono()
|
const emailRouter = new Hono()
|
||||||
const emailService = new EmailService()
|
const emailService = new EmailService()
|
||||||
@@ -18,24 +18,12 @@ const sendEmailSchema = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
async function generateBarcodeDataURL(data) {
|
async function generateBarcodeDataURL(data) {
|
||||||
const buffer = await toBuffer({
|
return `${process.env.DOCUMENT_SERVER_URL}/v1/barcodes/code128/${data}`
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emailRouter.post('/', bearerAuth({ token: process.env.AUTHKEY }), zValidator('json', sendEmailSchema), async (c) => {
|
emailRouter.post('/', bearerAuth({ token: process.env.AUTHKEY }), zValidator('json', sendEmailSchema), async (c) => {
|
||||||
let { to, templateName, language, data } = c.req.valid('json')
|
let { to, templateName, language, data } = c.req.valid('json')
|
||||||
|
const attachments: Attachment[] = []
|
||||||
try {
|
try {
|
||||||
const template = getEmailTemplate(templateName, language as Language)
|
const template = getEmailTemplate(templateName, language as Language)
|
||||||
if (templateName === "welcome") {
|
if (templateName === "welcome") {
|
||||||
@@ -45,6 +33,12 @@ emailRouter.post('/', bearerAuth({ token: process.env.AUTHKEY }), zValidator('js
|
|||||||
} else {
|
} else {
|
||||||
return c.json({ success: false, error: "required params 'data.name', 'data.link', 'data.barcode_content' not provided" }, 406)
|
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 (templateName === "password-reset") {
|
||||||
if (data.token) {
|
if (data.token) {
|
||||||
@@ -58,6 +52,7 @@ emailRouter.post('/', bearerAuth({ token: process.env.AUTHKEY }), zValidator('js
|
|||||||
data.event_name = process.env.EVENT_NAME
|
data.event_name = process.env.EVENT_NAME
|
||||||
await emailService.sendEmail({
|
await emailService.sendEmail({
|
||||||
to,
|
to,
|
||||||
|
attachments,
|
||||||
subject: template.subject(data),
|
subject: template.subject(data),
|
||||||
html: template.html(data),
|
html: template.html(data),
|
||||||
text: template.text(data)
|
text: template.text(data)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { emailQueue } from '../queues/email.queue'
|
import { emailQueue } from '../queues/email.queue'
|
||||||
import { config } from '../config/env'
|
import { config } from '../config/env'
|
||||||
|
import { Attachment } from 'nodemailer/lib/mailer'
|
||||||
|
|
||||||
interface EmailOptions {
|
interface EmailOptions {
|
||||||
to: string
|
to: string
|
||||||
subject: string
|
subject: string
|
||||||
html: string
|
html: string
|
||||||
|
attachments: Attachment[]
|
||||||
text: string
|
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