Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
4257686f35
|
|||
|
2f25937a94
|
|||
|
658b8d4dd8
|
|||
|
df6381fd5e
|
|||
|
a11e5f2f3e
|
@@ -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:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odit/lfk-mailer",
|
"name": "@odit/lfk-mailer",
|
||||||
"version": "1.2.0",
|
"version": "1.2.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -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,6 +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 { Attachment } from 'nodemailer/lib/mailer'
|
||||||
|
|
||||||
const emailRouter = new Hono()
|
const emailRouter = new Hono()
|
||||||
const emailService = new EmailService()
|
const emailService = new EmailService()
|
||||||
@@ -22,7 +23,7 @@ async function generateBarcodeDataURL(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')
|
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") {
|
||||||
@@ -32,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\nBEGIN:VEVENT\nSUMMARY:Lauf für Kaya! 2025\nDTSTART:20250523T110000Z\nDTEND:20250523T160000Z\nDTSTAMP:20250318T230306Z\nUID:1742338986492-lfk2025\nDESCRIPTION:Der Lauf für Kaya! 2025 findet am 23.05.2025 auf dem Sportplatz des Gymnasium Herzogenaurach statt - Bürgerlauf von 13 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 (templateName === "password-reset") {
|
||||||
if (data.token) {
|
if (data.token) {
|
||||||
@@ -45,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,8 +175,10 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Am Lauftag (<strong>{{event_date}}</strong>) musst du nur noch diesen
|
Am Lauftag (<strong>{{event_date}}</strong>) musst du nur noch
|
||||||
Barcode vorzeigen, damit erhältst du deine Läuferkarte.
|
diesen Barcode vorzeigen, damit erhältst du deine Läuferkarte.<br />Der
|
||||||
|
Bürger- & Firmenlauf findet von
|
||||||
|
<strong>13:00 bis 18:00 Uhr</strong> statt.
|
||||||
</p>
|
</p>
|
||||||
<table
|
<table
|
||||||
align="center"
|
align="center"
|
||||||
@@ -223,20 +225,68 @@
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
Deinen Registrierungs-Code, Rundenzeiten und weitere Infos kannst
|
Deinen Registrierungs-Code, Rundenzeiten und weitere Infos kannst
|
||||||
du jederzeit im
|
du jederzeit im Lauf für Kaya! Selfservice einsehen.
|
||||||
<a
|
|
||||||
href="{{link}}"
|
|
||||||
rel="noopener noreferrer nofollow"
|
|
||||||
style="
|
|
||||||
color: #111827;
|
|
||||||
text-decoration: underline;
|
|
||||||
font-weight: 500;
|
|
||||||
"
|
|
||||||
target="_blank"
|
|
||||||
>Lauf für Kaya! Selfservice</a
|
|
||||||
>
|
|
||||||
einsehen.
|
|
||||||
</p>
|
</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}}"
|
||||||
|
style="
|
||||||
|
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"
|
||||||
|
><span
|
||||||
|
><!--[if mso
|
||||||
|
]><i
|
||||||
|
style="mso-font-width: 400%; mso-text-raise: 18"
|
||||||
|
hidden
|
||||||
|
>    </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
|
||||||
|
>    ​</i
|
||||||
|
><!
|
||||||
|
[endif]--></span
|
||||||
|
></a
|
||||||
|
>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
<p
|
<p
|
||||||
style="
|
style="
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ Hallo {{name}} 👋
|
|||||||
vielen Dank für deine Registrierung beim {{event_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.
|
Am Lauftag ({{event_date}}) musst du nur noch deinen Barcode vorzeigen, damit erhältst du deine Läuferkarte.
|
||||||
|
Der Bürger- & Firmenlauf findet von 13:00 bis 18:00 Uhr statt.
|
||||||
|
|
||||||
Deinen Registrierungs-Code, Rundenzeiten und weitere Infos kannst du jederzeit im Lauf für Kaya! Selfservice unter {{link}} einsehen.
|
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!
|
Wir freuen uns schon auf dich und einen erfolgreichen Lauf für Kaya!
|
||||||
|
|||||||
@@ -160,7 +160,7 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Thank you for registering for the {{event_name}}
|
Thank you for registering for the {{event_name}}
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
style="
|
style="
|
||||||
@@ -175,7 +175,10 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-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
|
||||||
|
Citizens' & Company Run will take place from
|
||||||
|
<strong> 1:00 p.m. to 6:00 p.m.</strong>
|
||||||
</p>
|
</p>
|
||||||
<table
|
<table
|
||||||
align="center"
|
align="center"
|
||||||
@@ -221,18 +224,83 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-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
|
||||||
<a
|
information at any time from the Lauf für Kaya! Selfservice
|
||||||
href="{{link}}"
|
</p>
|
||||||
rel="noopener noreferrer nofollow"
|
<table
|
||||||
style="
|
align="center"
|
||||||
color: #111827;
|
width="100%"
|
||||||
text-decoration: underline;
|
border="0"
|
||||||
font-weight: 500;
|
cellpadding="0"
|
||||||
"
|
cellspacing="0"
|
||||||
target="_blank"
|
role="presentation"
|
||||||
>Lauf für Kaya! Selfservice</a
|
style="max-width: 100%; text-align: center; margin-bottom: 20px"
|
||||||
>
|
>
|
||||||
|
<tbody>
|
||||||
|
<tr style="width: 100%">
|
||||||
|
<td>
|
||||||
|
<a
|
||||||
|
href="{{link}}"
|
||||||
|
style="
|
||||||
|
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"
|
||||||
|
><span
|
||||||
|
><!--[if mso
|
||||||
|
]><i
|
||||||
|
style="mso-font-width: 400%; mso-text-raise: 18"
|
||||||
|
hidden
|
||||||
|
>    </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
|
||||||
|
>    ​</i
|
||||||
|
><!
|
||||||
|
[endif]--></span
|
||||||
|
></a
|
||||||
|
>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p
|
||||||
|
style="
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 24px;
|
||||||
|
margin: 16px 0;
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
margin-top: 0px;
|
||||||
|
color: #374151;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
We look forward to seeing you and to a successful Lauf für Kaya!
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
style="
|
style="
|
||||||
@@ -247,22 +315,8 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
We look forward to seeing you and to a successful Lauf für Kaya!
|
If you have any questions, please reply to this e-mail at any time
|
||||||
</p>
|
or write to
|
||||||
<p
|
|
||||||
style="
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 24px;
|
|
||||||
margin: 16px 0;
|
|
||||||
text-align: left;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
margin-top: 0px;
|
|
||||||
color: #374151;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
If you have any questions, please reply to this e-mail at any time or write to
|
|
||||||
<u
|
<u
|
||||||
><strong
|
><strong
|
||||||
><a
|
><a
|
||||||
@@ -292,7 +346,7 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Sporty Greetings 🏃♂️<br />Your Team Lauf für Kaya!
|
Sporty Greetings 🏃♂️<br />Your Team Lauf für Kaya!
|
||||||
</p>
|
</p>
|
||||||
<hr
|
<hr
|
||||||
style="
|
style="
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ Hello {{name}} 👋
|
|||||||
Thank you for registering for the {{event_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.
|
On the day of the run ({{event_date}}) you only have to show your barcode to receive your runner's card.
|
||||||
|
The Citizens' & Company Run will take place from 1:00 p.m. to 6:00 p.m.
|
||||||
|
|
||||||
You can view your registration code, lap times and further information at any time from the Lauf für Kaya! Selfservice at {{link}}.
|
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!
|
We look forward to seeing you and to a successful Lauf für Kaya!
|
||||||
|
|||||||
Reference in New Issue
Block a user