Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
b3d8d186a5
4 changed files with 34 additions and 22 deletions
|
|
@ -20,8 +20,8 @@
|
||||||
"@types/express-ws": "^3.0.5",
|
"@types/express-ws": "^3.0.5",
|
||||||
"@types/mjml": "^4.7.4",
|
"@types/mjml": "^4.7.4",
|
||||||
"@types/mustache": "^4.2.6",
|
"@types/mustache": "^4.2.6",
|
||||||
|
"@types/nodemailer": "^8.0.1",
|
||||||
"@types/sanitize-html": "^2.16.0",
|
"@types/sanitize-html": "^2.16.0",
|
||||||
|
|
||||||
"@types/ws": "^8.18.1",
|
"@types/ws": "^8.18.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
||||||
"@typescript-eslint/parser": "^8.43.0",
|
"@typescript-eslint/parser": "^8.43.0",
|
||||||
|
|
@ -48,17 +48,15 @@
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"express-rate-limit": "^7.5.1",
|
"express-rate-limit": "^7.5.1",
|
||||||
"express-ws": "^5.0.2",
|
"express-ws": "^5.0.2",
|
||||||
|
|
||||||
"localstorage-polyfill": "^1.0.1",
|
"localstorage-polyfill": "^1.0.1",
|
||||||
"mjml": "^4.15.3",
|
"mjml": "^4.15.3",
|
||||||
"mustache": "^4.2.0",
|
"mustache": "^4.2.0",
|
||||||
|
"nodemailer": "^6.10.1",
|
||||||
"nostr-tools": "^2.16.2",
|
"nostr-tools": "^2.16.2",
|
||||||
"postmark": "^4.0.5",
|
|
||||||
"sanitize-html": "^2.17.0",
|
"sanitize-html": "^2.17.0",
|
||||||
"sqlite3": "^5.1.7",
|
"sqlite3": "^5.1.7",
|
||||||
"succinct-async": "^1.0.4",
|
"succinct-async": "^1.0.4",
|
||||||
"ts-node-dev": "^2.0.0",
|
"ts-node-dev": "^2.0.0",
|
||||||
|
|
||||||
"ws": "^8.18.3"
|
"ws": "^8.18.3"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
|
|
||||||
BIN
pnpm-lock.yaml
BIN
pnpm-lock.yaml
Binary file not shown.
14
src/env.ts
14
src/env.ts
|
|
@ -8,8 +8,11 @@ import { routerContext } from '@welshman/router'
|
||||||
if (!process.env.MAILSHIP_URL) throw new Error('MAILSHIP_URL is not defined.')
|
if (!process.env.MAILSHIP_URL) throw new Error('MAILSHIP_URL is not defined.')
|
||||||
if (!process.env.MAILSHIP_NAME) throw new Error('MAILSHIP_NAME is not defined.')
|
if (!process.env.MAILSHIP_NAME) throw new Error('MAILSHIP_NAME is not defined.')
|
||||||
if (!process.env.MAILSHIP_SECRET) throw new Error('MAILSHIP_SECRET is not defined.')
|
if (!process.env.MAILSHIP_SECRET) throw new Error('MAILSHIP_SECRET is not defined.')
|
||||||
if (!process.env.POSTMARK_API_KEY) throw new Error('POSTMARK_API_KEY is not defined.')
|
if (!process.env.SMTP_HOST) throw new Error('SMTP_HOST is not defined.')
|
||||||
if (!process.env.POSTMARK_SENDER_ADDRESS) throw new Error('POSTMARK_SENDER_ADDRESS is not defined.')
|
if (!process.env.SMTP_PORT) throw new Error('SMTP_PORT is not defined.')
|
||||||
|
if (!process.env.SMTP_USER) throw new Error('SMTP_USER is not defined.')
|
||||||
|
if (!process.env.SMTP_PASSWORD) throw new Error('SMTP_PASSWORD is not defined.')
|
||||||
|
if (!process.env.SMTP_FROM) throw new Error('SMTP_FROM is not defined.')
|
||||||
if (!process.env.DEFAULT_RELAYS) throw new Error('DEFAULT_RELAYS is not defined.')
|
if (!process.env.DEFAULT_RELAYS) throw new Error('DEFAULT_RELAYS is not defined.')
|
||||||
if (!process.env.INDEXER_RELAYS) throw new Error('INDEXER_RELAYS is not defined.')
|
if (!process.env.INDEXER_RELAYS) throw new Error('INDEXER_RELAYS is not defined.')
|
||||||
if (!process.env.SEARCH_RELAYS) throw new Error('SEARCH_RELAYS is not defined.')
|
if (!process.env.SEARCH_RELAYS) throw new Error('SEARCH_RELAYS is not defined.')
|
||||||
|
|
@ -20,12 +23,15 @@ export const MAILSHIP_URL = process.env.MAILSHIP_URL
|
||||||
export const MAILSHIP_NAME = process.env.MAILSHIP_NAME
|
export const MAILSHIP_NAME = process.env.MAILSHIP_NAME
|
||||||
export const BASE_URL = process.env.BASE_URL
|
export const BASE_URL = process.env.BASE_URL
|
||||||
export const appSigner = Nip01Signer.fromSecret(process.env.MAILSHIP_SECRET)
|
export const appSigner = Nip01Signer.fromSecret(process.env.MAILSHIP_SECRET)
|
||||||
export const POSTMARK_API_KEY = process.env.POSTMARK_API_KEY
|
|
||||||
export const POSTMARK_SENDER_ADDRESS = process.env.POSTMARK_SENDER_ADDRESS
|
|
||||||
export const DEFAULT_RELAYS = process.env.DEFAULT_RELAYS.split(',').map(normalizeRelayUrl)
|
export const DEFAULT_RELAYS = process.env.DEFAULT_RELAYS.split(',').map(normalizeRelayUrl)
|
||||||
export const INDEXER_RELAYS = process.env.INDEXER_RELAYS.split(',').map(normalizeRelayUrl)
|
export const INDEXER_RELAYS = process.env.INDEXER_RELAYS.split(',').map(normalizeRelayUrl)
|
||||||
export const SEARCH_RELAYS = process.env.SEARCH_RELAYS.split(',').map(normalizeRelayUrl)
|
export const SEARCH_RELAYS = process.env.SEARCH_RELAYS.split(',').map(normalizeRelayUrl)
|
||||||
export const PORT = process.env.PORT
|
export const PORT = process.env.PORT
|
||||||
|
export const SMTP_HOST = process.env.SMTP_HOST
|
||||||
|
export const SMTP_PORT = process.env.SMTP_PORT
|
||||||
|
export const SMTP_USER = process.env.SMTP_USER
|
||||||
|
export const SMTP_PASSWORD = process.env.SMTP_PASSWORD
|
||||||
|
export const SMTP_FROM = process.env.SMTP_FROM
|
||||||
|
|
||||||
appSigner.getPubkey().then(pubkey => {
|
appSigner.getPubkey().then(pubkey => {
|
||||||
console.log(`Running as ${pubkey}`)
|
console.log(`Running as ${pubkey}`)
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,40 @@
|
||||||
import { ServerClient } from 'postmark'
|
import nodemailer from 'nodemailer'
|
||||||
import { POSTMARK_SENDER_ADDRESS, POSTMARK_API_KEY, MAILSHIP_NAME, BASE_URL } from './env.js'
|
import { SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROM, MAILSHIP_NAME, BASE_URL } from './env.js'
|
||||||
import type { Subscription } from './alert.js'
|
import type { Subscription } from './alert.js'
|
||||||
import { render } from './templates.js'
|
import { render } from './templates.js'
|
||||||
|
|
||||||
const client = new ServerClient(POSTMARK_API_KEY)
|
const transporter = nodemailer.createTransport({
|
||||||
|
host: SMTP_HOST,
|
||||||
|
port: Number(SMTP_PORT),
|
||||||
|
secure: true,
|
||||||
|
auth: {
|
||||||
|
user: SMTP_USER,
|
||||||
|
pass: SMTP_PASSWORD,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
export const sendConfirm = (sub: Subscription) => {
|
export const sendConfirm = (sub: Subscription) => {
|
||||||
const href = `${BASE_URL}/confirm?token=${sub.key}`
|
const href = `${BASE_URL}/confirm?token=${sub.key}`
|
||||||
|
|
||||||
return client.sendEmail({
|
return transporter.sendMail({
|
||||||
From: POSTMARK_SENDER_ADDRESS,
|
from: SMTP_FROM,
|
||||||
To: sub.email,
|
to: sub.email,
|
||||||
Subject: 'Confirm your email digest',
|
subject: 'Confirm your email digest',
|
||||||
HtmlBody: `
|
html: `
|
||||||
<h3>Welcome to ${MAILSHIP_NAME}!</h3>
|
<h3>Welcome to ${MAILSHIP_NAME}!</h3>
|
||||||
<p>Please confirm that you would like to receive ${sub.frequency} digests by clicking the link below:</p>
|
<p>Please confirm that you would like to receive ${sub.frequency} digests by clicking the link below:</p>
|
||||||
<p><a href="${href}">Confirm Digest</a></p>
|
<p><a href="${href}">Confirm Digest</a></p>
|
||||||
`,
|
`,
|
||||||
TextBody: `Please confirm that you would like to receive ${sub.frequency} digests by visiting: ${href}`,
|
text: `Please confirm that you would like to receive ${sub.frequency} digests by visiting: ${href}`,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sendDigest = async (sub: Subscription, variables: Record<string, any>) => {
|
export const sendDigest = async (sub: Subscription, variables: Record<string, any>) => {
|
||||||
return client.sendEmail({
|
return transporter.sendMail({
|
||||||
From: POSTMARK_SENDER_ADDRESS,
|
from: SMTP_FROM,
|
||||||
To: sub.email,
|
to: sub.email,
|
||||||
Subject: 'New activity',
|
subject: 'New activity',
|
||||||
HtmlBody: await render('emails/digest.mjml', {
|
html: await render('emails/digest.mjml', {
|
||||||
...variables,
|
...variables,
|
||||||
name: sub.email.split('@')[0],
|
name: sub.email.split('@')[0],
|
||||||
unsubscribeUrl: `${BASE_URL}/unsubscribe?token=${sub.key}`,
|
unsubscribeUrl: `${BASE_URL}/unsubscribe?token=${sub.key}`,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue