diff --git a/index.js b/index.js index 81c23fa..f97e2d5 100644 --- a/index.js +++ b/index.js @@ -37,12 +37,15 @@ import { registration } from './src/controllers/registration.controller.js'; import { findAll as getAllEvents } from './src/controllers/event.controller.js'; import { findAll as getAllSettings } from './src/controllers/setting.controller.js'; import { create as createSupporterYear } from './src/controllers/supporterYear.controller.js'; +import { findOne, create } from './src/controllers/mailingListToken.controller.js'; app.get("/", (req, res) => {res.json({ message: "up" });}); app.post('/registration', registration) app.get('/event', getAllEvents); app.get('/setting', getAllSettings); app.post('/supporterYear', createSupporterYear) +app.get('/mailingListToken/:token', findOne) +app.post('/mailingListToken', create) // protected routes import keycloak from './src/config/keycloak.js' diff --git a/src/config/mail.js b/src/config/mail.js index 6b76ec1..3f339b2 100644 --- a/src/config/mail.js +++ b/src/config/mail.js @@ -20,5 +20,6 @@ export default { from: process.env.SMTP_BOOKING_FROM || process.env.SMTP_FROM || "lama@example.com", pass: process.env.SMTP_BOOKING_PASS || process.env.SMTP_PASS || "password", secure: process.env.SMTP_BOOKING_SECURE || process.env.SMTP_SECURE || false, - } + }, + subscribeLists: JSON.parse(process.env.SUBSCRIBE_LISTS || '[]') }; \ No newline at end of file diff --git a/src/controllers/mail.controller.js b/src/controllers/mail.controller.js index 2b23457..9a4a52e 100644 --- a/src/controllers/mail.controller.js +++ b/src/controllers/mail.controller.js @@ -147,9 +147,16 @@ export async function addToMailinglist(mailingList, uuids) { } uuids.forEach(async (uuid) => { console.log(uuid); - const user = await userModel.findByPk(uuid); + let user = {}; + if (uuid.includes('@')) { + user = { + mail: uuid + } + } else { + user = await userModel.findByPk(uuid); + } console.log(user); - if (!user) return; + if (!user.mail) return; mg.lists.members.createMember(mailingList, { address: user.mail || '', name: user.firstName || '' + ' ' + user.lastName || '', @@ -165,7 +172,34 @@ export async function addToTeamMailinglist(uuids, year) { addToMailinglist('team' + year + '@' + (process.env.MAIL_LIST_DOMAIN || 'verteiler.lippesola.de'), uuids); } - +export async function sendNewsletterConfirmMail(mailAddress, token) { + const confirmLink = process.env.LAMA_API_URL + '/mailingListToken/' + token; + const html = '

' + + 'Vielen Dank für deine Anmeldung zum Lippesola Newsletter.
' + + 'Bitte bestätige deine Anmeldung durch Klick auf den folgenden Link:
' + + '' + confirmLink + '' + + '

' + + '

' + + 'Solltest du keine Anmeldung vorgenommen haben, kannst du diese E-Mail ignorieren.' + + '

'; + const transporter = nodemailer.createTransport({ + host: mail.default.host, + port: mail.default.port, + secure: mail.default.secure, + auth: { + user: mail.default.user, + pass: mail.default.pass + } + }); + transporter.sendMail({ + from: '"Lippesola Newsletter" <' + mail.default.from + '>', + to: mailAddress, + subject: 'Newsletter Anmeldung bestätigen', + text: convert(html), + html: html + }); + +} export async function sendMailToParents(orderId, positionId, type) { const participator = await findOneParticipator({params: { diff --git a/src/controllers/mailingListToken.controller.js b/src/controllers/mailingListToken.controller.js new file mode 100644 index 0000000..19eac42 --- /dev/null +++ b/src/controllers/mailingListToken.controller.js @@ -0,0 +1,58 @@ +import mailingListTokenModel from '../models/mailingListToken.model.js' +import { addToMailinglist, sendNewsletterConfirmMail } from './mail.controller.js'; +import mail from '../config/mail.js'; + +function generateToken(length) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const charactersLength = characters.length; + let counter = 0; + while (counter < length) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + counter += 1; + } + return result; +} + +export async function create (req, res) { + if (!req.body || !req.body.mail || !req.body.list) { + res.status(400).send('bad request') + return; + } + if (!mail.subscribeLists.includes(req.body.list)) { + res.status(403).send('you are not allowed to subscribe to this list') + return; + } + const token = generateToken(32) + await mailingListTokenModel.create({ + token: token, + mail: req.body.mail, + list: req.body.list, + valid: true + }) + sendNewsletterConfirmMail(req.body.mail, token) + res.status(200).send() +} + +export async function findOne (req, res) { + if (!req.params || !req.params.token) { + res.status(400).send('bad request') + return; + } + const mailingListToken = await mailingListTokenModel.findByPk(req.params.token) + if (!mailingListToken) { + res.status(404).send('not found') + return; + } + if (!mailingListToken.valid) { + res.status(403).send('invalid mailingListToken') + return; + } + if (!mail.subscribeLists.includes(mailingListToken.list)) { + res.status(403).send('you are not allowed to subscribe to this list') + return; + } + await addToMailinglist(mailingListToken.list, mailingListToken.mail) + await mailingListToken.update({valid: false}) + res.status(200).send("Du wurdest erfolgreich in den Verteiler eingetragen. Dieses Fenster kann geschlossen werden.") +} \ No newline at end of file diff --git a/src/models/mailingListToken.model.js b/src/models/mailingListToken.model.js new file mode 100644 index 0000000..4e0cfb8 --- /dev/null +++ b/src/models/mailingListToken.model.js @@ -0,0 +1,18 @@ +import { DataTypes } from 'sequelize'; +import sequelize from './db.model.js'; + +export default sequelize.define('MailingListToken', { + token: { + type: DataTypes.STRING, + primaryKey: true, + }, + list: { + type: DataTypes.STRING + }, + mail: { + type: DataTypes.STRING + }, + valid: { + type: DataTypes.BOOLEAN + } +}); \ No newline at end of file