mirror of
https://github.com/Lissy93/web-check.git
synced 2024-11-22 16:23:56 +01:00
Adds mail security config section
This commit is contained in:
parent
e3541679c2
commit
ae00af2e24
79
api/mail-config.js
Normal file
79
api/mail-config.js
Normal file
@ -0,0 +1,79 @@
|
||||
const dns = require('dns').promises;
|
||||
const URL = require('url-parse');
|
||||
|
||||
exports.handler = async (event, context) => {
|
||||
try {
|
||||
let domain = event.queryStringParameters.url;
|
||||
const parsedUrl = new URL(domain);
|
||||
domain = parsedUrl.hostname || parsedUrl.pathname;
|
||||
|
||||
// Get MX records
|
||||
const mxRecords = await dns.resolveMx(domain);
|
||||
|
||||
// Get TXT records
|
||||
const txtRecords = await dns.resolveTxt(domain);
|
||||
|
||||
// Filter for only email related TXT records (SPF, DKIM, DMARC, and certain provider verifications)
|
||||
const emailTxtRecords = txtRecords.filter(record => {
|
||||
const recordString = record.join('');
|
||||
return (
|
||||
recordString.startsWith('v=spf1') ||
|
||||
recordString.startsWith('v=DKIM1') ||
|
||||
recordString.startsWith('v=DMARC1') ||
|
||||
recordString.startsWith('protonmail-verification=') ||
|
||||
recordString.startsWith('google-site-verification=') || // Google Workspace
|
||||
recordString.startsWith('MS=') || // Microsoft 365
|
||||
recordString.startsWith('zoho-verification=') || // Zoho
|
||||
recordString.startsWith('titan-verification=') || // Titan
|
||||
recordString.includes('bluehost.com') // BlueHost
|
||||
);
|
||||
});
|
||||
|
||||
// Identify specific mail services
|
||||
const mailServices = emailTxtRecords.map(record => {
|
||||
const recordString = record.join('');
|
||||
if (recordString.startsWith('protonmail-verification=')) {
|
||||
return { provider: 'ProtonMail', value: recordString.split('=')[1] };
|
||||
} else if (recordString.startsWith('google-site-verification=')) {
|
||||
return { provider: 'Google Workspace', value: recordString.split('=')[1] };
|
||||
} else if (recordString.startsWith('MS=')) {
|
||||
return { provider: 'Microsoft 365', value: recordString.split('=')[1] };
|
||||
} else if (recordString.startsWith('zoho-verification=')) {
|
||||
return { provider: 'Zoho', value: recordString.split('=')[1] };
|
||||
} else if (recordString.startsWith('titan-verification=')) {
|
||||
return { provider: 'Titan', value: recordString.split('=')[1] };
|
||||
} else if (recordString.includes('bluehost.com')) {
|
||||
return { provider: 'BlueHost', value: recordString };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}).filter(record => record !== null);
|
||||
|
||||
// Check MX records for Yahoo
|
||||
const yahooMx = mxRecords.filter(record => record.exchange.includes('yahoodns.net'));
|
||||
if (yahooMx.length > 0) {
|
||||
mailServices.push({ provider: 'Yahoo', value: yahooMx[0].exchange });
|
||||
}
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({
|
||||
mxRecords,
|
||||
txtRecords: emailTxtRecords,
|
||||
mailServices,
|
||||
}),
|
||||
};
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOTFOUND' || error.code === 'ENODATA') {
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({ skipped: 'No mail server in use on this domain' }),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
statusCode: 500,
|
||||
body: JSON.stringify({ error: error.message }),
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
45
src/components/Results/MailConfig.tsx
Normal file
45
src/components/Results/MailConfig.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
import { Card } from 'components/Form/Card';
|
||||
import Row from 'components/Form/Row';
|
||||
import Heading from 'components/Form/Heading';
|
||||
import colors from 'styles/colors';
|
||||
|
||||
const cardStyles = ``;
|
||||
|
||||
const MailConfigCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
|
||||
const mailServer = props.data;
|
||||
const txtRecords = (mailServer.txtRecords || []).join('').toLowerCase() || '';
|
||||
return (
|
||||
<Card heading={props.title} actionButtons={props.actionButtons} styles={cardStyles}>
|
||||
<Heading as="h3" color={colors.primary} size="small">Mail Security Checklist</Heading>
|
||||
<Row lbl="SPF" val={txtRecords.includes('spf')} />
|
||||
<Row lbl="DKIM" val={txtRecords.includes('dkim')} />
|
||||
<Row lbl="DMARC" val={txtRecords.includes('dmarc')} />
|
||||
<Row lbl="BIMI" val={txtRecords.includes('bimi')} />
|
||||
|
||||
{ mailServer.mxRecords && <Heading as="h3" color={colors.primary} size="small">MX Records</Heading>}
|
||||
{ mailServer.mxRecords && mailServer.mxRecords.map((record: any) => (
|
||||
<Row lbl="" val="">
|
||||
<span>{record.exchange}</span>
|
||||
<span>{record.priority ? `Priority: ${record.priority}` : ''}</span>
|
||||
</Row>
|
||||
))
|
||||
}
|
||||
{ mailServer.mailServices.length > 0 && <Heading as="h3" color={colors.primary} size="small">External Mail Services</Heading>}
|
||||
{ mailServer.mailServices && mailServer.mailServices.map((service: any) => (
|
||||
<Row lbl={service.provider} val={service.value} />
|
||||
))
|
||||
}
|
||||
|
||||
{ mailServer.txtRecords && <Heading as="h3" color={colors.primary} size="small">Mail-related TXT Records</Heading>}
|
||||
{ mailServer.txtRecords && mailServer.txtRecords.map((record: any) => (
|
||||
<Row lbl="" val="">
|
||||
<span>{record}</span>
|
||||
</Row>
|
||||
))
|
||||
}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default MailConfigCard;
|
@ -194,6 +194,7 @@ const jobNames = [
|
||||
'hosts',
|
||||
'quality',
|
||||
'cookies',
|
||||
'ssl',
|
||||
// 'server-info',
|
||||
'redirects',
|
||||
'robots-txt',
|
||||
@ -207,7 +208,7 @@ const jobNames = [
|
||||
'security-txt',
|
||||
'social-tags',
|
||||
'linked-pages',
|
||||
'mail-server',
|
||||
'mail-config',
|
||||
// 'whois',
|
||||
'features',
|
||||
'carbon',
|
||||
|
@ -47,6 +47,7 @@ import TechStackCard from 'components/Results/TechStack';
|
||||
import SecurityTxtCard from 'components/Results/SecurityTxt';
|
||||
import ContentLinksCard from 'components/Results/ContentLinks';
|
||||
import SocialTagsCard from 'components/Results/SocialTags';
|
||||
import MailConfigCard from 'components/Results/MailConfig';
|
||||
|
||||
import keys from 'utils/get-keys';
|
||||
import { determineAddressType, AddressType } from 'utils/address-type-checker';
|
||||
@ -397,6 +398,14 @@ const Results = (): JSX.Element => {
|
||||
fetchRequest: () => fetch(`${api}/content-links?url=${address}`).then(res => parseJson(res)),
|
||||
});
|
||||
|
||||
// Get mail config for server, based on DNS records
|
||||
const [mailConfigResults, updateMailConfigResults] = useMotherHook({
|
||||
jobId: 'mail-config',
|
||||
updateLoadingJobs,
|
||||
addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly },
|
||||
fetchRequest: () => fetch(`${api}/mail-config?url=${address}`).then(res => parseJson(res)),
|
||||
});
|
||||
|
||||
/* Cancel remaining jobs after 10 second timeout */
|
||||
useEffect(() => {
|
||||
const checkJobs = () => {
|
||||
@ -443,6 +452,7 @@ const Results = (): JSX.Element => {
|
||||
{ id: 'txt-records', title: 'TXT Records', result: txtRecordResults, Component: TxtRecordCard, refresh: updateTxtRecordResults },
|
||||
{ id: 'hsts', title: 'HSTS Check', result: hstsResults, Component: HstsCard, refresh: updateHstsResults },
|
||||
{ id: 'whois', title: 'Domain Info', result: whoIsResults, Component: WhoIsCard, refresh: updateWhoIsResults },
|
||||
{ id: 'mail-config', title: 'Email Configuration', result: mailConfigResults, Component: MailConfigCard, refresh: updateMailConfigResults },
|
||||
{ id: 'dns-server', title: 'DNS Server', result: dnsServerResults, Component: DnsServerCard, refresh: updateDnsServerResults },
|
||||
{ id: 'social-tags', title: 'Social Tags', result: socialTagResults, Component: SocialTagsCard, refresh: updateSocialTagResults },
|
||||
{ id: 'linked-pages', title: 'Linked Pages', result: linkedPagesResults, Component: ContentLinksCard, refresh: updateLinkedPagesResults },
|
||||
|
Loading…
Reference in New Issue
Block a user