mirror of
https://github.com/directus/directus.git
synced 2026-02-14 07:15:01 -05:00
10
.env.example
10
.env.example
@@ -1,10 +0,0 @@
|
||||
PORT=3000
|
||||
|
||||
DB_CLIENT="pg"
|
||||
DB_HOST="localhost"
|
||||
DB_PORT=5432
|
||||
DB_NAME="directus"
|
||||
DB_USER="postgres"
|
||||
DB_PASSWORD="psql1234"
|
||||
|
||||
EXTENSIONS_PATH="./extensions"
|
||||
29
example.env
Normal file
29
example.env
Normal file
@@ -0,0 +1,29 @@
|
||||
# General
|
||||
PORT=3000
|
||||
|
||||
# Database
|
||||
DB_CLIENT="pg"
|
||||
DB_HOST="localhost"
|
||||
DB_PORT=5432
|
||||
DB_NAME="directus"
|
||||
DB_USER="postgres"
|
||||
DB_PASSWORD="psql1234"
|
||||
|
||||
# Extensions
|
||||
EXTENSIONS_PATH="./extensions"
|
||||
|
||||
# Email
|
||||
EMAIL_TRANSPORT="sendmail"
|
||||
|
||||
## Email (Sendmail Transport)
|
||||
EMAIL_SENDMAIL_NEW_LINE="unix"
|
||||
EMAIL_SENDMAIL_PATH="/usr/sbin/sendmail"
|
||||
|
||||
## Email (SMTP Transport)
|
||||
EMAIL_SMTP_POOL=true
|
||||
EMAIL_SMTP_HOST="localhost"
|
||||
EMAIL_SMTP_PORT=465
|
||||
EMAIL_SMTP_SECURE=false # Use TLS
|
||||
EMAIL_SMTP_USER="username"
|
||||
EMAIL_SMTP_PASSWORD="password"
|
||||
|
||||
180
package-lock.json
generated
180
package-lock.json
generated
@@ -119,6 +119,15 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz",
|
||||
"integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA=="
|
||||
},
|
||||
"@types/nodemailer": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.0.tgz",
|
||||
"integrity": "sha512-KY7bFWB0MahRZvVW4CuW83qcCDny59pJJ0MQ5ifvfcjNwPlIT0vW4uARO4u1gtkYnWdhSvURegecY/tzcukJcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
||||
@@ -722,6 +731,17 @@
|
||||
"string-width": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
@@ -826,6 +846,28 @@
|
||||
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
|
||||
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
|
||||
},
|
||||
"copyfiles": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.3.0.tgz",
|
||||
"integrity": "sha512-73v7KFuDFJ/ofkQjZBMjMBFWGgkS76DzXvBMUh7djsMOE5EELWtAO/hRB6Wr5Vj5Zg+YozvoHemv0vnXpqxmOQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.0.5",
|
||||
"minimatch": "^3.0.3",
|
||||
"mkdirp": "^1.0.4",
|
||||
"noms": "0.0.0",
|
||||
"through2": "^2.0.1",
|
||||
"yargs": "^15.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
@@ -1677,6 +1719,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"dev": true
|
||||
},
|
||||
"get-own-enumerable-property-symbols": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
|
||||
@@ -2463,6 +2511,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"liquidjs": {
|
||||
"version": "9.12.0",
|
||||
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.12.0.tgz",
|
||||
"integrity": "sha512-Z1fERRy5TG76kNQfDuCl9+YmK6RMBsGhi3fl/57rBb5BbuVAS0YA7R3kh0/V0TwezpeywUf5xasR+Np86nD2TA=="
|
||||
},
|
||||
"listr2": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-2.1.7.tgz",
|
||||
@@ -2963,6 +3016,57 @@
|
||||
"rimraf": "^2.6.1",
|
||||
"semver": "^5.3.0",
|
||||
"tar": "^4"
|
||||
},
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodemailer": {
|
||||
"version": "6.4.10",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.10.tgz",
|
||||
"integrity": "sha512-j+pS9CURhPgk6r0ENr7dji+As2xZiHSvZeVnzKniLOw1eRAyM/7flP0u65tCnsapV8JFu+t0l/5VeHsCZEeh9g=="
|
||||
},
|
||||
"noms": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz",
|
||||
"integrity": "sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "~1.0.31"
|
||||
},
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.0.34",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "~0.10.x"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
@@ -3769,6 +3873,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
|
||||
"dev": true
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
|
||||
@@ -3813,9 +3929,10 @@
|
||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
@@ -4559,6 +4676,14 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4790,6 +4915,12 @@
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"which-module": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
|
||||
"dev": true
|
||||
},
|
||||
"which-pm-runs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
|
||||
@@ -4905,6 +5036,12 @@
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
@@ -4916,6 +5053,43 @@
|
||||
"integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
|
||||
"integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^6.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^4.1.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^4.2.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^18.1.1"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"main": "dist/server.js",
|
||||
"scripts": {
|
||||
"start": "NODE_ENV=production node dist/server.js",
|
||||
"build": "tsc",
|
||||
"build": "rimraf dist && tsc && copyfiles \"src/**/*.*\" -e \"src/**/*.ts\" -u 1 dist",
|
||||
"dev": "LOG_LEVEL=trace ts-node-dev src/server.ts --clear --watch \"src/**/*.ts\" --rs --transpile-only | pino-colada"
|
||||
},
|
||||
"repository": {
|
||||
@@ -29,12 +29,15 @@
|
||||
"homepage": "https://github.com/directus/api-node#readme",
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/nodemailer": "^6.4.0",
|
||||
"@types/pino": "^6.3.0",
|
||||
"copyfiles": "^2.3.0",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"husky": "^4.2.5",
|
||||
"lint-staged": "^10.2.10",
|
||||
"pino-colada": "^1.6.1",
|
||||
"prettier": "^2.0.5",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^8.10.2",
|
||||
"tslint": "^6.1.2",
|
||||
"typescript": "^3.9.5"
|
||||
@@ -56,8 +59,10 @@
|
||||
"express-async-handler": "^1.1.4",
|
||||
"get-port": "^5.1.1",
|
||||
"knex": "^0.21.1",
|
||||
"liquidjs": "^9.12.0",
|
||||
"mssql": "^6.2.0",
|
||||
"mysql": "^2.18.1",
|
||||
"nodemailer": "^6.4.10",
|
||||
"oracledb": "^4.2.0",
|
||||
"pg": "^8.2.1",
|
||||
"pino": "^6.3.2",
|
||||
|
||||
@@ -23,6 +23,15 @@ import webhooksRouter from './routes/webhooks';
|
||||
|
||||
import notFoundHandler from './routes/not-found';
|
||||
|
||||
// import sendMail from './mail';
|
||||
|
||||
// sendMail({
|
||||
// to: 'rijkvanzanten@me.com',
|
||||
// subject: 'Test Email',
|
||||
// text: 'Hi there!',
|
||||
// html: '<h1>Hi there!</h1>',
|
||||
// });
|
||||
|
||||
const app = express()
|
||||
.disable('x-powered-by')
|
||||
.use(bodyParser.json())
|
||||
|
||||
70
src/mail/index.ts
Normal file
70
src/mail/index.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import logger from '../logger';
|
||||
import nodemailer, { Transporter } from 'nodemailer';
|
||||
import { Liquid } from 'liquidjs';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { promisify } from 'util';
|
||||
|
||||
const readFile = promisify(fs.readFile);
|
||||
|
||||
const liquidEngine = new Liquid();
|
||||
|
||||
logger.trace('[Email] Initializing email transport...');
|
||||
|
||||
if (!process.env.EMAIL_TRANSPORT) {
|
||||
logger.warn(`[Email] No email transport is configured. Using default: sendmail.`);
|
||||
}
|
||||
|
||||
const emailTransport = process.env.EMAIL_TRANSPORT || 'sendmail';
|
||||
|
||||
let transporter: Transporter;
|
||||
|
||||
if (emailTransport === 'sendmail') {
|
||||
transporter = nodemailer.createTransport({
|
||||
sendmail: true,
|
||||
newline: process.env.EMAIL_SENDMAIL_NEW_LINE || 'unix',
|
||||
path: process.env.EMAIL_SENDMAIL_PATH || '/usr/sbin/sendmail',
|
||||
});
|
||||
} else if (emailTransport.toLowerCase() === 'smtp') {
|
||||
transporter = nodemailer.createTransport({
|
||||
pool: process.env.EMAIL_SMTP_POOL === 'true',
|
||||
host: process.env.EMAIL_SMTP_HOST,
|
||||
port: Number(process.env.EMAIL_SMTP_PORT),
|
||||
secure: process.env.EMAIL_SMTP_SECURE === 'true',
|
||||
auth: {
|
||||
user: process.env.EMAIL_SMTP_USER,
|
||||
pass: process.env.EMAIL_SMTP_PASSWORD,
|
||||
},
|
||||
} as any);
|
||||
|
||||
logger.trace('[Email] Verifying SMTP connection.');
|
||||
|
||||
transporter
|
||||
.verify()
|
||||
.then(() => {
|
||||
logger.info('[Email] SMTP connected. Ready to send emails.');
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.error(`[Email] Couldn't connect to SMTP server:`);
|
||||
logger.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
export type EmailOptions = {
|
||||
to: string; // email address of the recipient
|
||||
subject: string;
|
||||
text: string;
|
||||
html: string;
|
||||
};
|
||||
|
||||
export default async function sendMail(options: EmailOptions) {
|
||||
const templateString = await readFile(path.join(__dirname, 'templates/base.liquid'), 'utf8');
|
||||
const html = await liquidEngine.parseAndRender(templateString, { html: options.html });
|
||||
|
||||
try {
|
||||
await transporter.sendMail({ ...options, html: html });
|
||||
} catch (error) {
|
||||
logger.warn('[Email] Unexpected error while sending an email:');
|
||||
logger.warn(error);
|
||||
}
|
||||
}
|
||||
72
src/mail/templates/base.liquid
Normal file
72
src/mail/templates/base.liquid
Normal file
@@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Directus Email Service</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<style type="text/css">
|
||||
a {
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
color: #2196f3;
|
||||
outline: none !important;
|
||||
color: #2196f3 !important;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #2196f3 !important;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 20px 0 20px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body
|
||||
style="margin: 0; padding: 20px; background-color: #eceff1; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; -ms-text-size-adjust: none; font-weight: 400; font-size: 14px; color: #546e7a; font-family: 'Roboto', Helvetica, Helvetica, Arial, sans-serif; letter-spacing: 0;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td style="padding: 0;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600"
|
||||
style="border: 0 solid #263238; border-collapse: collapse;">
|
||||
<tr>
|
||||
<td align="center" bgcolor="#263238"
|
||||
style="padding: 30px 0 30px 0; border-radius: 4px 4px 0 0;">
|
||||
<img src="https://directus.io/assets/directus-white.png" alt="Directus" width="130"
|
||||
style="display: block;" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" style="padding: 60px 30px 60px 30px; border-radius: 0 0 4px 4px;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td
|
||||
style="color: #546e7a; font-family: Helvetica, Arial, sans-serif; padding: 0; line-height: 1.5; font-size: 16px;">
|
||||
{% block content %}{{ html }}{% endblock %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#eceff1" style="padding: 20px 30px 0 32px;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td style="color:#b0bec5; font-family:Helvetica, Arial, sans-serif; font-size:12px;"
|
||||
width="75%">
|
||||
{% block footer %}{% endblock %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user