9 Commits
1.2.0 ... 1.2.5

Author SHA1 Message Date
f9a202db55 chore(deps): bump
Some checks failed
Build Latest image / build-container (push) Successful in 44s
Build release images / build-container (push) Failing after 3h14m11s
2025-03-27 10:20:15 +01:00
92fc5762e4 chore(deps): bun:1.2.6
All checks were successful
Build Latest image / build-container (push) Successful in 38s
2025-03-27 10:03:18 +01:00
326b241dab feat: update email for new times
All checks were successful
Build Latest image / build-container (push) Successful in 33s
Build release images / build-container (push) Successful in 31s
2025-03-27 10:00:56 +01:00
a7a50ff59d refactor(ci): Switch to actions
All checks were successful
Build Latest image / build-container (push) Successful in 36s
2025-03-22 22:55:22 +01:00
4257686f35 ics invite 2025-03-19 00:37:53 +01:00
2f25937a94 feat: add ical 2025-03-18 23:57:01 +01:00
658b8d4dd8 chore: 1.2.1 2025-03-18 23:38:08 +01:00
df6381fd5e feat: new email templates 2025-03-18 23:37:28 +01:00
a11e5f2f3e ci: drop main branch
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-18 18:01:12 +01:00
14 changed files with 242 additions and 112 deletions

28
.gitea/workflows/dev.yaml Normal file
View File

@@ -0,0 +1,28 @@
name: Build Latest image
on:
push:
branches:
- dev
jobs:
build-container:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to registry
uses: docker/login-action@v3
with:
registry: registry.odit.services
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: |
${{ vars.REGISTRY }}/lfk/mailer:dev
${{ vars.REGISTRY }}/lfk/mailer:latest
platforms: linux/amd64,linux/arm64

View File

@@ -0,0 +1,27 @@
name: Build release images
on:
push:
tags:
- "*.*.*"
jobs:
build-container:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to registry
uses: docker/login-action@v3
with:
registry: registry.odit.services
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: |
${{ vars.REGISTRY }}/lfk/mailer:${{ github.ref_name }}
platforms: linux/amd64,linux/arm64

View File

@@ -1,33 +0,0 @@
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:
repo: registry.odit.services/lfk/mailer
tags:
- dev
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: dev
when:
event: push

View File

@@ -1,17 +0,0 @@
steps:
- name: build tag
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/mailer
tags:
- "${CI_COMMIT_TAG}"
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:
event:
- tag

View File

@@ -1,4 +1,4 @@
FROM oven/bun:1.1.40-slim
FROM oven/bun:1.2.6-slim
WORKDIR /app
COPY package.json .
RUN bun i

BIN
bun.lockb

Binary file not shown.

View File

@@ -1,6 +1,6 @@
{
"name": "@odit/lfk-mailer",
"version": "1.2.0",
"version": "1.2.3",
"private": true,
"type": "module",
"scripts": {
@@ -8,20 +8,20 @@
"start": "bun src/index.ts"
},
"dependencies": {
"@hono/node-server": "1.13.7",
"@hono/swagger-ui": "0.5.0",
"@hono/zod-openapi": "0.18.3",
"@hono/zod-validator": "0.4.2",
"bullmq": "5.34.3",
"@hono/node-server": "1.14.0",
"@hono/swagger-ui": "0.5.1",
"@hono/zod-openapi": "0.19.2",
"@hono/zod-validator": "0.4.3",
"bullmq": "5.44.4",
"handlebars": "4.7.8",
"hono": "4.6.14",
"ioredis": "5.4.1",
"nodemailer": "6.9.16",
"zod": "3.24.1"
"hono": "4.7.5",
"ioredis": "5.6.0",
"nodemailer": "6.10.0",
"zod": "3.24.2"
},
"devDependencies": {
"@types/node": "22.10.2",
"@types/node": "22.13.14",
"@types/nodemailer": "6.4.17",
"bun-types": "1.1.40"
"bun-types": "1.2.6"
}
}

View File

@@ -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,
});
},
{

View File

@@ -5,6 +5,7 @@ import { z } from 'zod'
import { EmailService } from '../services/email'
import { getEmailTemplate } from '../templates'
import { Language } from '../types'
import { Attachment } from 'nodemailer/lib/mailer'
const emailRouter = new Hono()
const emailService = new EmailService()
@@ -20,9 +21,9 @@ async function generateBarcodeDataURL(data) {
return `${process.env.DOCUMENT_SERVER_URL}/v1/barcodes/code128/${data}`
}
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')
const attachments: Attachment[] = []
try {
const template = getEmailTemplate(templateName, language as Language)
if (templateName === "welcome") {
@@ -32,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\nBEGIN:VEVENT\nSUMMARY:Lauf für Kaya! 2025\nDTSTART:20250523T110000Z\nDTEND:20250523T160000Z\nDTSTAMP:20250318T230306Z\nUID:lfk2025-xhJP3h\nDESCRIPTION:Der Lauf für Kaya! 2025 findet am 23.05.2025 auf dem Sportplatz des Gymnasium Herzogenaurach statt - Bürgerlauf von 14 bis 18 Uhr - Firmenlauf von 13:30 bis 18 Uhr.\nLOCATION:Sportplatz Gymnasium Herzogenaurach\nORGANIZER:info@lauf-fuer-kaya.de\nSTATUS:CONFIRMED\nPRIORITY:5\nEND:VEVENT\nEND:VCALENDAR`,
contentType: 'text/calendar; method=REQUEST',
}
attachments.push(attachment)
}
if (templateName === "password-reset") {
if (data.token) {
@@ -45,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)

View File

@@ -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
}

View File

@@ -175,8 +175,11 @@
-moz-osx-font-smoothing: grayscale;
"
>
Am Lauftag (<strong>{{event_date}}</strong>) musst du nur noch diesen
Barcode vorzeigen, damit erhältst du deine Läuferkarte.
Am Lauftag (<strong>{{event_date}}</strong>) musst du nur noch
diesen Barcode vorzeigen, damit erhältst du deine Läuferkarte.<br />Der
<b>Bürgerlauf</b> findet von
<b>14:00 bis 18:00 Uhr</b> statt.<br />Der
<b>Firmenlauf</b> beginnt um <b>13:30 Uhr</b>.
</p>
<table
align="center"
@@ -223,20 +226,68 @@
"
>
Deinen Registrierungs-Code, Rundenzeiten und weitere Infos kannst
du jederzeit im
du jederzeit im Lauf für Kaya! Selfservice einsehen.
</p>
<table
align="center"
width="100%"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="max-width: 100%; text-align: center; margin-bottom: 20px"
>
<tbody>
<tr style="width: 100%">
<td>
<a
href="{{link}}"
rel="noopener noreferrer nofollow"
style="
color: #111827;
text-decoration: underline;
line-height: 100%;
text-decoration: none;
display: inline-block;
max-width: 100%;
mso-padding-alt: 0px;
color: #ffffff;
background-color: #3a4bdd;
border-color: #3a4bdd;
border-width: 2px;
border-style: solid;
font-size: 14px;
font-weight: 500;
border-radius: 0px;
padding: 12px 32px 12px 32px;
"
target="_blank"
>Lauf für Kaya! Selfservice</a
><span
><!--[if mso
]><i
style="mso-font-width: 400%; mso-text-raise: 18"
hidden
>&#8202;&#8202;&#8202;&#8202;</i
><!
[endif]--></span
><span
style="
max-width: 100%;
display: inline-block;
line-height: 120%;
mso-padding-alt: 0px;
mso-text-raise: 9px;
"
>Zum Selfservice Portal</span
><span
><!--[if mso
]><i style="mso-font-width: 400%" hidden
>&#8202;&#8202;&#8202;&#8202;&#8203;</i
><!
[endif]--></span
></a
>
einsehen.
</p>
</td>
</tr>
</tbody>
</table>
<p
style="
font-size: 15px;

View File

@@ -3,6 +3,9 @@ Hallo {{name}} 👋
vielen Dank für deine Registrierung beim {{event_name}}
Am Lauftag ({{event_date}}) musst du nur noch deinen Barcode vorzeigen, damit erhältst du deine Läuferkarte.
Der Bürgerlauf findet von 14:00 bis 18:00 Uhr statt.
Der Firmenlauf beginnt um 13:30 Uhr.
Deinen Registrierungs-Code, Rundenzeiten und weitere Infos kannst du jederzeit im Lauf für Kaya! Selfservice unter {{link}} einsehen.
Wir freuen uns schon auf dich und einen erfolgreichen Lauf für Kaya!

View File

@@ -175,7 +175,11 @@
-moz-osx-font-smoothing: grayscale;
"
>
On the day of the run (<strong>{{event_date}}</strong>) you only have to show your barcode to receive your runner's card.
On the day of the run (<strong>{{event_date}}</strong>) you only
have to show your barcode to receive your runner's card.<br />The
<b>Citizens' Run</b> takes place from
<b>2:00 PM to 6:00 PM</b>.<br />The <b>Corporate Run</b> begins at
<b>1:30 PM</b>.
</p>
<table
align="center"
@@ -221,19 +225,69 @@
-moz-osx-font-smoothing: grayscale;
"
>
You can view your registration code, lap times and further information at any time from the
You can view your registration code, lap times and further
information at any time from the Lauf für Kaya! Selfservice
</p>
<table
align="center"
width="100%"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="max-width: 100%; text-align: center; margin-bottom: 20px"
>
<tbody>
<tr style="width: 100%">
<td>
<a
href="{{link}}"
rel="noopener noreferrer nofollow"
style="
color: #111827;
text-decoration: underline;
line-height: 100%;
text-decoration: none;
display: inline-block;
max-width: 100%;
mso-padding-alt: 0px;
color: #ffffff;
background-color: #3a4bdd;
border-color: #3a4bdd;
border-width: 2px;
border-style: solid;
font-size: 14px;
font-weight: 500;
border-radius: 0px;
padding: 12px 32px 12px 32px;
"
target="_blank"
>Lauf für Kaya! Selfservice</a
><span
><!--[if mso
]><i
style="mso-font-width: 400%; mso-text-raise: 18"
hidden
>&#8202;&#8202;&#8202;&#8202;</i
><!
[endif]--></span
><span
style="
max-width: 100%;
display: inline-block;
line-height: 120%;
mso-padding-alt: 0px;
mso-text-raise: 9px;
"
>To the self-service portal</span
><span
><!--[if mso
]><i style="mso-font-width: 400%" hidden
>&#8202;&#8202;&#8202;&#8202;&#8203;</i
><!
[endif]--></span
></a
>
</p>
</td>
</tr>
</tbody>
</table>
<p
style="
font-size: 15px;
@@ -262,7 +316,8 @@
-moz-osx-font-smoothing: grayscale;
"
>
If you have any questions, please reply to this e-mail at any time or write to
If you have any questions, please reply to this e-mail at any time
or write to
<u
><strong
><a

View File

@@ -3,6 +3,9 @@ Hello {{name}} 👋
Thank you for registering for the {{event_name}}
On the day of the run ({{event_date}}) you only have to show your barcode to receive your runner's card.
The Citizens' Run takes place from 2:00 PM to 6:00 PM.
The Corporate Run begins at 1:30 PM.
You can view your registration code, lap times and further information at any time from the Lauf für Kaya! Selfservice at {{link}}.
We look forward to seeing you and to a successful Lauf für Kaya!