-
Notifications
You must be signed in to change notification settings - Fork 205
Expand file tree
/
Copy pathcleanup-truth-sources.js
More file actions
119 lines (104 loc) · 3.25 KB
/
Copy pathcleanup-truth-sources.js
File metadata and controls
119 lines (104 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
* Copyright (c) Forward Email LLC
* SPDX-License-Identifier: BUSL-1.1
*/
// eslint-disable-next-line import/no-unassigned-import
require('#config/env');
const process = require('node:process');
// eslint-disable-next-line import/no-unassigned-import
require('#config/env');
// eslint-disable-next-line import/no-unassigned-import
require('#config/mongoose');
const Graceful = require('@ladjs/graceful');
const mongoose = require('mongoose');
const isFQDN = require('is-fqdn');
const Redis = require('@ladjs/redis');
const sharedConfig = require('@ladjs/shared-config');
const Domains = require('#models/domains');
const config = require('#config');
const createTangerine = require('#helpers/create-tangerine');
const parseRootDomain = require('#helpers/parse-root-domain');
const setupMongoose = require('#helpers/setup-mongoose');
const logger = require('#helpers/logger');
const isTimeoutError = require('#helpers/is-timeout-error');
const breeSharedConfig = sharedConfig('BREE');
const client = new Redis(breeSharedConfig.redis, logger);
const resolver = createTangerine(client);
const graceful = new Graceful({
redisClients: [client],
mongooses: [mongoose]
});
// <https://github.com/nodejs/node/blob/08dd4b1723b20d56fbedf37d52e736fe09715f80/lib/dns.js#L296-L320>
// <https://docs.rs/c-ares/4.0.3/c_ares/enum.Error.html>
const DNS_RETRY_CODES = new Set([
'EADDRGETNETWORKPARAMS',
'EBADFAMILY',
'EBADFLAGS',
'EBADHINTS',
'EBADNAME',
'EBADQUERY',
'EBADRESP',
'EBADSTR',
'ECANCELED',
'ECANCELLED',
'ECONNREFUSED',
'EDESTRUCTION',
'EFILE',
'EFORMERR',
'ELOADIPHLPAPI',
// NOTE: ENODATA indicates there were no records set for MX or TXT
// 'ENODATA',
'ENOMEM',
'ENONAME',
// NOTE: ENOTFOUND indicates the domain doesn't exist
// (and we don't want to send emails to people that didn't even register it yet)
// 'ENOTFOUND',
'ENOTIMP',
'ENOTINITIALIZED',
'EOF',
'EREFUSED',
// NOTE: ESERVFAIL indicates the NS does not work
'ESERVFAIL',
'ETIMEOUT'
]);
graceful.listen();
(async () => {
await setupMongoose();
for await (const domain of Domains.find({})
.sort({ created_at: -1 })
.cursor()
.addCursorFlag('noCursorTimeout', true)) {
try {
if (!isFQDN(domain.name)) continue;
// domain cannot be one of the trusted senders
const root = parseRootDomain(domain.name);
if (!config.truthSources.has(root)) continue;
// check one more time for mx or txt if non-root match
// get verification results (and any errors too)
const { txt, mx, errors } = await Domains.getVerificationResults(
domain,
resolver
);
const hasDNSError =
Array.isArray(errors) &&
errors.some(
(err) =>
(err.code && DNS_RETRY_CODES.has(err.code)) || isTimeoutError(err)
);
if (!hasDNSError && !txt && !mx) {
// otherwise remove the domain
console.log('removing', domain.name);
await Domains.findByIdAndRemove(domain._id);
continue;
}
// email admins
const err = new TypeError(
`${domain.name} has a truth source of ${root} and is MX and/or TXT verified`
);
await logger.error(err);
} catch (err) {
console.error(err);
}
}
process.exit(0);
})();