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 `
+
+ 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.
+
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.
+