Postkutsche
A module that combines PowerDns and Mailcow to create a mail domain with all required entries on both services in a single command.

Install
yarn add postkutsche
or
npm i postkutsche
Basic use
(async () => {
require('dotenv').config();
const {
Postkutsche
} = require("./index.js");
const pk = new Postkutsche({
mailcow: {
url: process.env.MAILCOW_API_URL,
apikey: process.env.MAILCOW_API_KEY
},
powerdns: {
url: process.env.PDNS_API_URL,
apikey: process.env.PDNS_API_KEY
}
});
const info={
nameserver: ['ns1.domain.tld', 'ns2.domain.tld', 'ns3.domain.tld'],
hostmasterEmail: 'hostmaster@domain.tld',
dmarcMail: 'postmaster@domain.tld',
mailDomain: 'domain.tld',
mailServerHostname: 'mail.domain.tld',
defaultMailbox: {
local_part: `max.mustermensch`,
name: `Max Mustermensch`
},
mailServerIp: '2a00:1450:4016:801::2003',
mailServerLegacyIp: '127.0.0.1',
addLetsEncryptCAA: true,
caaReportMail: 'caa.report@domain.tld'
}
await pk.addMailDomain(info);
})();
Need help or missing a feature?
Feel free to contact me via xl9jthv_7bvgakv9o9wg0jabn2ylm91xxrzzgt0e@y.gy in english or german
Links
NPM
Documentation
Code
powerdns-api
NPM
Documentation
Code
mailcow-api
NPM
Documentation
Code
Modules
- postkutsche
Typedefs
- ApiInfo :
object
- Info :
object
postkutsche
postkutsche.Postkutsche
Class representing the Postkutsche client
Kind: static class of postkutsche
new module.exports.Postkutsche(info)
Create a postkutsche client.
Example
(async () => {
require('dotenv').config();
const {
Postkutsche
} = require("./index.js");
const pk = new Postkutsche({
mailcow: {
url: process.env.MAILCOW_API_URL,
apikey: process.env.MAILCOW_API_KEY
},
powerdns: {
url: process.env.PDNS_API_URL,
apikey: process.env.PDNS_API_KEY
}
});
const info={
nameserver: ['ns1.domain.tld', 'ns2.domain.tld', 'ns3.domain.tld'],
hostmasterEmail: 'hostmaster@domain.tld',
dmarcMail: 'postmaster@domain.tld',
mailDomain: 'domain.tld',
mailServerHostname: 'mail.domain.tld',
defaultMailbox: {
local_part: `max.mustermensch`,
name: `Max Mustermensch`
},
mailServerIp: '2a00:1450:4016:801::2003',
mailServerLegacyIp: '127.0.0.1',
addLetsEncryptCAA: true,
caaReportMail: 'caa.report@domain.tld'
}
await pk.addMailDomain(info);
})();
postkutsche.getTLSA(info) ⇒ Array
Kind: instance method of Postkutsche
Returns: Array
- with tlsa records ready to be inserted into powerdns
info | Info | Info object with the necessary information to generate the tlsa records |
Example
await pk.getTLSA({
mailServerHostname: 'mail.domain.tld',
mailServerIp: '2a00:1450:4016:801::2003',
mailServerLegacyIp: '127.0.0.1'
});
postkutsche.genMailDomainRecords(info) ⇒ Array
Kind: instance method of Postkutsche
Returns: Array
- with domain relevant mail records
info | Info | Info object with the necessary information to generate the domain mail records |
Example
pk.genMailDomainRecords({
mailServerHostname: 'mail.domain.tld',
mailDomain: 'domain.tld',
dmarcMail: 'dmarc@domain.tld'
});
postkutsche.addMailDomain(info, [log]) ⇒ Boolean
This will add:
- Mailcow:
- Domain (if not present)
- Mailbox (if not present)
- DKIM Key (if not present)
- Alias: catchall (catchall will relay everything @yourdomain.tld to your Mailbox) (if not present)
- PowerDns:
- Domain (if not present)
- Mail records for the domain (won't touch other records but will overwrite present matching records)
- DNSSEC (if domain wasn't present)
- Create record on mailServerDomain(if not the same as mailDomain) to allow dmarc mails to sent to this domain
Kind: instance method of Postkutsche
Returns: Boolean
- true on success
info | Info | | Info object with the necessary information to create a mail domain on mailcow and the necessary records on powerdns |
[log] | Boolean | true | you can disable logging by setting this to false |
Example
await pk.addMailDomain({
nameserver: ['ns1.domain.tld', 'ns2.domain.tld', 'ns3.domain.tld'],
hostmasterEmail: 'hostmaster@domain.tld',
dmarcMail: 'postmaster@domain.tld',
mailDomain: 'domain.tld',
mailServerHostname: 'mail.domain.tld',
defaultMailbox: {
local_part: `max.mustermensch`,
name: `Max Mustermensch`,
password:`set some good password here`
}
});
postkutsche.addMailServerDnsRecords(info, [log]) ⇒ Boolean
This will add:
- PowerDns:
- Domain for the mailserver hostname (if not present)
- DNSSEC (will replace old dnssec if present)
- TLSA records for the domain (for the creation of the tlsa records you need to have openssl installed. you can specify the path, if it can't be found globally as 'openssl')
- Records for the mailserver
Kind: instance method of Postkutsche
Returns: Boolean
- true on success
info | Info | | Info object with the necessary information to create the relevant records for the mailserver |
[log] | Boolean | true | you can disable logging by setting this to false |
Example
await pk.addMailServerDnsRecords({
nameserver: ['ns1.domain.tld', 'ns2.domain.tld', 'ns3.domain.tld'],
hostmasterEmail: 'hostmaster@domain.tld',
mailServerHostname: 'mail.domain.tld',
mailServerIp: '2a00:1450:4016:801::2003',
mailServerLegacyIp: '127.0.0.1',
addLetsEncryptCAA: true,
caaReportMail: 'caa.report@domain.tld'
});
postkutsche.openpgpHash(localPart)
Creates the front part of the openpgp dns record
Kind: instance method of Postkutsche
localPart | String | local part of your email address (the part before the @ not including the @) |
Example
console.log(pk.openpgpHash('max.mustermensch'));
postkutsche.openpgpRecord(localPart, publicKeyB64) ⇒ OpenpgpRecord
Creates an openpgp dns record
Kind: instance method of Postkutsche
localPart | String | local part of your email address (the part before the @ not including the @) |
publicKeyB64 | String | your publickey in base64 (it should be correct if it includes -----BEGIN PGP PUBLICKEY BLOCK-----) or only contains these characters: A-Z a-z 0-9 + / |
Example
console.log(pk.openpgpRecord('max.mustermensch','-----BEGIN PGP (...)'));
postkutsche.setOpenpgpRecord(localPart, domain, publicKeyB64)
Sets an openpgp record on your powerdns server
Will overwrite key with the same local part
Kind: instance method of Postkutsche
localPart | String | local part of your email address (the part before the @ not including the @) |
domain | String | the domain you want to add the key to |
publicKeyB64 | String | your publickey in base64 (it should be correct if it includes -----BEGIN PGP PUBLICKEY BLOCK-----) or only contains these characters: A-Z a-z 0-9 + / |
Example
await pk.setOpenpgpRecord('max.mustermensch','domain.tld','-----BEGIN PGP (...)');
postkutsche.cleanupAddMailServer(info)
Will delete the complete mailserver domain from powerdns
Kind: instance method of Postkutsche
info | Info | Info object with the necessary information to delete the mailserver domain |
Example
pk.cleanupAddMailServer({mailServerHostname:'mail.domain.tld'});
postkutsche.cleanupAddMailDomain(info)
Will delete a domain from powerdns and mailcow
THIS WILL DELETE YOUR MAILBOX AND EVERYTHING ELSE CONCERNING THIS DOMAIN
Kind: instance method of Postkutsche
info | Info | Info object with the necessary information to create a mail domain on mailcow and the necessary records on powerdns |
Example
await pk.cleanupAddMailDomain({
dmarcMail: 'postmaster@domain.tld',
mailDomain: 'domain.tld',
defaultMailbox: {
local_part: `max.mustermensch`,
name: `Max Mustermensch`
}
});
ApiInfo : object
Kind: global typedef
Properties
mailcow | object |
mailcow.url | string |
mailcow.apikey | string |
powerdns | object |
powerdns.url | String |
powerdns.apikey | String |
Example
{
mailcow: {
url: process.env.MAILCOW_API_URL,
apikey: process.env.MAILCOW_API_KEY
},
powerdns: {
url: process.env.PDNS_API_URL,
apikey: process.env.PDNS_API_KEY
}
}
Info : object
Kind: global typedef
Properties
nameserver | Array.<string> | | array of nameservers for your domain, first ns in the list will be used as primary |
hostmasterEmail | string | | hostnmaster email address |
[dmarcMail] | string | | add mail if you want to get dmarc reports |
mailDomain | string | | the domain you may want to add mail for |
mailServerHostname | String | | the hostname of the mailserver |
defaultMailbox | Object | | |
defaultMailbox.local_part | String | | local part of you mailbox (the part before the @ not including the @) |
defaultMailbox.name | String | | the name of mailbox |
[defaultMailbox.password] | String | RANDOM | will generate a random password for your mailbox if omitted |
mailServerIp | String | | IPv6 address of your mailserver |
mailServerLegacyIp | String | | IPv4 address of your mailserver |
[addLetsEncryptCAA] | Boolean | | enable this option if you are ONLY using letsencrypt certs |
[caaReportMail] | String | | |
[openssl_path] | String | 'openssl' | optional alternative path for openssl |
Example
{
nameserver: ['ns1.domain.tld', 'ns2.domain.tld', 'ns3.domain.tld'],
hostmasterEmail: 'hostmaster@domain.tld',
dmarcMail: 'postmaster@domain.tld',
mailDomain: 'domain.tld',
mailServerHostname: 'mail.domain.tld',
defaultMailbox: {
local_part: `max.mustermensch`,
name: `Max Mustermensch`
},
mailServerIp: '2a00:1450:4016:801::2003',
mailServerLegacyIp: '127.0.0.1',
addLetsEncryptCAA: true,
caaReportMail: 'caa.report@domain.tld'
}