diff --git a/assets/scripts/Field.js b/assets/scripts/Field.js index dee58db..1bc84fb 100644 --- a/assets/scripts/Field.js +++ b/assets/scripts/Field.js @@ -10,6 +10,7 @@ export class Field { categoryName = null; isHidden = false; isDisabled = false; + isRequired = false; allowMultiple = false; constructor(key) { @@ -32,6 +33,11 @@ export class Field { // Builder methods + required() { + this.isRequired = true; + return this; + } + label(label) { this.displayName = label; return this; diff --git a/assets/scripts/FieldInputItem.js b/assets/scripts/FieldInputItem.js index 5cd7910..d82cc95 100644 --- a/assets/scripts/FieldInputItem.js +++ b/assets/scripts/FieldInputItem.js @@ -12,8 +12,7 @@ export class FieldInputItem { appendHtml(parent) { const container = document.createElement("div"); - container.style.display = "flex"; - container.style.gap = "0.5rem"; + container.className = "input-container"; if (this.field.allowMultiple) { const wrapper = document.createElement("div"); diff --git a/assets/scripts/records/DkimRecord.js b/assets/scripts/records/DkimRecord.js new file mode 100644 index 0000000..c64a007 --- /dev/null +++ b/assets/scripts/records/DkimRecord.js @@ -0,0 +1,55 @@ +import { TagListRecord } from "./TagListRecord.js"; +import { ConstantTag } from "../tags/ConstantTag.js"; +import { EnumTag } from "../tags/EnumTag.js"; +import { TextTag } from "../tags/TextTag.js"; +import { FlagsTag } from "../tags/FlagsTag.js"; + +export class DkimRecord extends TagListRecord { + static fields = [ + new ConstantTag("v", "DKIM1") + .required() + .hidden() + .pos(0), + + new TextTag("p") + .label("Public key") + .desc("Base64-encoded public key data") + .required() + .pos(1), + + new FlagsTag("t", ["y", "s"]) + .label("Flags") + .desc("Optional extra options that can be enabled") + .options(["Test mode", "Require identical domain in i= and d= tags of DKIM signature (Recommended)"]) + .default("") + .pos(1), + + new EnumTag("h", ["sha1", "sha256"]) + .label("Hash algorithms") + .desc("Which hash algorithms are allowed to be used. If not set, all are allowed") + .options(["SHA-1", "SHA-256"]) + .category("advanced") + .pos(1), + + new TextTag("n") + .label("Note") + .desc("Any extra comments for humans. Not parsed by machines") + .category("advanced") + .default("") + .pos(1), + + new EnumTag("k", ["rsa"]) + .disabled() + .default("rsa") + .pos(1), + + new EnumTag("s", ["*", "email"]) + .disabled() + .default("*") + .pos(1), + ]; + + static categories = { + "advanced": "Advanced", + }; +} diff --git a/assets/scripts/records/DmarcRecord.js b/assets/scripts/records/DmarcRecord.js index 1c797a5..66fe128 100644 --- a/assets/scripts/records/DmarcRecord.js +++ b/assets/scripts/records/DmarcRecord.js @@ -78,9 +78,10 @@ export class DmarcRecord extends TagListRecord { .default(86400) .pos(2), - new Tag("rf") + new EnumTag("rf", ["afrf"]) .disabled() - .default("afrf"), // Other values not supported + .default("afrf") + .pos(2), ]; static categories = { diff --git a/assets/scripts/records/TagListRecord.js b/assets/scripts/records/TagListRecord.js index 526e664..35146a3 100644 --- a/assets/scripts/records/TagListRecord.js +++ b/assets/scripts/records/TagListRecord.js @@ -11,7 +11,7 @@ export class TagListRecord { static createFromFieldInputItems(items) { const tokens = items .filter(item => !item.field.isDisabled && item.isValid()) - .filter(item => !item.field.defaultValue || item.getValue() !== item.field.defaultValue) + .filter(item => item.field.defaultValue === null || item.getValue() !== item.field.defaultValue) .map(input => input.toString()); const text = tokens.join("; "); diff --git a/assets/scripts/spf/Term.js b/assets/scripts/spf/Term.js index 32c6cd3..87e0595 100644 --- a/assets/scripts/spf/Term.js +++ b/assets/scripts/spf/Term.js @@ -3,7 +3,6 @@ import { Field } from "../Field.js"; export class Term extends Field { separator = null; - isRequired = false; position = null; valueRequirement = ValueRequirement.REQUIRED; @@ -41,11 +40,6 @@ export class Term extends Field { // Builder methods - required() { - this.isRequired = true; - return this; - } - pos(i) { this.position = i; return this; diff --git a/assets/scripts/tags/EnumTag.js b/assets/scripts/tags/EnumTag.js index c4eb54f..c2732bb 100644 --- a/assets/scripts/tags/EnumTag.js +++ b/assets/scripts/tags/EnumTag.js @@ -17,9 +17,9 @@ export class EnumTag extends Tag { getInputHtml(id) { return ` ${this.flagLabels[i]} + `).join("") + + ""; + } + + getInputValue() { + return this.flags.map(flag => document.getElementById(this.id + "-" + flag).checked ? flag : "") + .filter(val => val) + .join(":"); + } +} \ No newline at end of file diff --git a/assets/scripts/tags/IntTag.js b/assets/scripts/tags/IntTag.js index 339c43a..a6146c0 100644 --- a/assets/scripts/tags/IntTag.js +++ b/assets/scripts/tags/IntTag.js @@ -23,7 +23,7 @@ export class IntTag extends Tag { } getInputHtml(id) { - return ``; + return ``; } getInputValue(id) { diff --git a/assets/scripts/tags/Tag.js b/assets/scripts/tags/Tag.js index e1899d1..a663e31 100644 --- a/assets/scripts/tags/Tag.js +++ b/assets/scripts/tags/Tag.js @@ -2,8 +2,8 @@ import { Field } from "../Field.js"; /** A tag within a DMARC/DKIM record */ export class Tag extends Field { - isRequired = false; defaultValue = null; + initialValue = null; position = null; constructor(key) { @@ -34,13 +34,14 @@ export class Tag extends Field { // Builder methods - required() { - this.isRequired = true; + default(value) { + this.defaultValue = value; + this.initialValue = value; return this; } - default(value) { - this.defaultValue = value; + initial(value) { + this.initialValue = value; return this; } diff --git a/assets/scripts/tags/TextTag.js b/assets/scripts/tags/TextTag.js new file mode 100644 index 0000000..a4a5bf5 --- /dev/null +++ b/assets/scripts/tags/TextTag.js @@ -0,0 +1,19 @@ +import { Tag } from "./Tag.js"; + +export class TextTag extends Tag { + constructor(key) { + super(key); + } + + validate(value) { + return true; + } + + getInputHtml(id) { + return ``; + } + + getInputValue(id) { + return document.getElementById(id).value; + } +} diff --git a/assets/scripts/ui/creator.js b/assets/scripts/ui/creator.js index 1004a02..bb00a0e 100644 --- a/assets/scripts/ui/creator.js +++ b/assets/scripts/ui/creator.js @@ -1,7 +1,9 @@ +import { DkimRecord } from "../records/DkimRecord.js"; import { DmarcRecord } from "../records/DmarcRecord.js"; import { SpfRecord } from "../records/SpfRecord.js"; const records = { + "/dkim-creator": DkimRecord, "/dmarc-creator": DmarcRecord, "/spf-creator": SpfRecord, }; diff --git a/assets/styles/main.css b/assets/styles/main.css index 7b389c9..7fca2b5 100644 --- a/assets/styles/main.css +++ b/assets/styles/main.css @@ -31,7 +31,7 @@ h1, h2 { text-align: center; } -label { +body > label { color: #757575; font-size: 0.8rem; } @@ -122,7 +122,7 @@ li:not(:first-of-type) { display: flex; } -form label { +form > label, details > label { color: black; font-weight: bold; display: block; @@ -134,6 +134,7 @@ form input { border: 1px solid #BDBDBD; padding: 0.5rem 1rem; transition: border 200ms; + accent-color: black; } form input:focus { @@ -173,6 +174,12 @@ summary:hover { margin-bottom: 0.5rem; } +.input-container { + display: flex; + gap: 0.5rem; + width: 100%; +} + .text-button { background: none; border: none; diff --git a/dkim-creator/index.html b/dkim-creator/index.html new file mode 100644 index 0000000..59b15ae --- /dev/null +++ b/dkim-creator/index.html @@ -0,0 +1,57 @@ + + + + + + DKIM Record Creator - Generate DKIM DNS Records + + + + +

DKIM Record Creator

+ +
+ + +
+

Create a DKIM DNS Record

+ +

Customize the options below to generate a DKIM record, which will be shown in the input field above.

+ +
+ +
+ +

+ This tool can be used to create DKIM DNS records, which together with a signature header can be used + for authorizing emails. +

+ +

+ When setting up DKIM, you must first generate a public/private key pair. The private key is signed with + the email message and should be automatically included in the DKIM-signature email header, while the + public key should be pasted here in the DKIM DNS record, so that other email servers can verify the + signature. +

+ +

+ Using DKIM prevents your emails from ending up in the receiver's spam folder. It is recommended to also + set up SPF (to authorize certain IP addresses to send mail) and + DMARC (to specify how to handle failed validation), to minimize the risk of + getting your emails flagged as spam. +

+ +

+ This tool only helps with setting up the DNS record. The DKIM-signature email header should be + automatically set by your email provider when sending mails. +

+ +
+

More tools:

+ DKIM Validator Tool • + DMARC Creator Tool • + SPF Creator Tool +
+
+ + diff --git a/dmarc-creator/index.html b/dmarc-creator/index.html index 276703c..6043dd5 100644 --- a/dmarc-creator/index.html +++ b/dmarc-creator/index.html @@ -23,7 +23,7 @@

- This tool allows you to create DMARC DNS records, which can be used when you are hosting an email-server + This tool allows you to create DMARC DNS records, which can be used when you are hosting an email server and want to provide an extra layer of security, so other email providers will trust your emails.

@@ -32,9 +32,16 @@ subdomain (e.g. _dmarc.example.com) with the content being the text above.

+

+ Using DMARC prevents your emails from ending up in the receiver's spam folder by telling email servers + how strictly to handle validation with DKIM and + SPF. It is highly recommended to set up both of these before using DMARC. +

+

More tools:

DMARC Validator Tool • + DKIM Creator ToolSPF Creator Tool
diff --git a/spf-creator/index.html b/spf-creator/index.html index ae98ab9..5b77bc8 100644 --- a/spf-creator/index.html +++ b/spf-creator/index.html @@ -49,9 +49,17 @@ current IP address. See the Macro Guide for a list of all macros.

+

+ Using SPF prevents your emails from ending up in the receiver's spam folder. It is recommended to also + set up DKIM (to authorize emails by signing them cryptographically) and + DMARC (to specify how to handle failed validation), to minimize the risk of + getting your emails flagged as spam. +

+

More tools:

SPF Validator Tool • + DKIM Creator ToolDMARC Creator Tool