Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auto-send invitation letter #2

Draft
wants to merge 3 commits into
base: saga
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cdk/container/inkscape/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM ubuntu:22.04 AS base

ENV DEBIAN_FRONTEND=noninteractive

RUN <<EOT
apt-get -y update
apt-get -y upgrade
apt-get -y install inkscape fonts-alegreya-sans
apt-get -y clean
rm -rf /var/lib/apt/lists/*
EOT

90 changes: 90 additions & 0 deletions invitation-letter/send-letter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb";
import { SendRawEmailCommand, SESClient } from "@aws-sdk/client-ses";
import { unmarshall } from "@aws-sdk/util-dynamodb";
import run from "@bifravst/run";
import { fromEnv } from "@nordicsemiconductor/from-env";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { CC, From } from "../lambdas/emails.ts";

const registrationId = process.argv[process.argv.length - 1] as string;

const { RegistrationsTableName } = fromEnv({
RegistrationsTableName: "REGISTRATIONS_TABLE_NAME",
})(process.env);

const db = new DynamoDBClient({});
const ses = new SESClient({});
const { Item } = await db.send(
new GetItemCommand({
TableName: RegistrationsTableName,
Key: {
id: { S: registrationId },
},
})
);
if (!Item) {
throw new Error(`Registration ${registrationId} not found`);
}

const registration = unmarshall(Item);

console.log(registration);

const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "invitation-letters-"));
const template = await fs.readFile(
path.join(process.cwd(), "invitation-letter", "template.svg"),
"utf-8"
);

const outFile = `invitation-letter-${registrationId}.pdf`;
const out = path.join(tempDir, outFile);
const infile = path.join(tempDir, "invitation-letter.svg");

await fs.writeFile(
infile,
template
.replaceAll("{{ DATE }}", new Date().toISOString().slice(0, 10))
.replaceAll("{{ NAME }}", registration.name)
.replaceAll("{{ REGISTRATION_ID }}", registration.id)
.replaceAll("{{ CODEFREEZE_DATE }}", "Sat Jan 11th - Sat 18th 2025") // FIXME: make dynamic
);

console.log(
await run({
command: "inkscape",
args: [`--export-filename=${out}`, infile],
})
);

const boundary = "NextPart";
let rawEmail = `From: ${From}\n`;
rawEmail += `To: ${`"${registration.name}" <${registration.email}>`}\n`;
rawEmail += `Cc: ${CC}\n`;
rawEmail += `Reply-To: ${CC}\n`;
rawEmail += `Subject: [codefreeze.fi] Your invitation letter for your registration ${registrationId}\n`;
rawEmail += `MIME-Version: 1.0\n`;
rawEmail += `Content-Type: multipart/mixed; boundary="${boundary}"\n\n`;
rawEmail += `--${boundary}\n`;
rawEmail += `Content-Type: text/plain; charset="UTF-8"\n\n`;
rawEmail += `${[
`Hei ${registration.name},`,
`Please find attached your invitation letter.`,
`Please do no hesitate to reach out to us if you have any questions.`,
`❄`,
].join("\n\n")}\n\n`;
rawEmail += `--${boundary}\n`;
rawEmail += `Content-Type: application/pdf ; name="${outFile}"\n`;
rawEmail += `Content-Disposition: attachment; filename="${outFile}"\n`;
rawEmail += `Content-Transfer-Encoding: base64\n\n`;
rawEmail += `${Buffer.from(await fs.readFile(out)).toString("base64")}\n\n`;
rawEmail += `--${boundary}--`;

await ses.send(
new SendRawEmailCommand({
RawMessage: {
Data: Buffer.from(rawEmail),
},
})
);
Loading