mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2024-10-02 00:02:54 +00:00
feat: Adapt Desired DNS Records checking for Digital Ocean
This commit is contained in:
parent
120a8fc644
commit
3b962c5f5a
|
@ -189,6 +189,88 @@ class CloudflareApi extends DnsProviderApi {
|
||||||
return allRecords;
|
return allRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<DesiredDnsRecord> getDesiredDnsRecords({
|
||||||
|
final String? domainName,
|
||||||
|
final String? ipAddress,
|
||||||
|
final String? dkimPublicKey,
|
||||||
|
}) {
|
||||||
|
if (domainName == null || ipAddress == null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: domainName,
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.root',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'api.$domainName',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.api',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'cloud.$domainName',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.cloud',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'git.$domainName',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.git',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'meet.$domainName',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.meet',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'social.$domainName',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.social',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'password.$domainName',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.password',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'vpn.$domainName',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.vpn',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: domainName,
|
||||||
|
content: domainName,
|
||||||
|
description: 'record.mx',
|
||||||
|
type: 'MX',
|
||||||
|
category: DnsRecordsCategory.email,
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: '_dmarc.$domainName',
|
||||||
|
content: 'v=DMARC1; p=none',
|
||||||
|
description: 'record.dmarc',
|
||||||
|
type: 'TXT',
|
||||||
|
category: DnsRecordsCategory.email,
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: domainName,
|
||||||
|
content: 'v=spf1 a mx ip4:$ipAddress -all',
|
||||||
|
description: 'record.spf',
|
||||||
|
type: 'TXT',
|
||||||
|
category: DnsRecordsCategory.email,
|
||||||
|
),
|
||||||
|
if (dkimPublicKey != null)
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'selector._domainkey.$domainName',
|
||||||
|
content: dkimPublicKey,
|
||||||
|
description: 'record.dkim',
|
||||||
|
type: 'TXT',
|
||||||
|
category: DnsRecordsCategory.email,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APIGenericResult<void>> createMultipleDnsRecords({
|
Future<APIGenericResult<void>> createMultipleDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
enum DnsRecordsCategory {
|
||||||
|
services,
|
||||||
|
email,
|
||||||
|
other,
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesiredDnsRecord {
|
||||||
|
const DesiredDnsRecord({
|
||||||
|
required this.name,
|
||||||
|
required this.content,
|
||||||
|
this.type = 'A',
|
||||||
|
this.description = '',
|
||||||
|
this.category = DnsRecordsCategory.services,
|
||||||
|
this.isSatisfied = false,
|
||||||
|
this.displayName,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String name;
|
||||||
|
final String type;
|
||||||
|
final String content;
|
||||||
|
final String description;
|
||||||
|
final String? displayName;
|
||||||
|
final DnsRecordsCategory category;
|
||||||
|
final bool isSatisfied;
|
||||||
|
|
||||||
|
DesiredDnsRecord copyWith({
|
||||||
|
final String? name,
|
||||||
|
final String? type,
|
||||||
|
final String? content,
|
||||||
|
final String? description,
|
||||||
|
final String? displayName,
|
||||||
|
final DnsRecordsCategory? category,
|
||||||
|
final bool? isSatisfied,
|
||||||
|
}) =>
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: name ?? this.name,
|
||||||
|
type: type ?? this.type,
|
||||||
|
content: content ?? this.content,
|
||||||
|
description: description ?? this.description,
|
||||||
|
category: category ?? this.category,
|
||||||
|
isSatisfied: isSatisfied ?? this.isSatisfied,
|
||||||
|
displayName: displayName ?? this.displayName,
|
||||||
|
);
|
||||||
|
}
|
|
@ -171,6 +171,96 @@ class DigitalOceanDnsApi extends DnsProviderApi {
|
||||||
return allRecords;
|
return allRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<DesiredDnsRecord> getDesiredDnsRecords({
|
||||||
|
final String? domainName,
|
||||||
|
final String? ipAddress,
|
||||||
|
final String? dkimPublicKey,
|
||||||
|
}) {
|
||||||
|
if (domainName == null || ipAddress == null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: '@',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.root',
|
||||||
|
displayName: domainName,
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'api',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.api',
|
||||||
|
displayName: 'api.$domainName',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'cloud',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.cloud',
|
||||||
|
displayName: 'cloud.$domainName',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'git',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.git',
|
||||||
|
displayName: 'git.$domainName',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'meet',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.meet',
|
||||||
|
displayName: 'meet.$domainName',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'social',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.social',
|
||||||
|
displayName: 'social.$domainName',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'password',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.password',
|
||||||
|
displayName: 'password.$domainName',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'vpn',
|
||||||
|
content: ipAddress,
|
||||||
|
description: 'record.vpn',
|
||||||
|
displayName: 'vpn.$domainName',
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: domainName,
|
||||||
|
content: domainName,
|
||||||
|
description: 'record.mx',
|
||||||
|
type: 'MX',
|
||||||
|
category: DnsRecordsCategory.email,
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: '_dmarc.$domainName',
|
||||||
|
content: 'v=DMARC1; p=none',
|
||||||
|
description: 'record.dmarc',
|
||||||
|
type: 'TXT',
|
||||||
|
category: DnsRecordsCategory.email,
|
||||||
|
),
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: domainName,
|
||||||
|
content: 'v=spf1 a mx ip4:$ipAddress -all',
|
||||||
|
description: 'record.spf',
|
||||||
|
type: 'TXT',
|
||||||
|
category: DnsRecordsCategory.email,
|
||||||
|
),
|
||||||
|
if (dkimPublicKey != null)
|
||||||
|
DesiredDnsRecord(
|
||||||
|
name: 'selector._domainkey.$domainName',
|
||||||
|
content: dkimPublicKey,
|
||||||
|
description: 'record.dkim',
|
||||||
|
type: 'TXT',
|
||||||
|
category: DnsRecordsCategory.email,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APIGenericResult<void>> createMultipleDnsRecords({
|
Future<APIGenericResult<void>> createMultipleDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||||
|
|
||||||
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
|
export 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
|
||||||
|
|
||||||
class DomainNotFoundException implements Exception {
|
class DomainNotFoundException implements Exception {
|
||||||
DomainNotFoundException(this.message);
|
DomainNotFoundException(this.message);
|
||||||
|
@ -14,6 +16,11 @@ abstract class DnsProviderApi extends ApiMap {
|
||||||
Future<List<DnsRecord>> getDnsRecords({
|
Future<List<DnsRecord>> getDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
});
|
});
|
||||||
|
List<DesiredDnsRecord> getDesiredDnsRecords({
|
||||||
|
final String? domainName,
|
||||||
|
final String? ipAddress,
|
||||||
|
final String? dkimPublicKey,
|
||||||
|
});
|
||||||
Future<APIGenericResult<void>> removeSimilarRecords({
|
Future<APIGenericResult<void>> removeSimilarRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
final String? ip4,
|
||||||
|
|
|
@ -25,11 +25,14 @@ class DnsRecordsCubit
|
||||||
emit(
|
emit(
|
||||||
DnsRecordsState(
|
DnsRecordsState(
|
||||||
dnsState: DnsRecordsStatus.refreshing,
|
dnsState: DnsRecordsStatus.refreshing,
|
||||||
dnsRecords: getDesiredDnsRecords(
|
dnsRecords: ApiController.currentDnsProviderApiFactory!
|
||||||
serverInstallationCubit.state.serverDomain?.domainName,
|
.getDnsProvider()
|
||||||
'',
|
.getDesiredDnsRecords(
|
||||||
'',
|
domainName:
|
||||||
),
|
serverInstallationCubit.state.serverDomain?.domainName,
|
||||||
|
dkimPublicKey: '',
|
||||||
|
ipAddress: '',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -44,16 +47,23 @@ class DnsRecordsCubit
|
||||||
.getDnsRecords(domain: domain);
|
.getDnsRecords(domain: domain);
|
||||||
final String? dkimPublicKey =
|
final String? dkimPublicKey =
|
||||||
extractDkimRecord(await api.getDnsRecords())?.content;
|
extractDkimRecord(await api.getDnsRecords())?.content;
|
||||||
final List<DesiredDnsRecord> desiredRecords =
|
final List<DesiredDnsRecord> desiredRecords = ApiController
|
||||||
getDesiredDnsRecords(domain.domainName, ipAddress, dkimPublicKey);
|
.currentDnsProviderApiFactory!
|
||||||
|
.getDnsProvider()
|
||||||
|
.getDesiredDnsRecords(
|
||||||
|
domainName: domain.domainName,
|
||||||
|
ipAddress: ipAddress,
|
||||||
|
dkimPublicKey: dkimPublicKey,
|
||||||
|
);
|
||||||
final List<DesiredDnsRecord> foundRecords = [];
|
final List<DesiredDnsRecord> foundRecords = [];
|
||||||
for (final DesiredDnsRecord record in desiredRecords) {
|
for (final DesiredDnsRecord desiredRecord in desiredRecords) {
|
||||||
if (record.description == 'record.dkim') {
|
if (desiredRecord.description == 'record.dkim') {
|
||||||
final DnsRecord foundRecord = records.firstWhere(
|
final DnsRecord foundRecord = records.firstWhere(
|
||||||
(final r) => r.name == record.name && r.type == record.type,
|
(final r) =>
|
||||||
|
r.name == desiredRecord.name && r.type == desiredRecord.type,
|
||||||
orElse: () => DnsRecord(
|
orElse: () => DnsRecord(
|
||||||
name: record.name,
|
name: desiredRecord.name,
|
||||||
type: record.type,
|
type: desiredRecord.type,
|
||||||
content: '',
|
content: '',
|
||||||
ttl: 800,
|
ttl: 800,
|
||||||
proxied: false,
|
proxied: false,
|
||||||
|
@ -65,22 +75,22 @@ class DnsRecordsCubit
|
||||||
final String? foundContent =
|
final String? foundContent =
|
||||||
foundRecord.content?.replaceAll(RegExp(r'\s+'), '');
|
foundRecord.content?.replaceAll(RegExp(r'\s+'), '');
|
||||||
final String content =
|
final String content =
|
||||||
record.content.replaceAll(RegExp(r'\s+'), '');
|
desiredRecord.content.replaceAll(RegExp(r'\s+'), '');
|
||||||
if (foundContent == content) {
|
if (foundContent == content) {
|
||||||
foundRecords.add(record.copyWith(isSatisfied: true));
|
foundRecords.add(desiredRecord.copyWith(isSatisfied: true));
|
||||||
} else {
|
} else {
|
||||||
foundRecords.add(record.copyWith(isSatisfied: false));
|
foundRecords.add(desiredRecord.copyWith(isSatisfied: false));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (records.any(
|
if (records.any(
|
||||||
(final r) =>
|
(final r) =>
|
||||||
r.name == record.name &&
|
r.name == desiredRecord.name &&
|
||||||
r.type == record.type &&
|
r.type == desiredRecord.type &&
|
||||||
r.content == record.content,
|
r.content == desiredRecord.content,
|
||||||
)) {
|
)) {
|
||||||
foundRecords.add(record.copyWith(isSatisfied: true));
|
foundRecords.add(desiredRecord.copyWith(isSatisfied: true));
|
||||||
} else {
|
} else {
|
||||||
foundRecords.add(record.copyWith(isSatisfied: false));
|
foundRecords.add(desiredRecord.copyWith(isSatisfied: false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
|
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
||||||
import 'package:selfprivacy/utils/network_utils.dart';
|
|
||||||
|
|
||||||
class DnsDetailsPage extends StatefulWidget {
|
class DnsDetailsPage extends StatefulWidget {
|
||||||
const DnsDetailsPage({super.key});
|
const DnsDetailsPage({super.key});
|
||||||
|
@ -109,9 +109,12 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
|
||||||
heroIcon: BrandIcons.globe,
|
heroIcon: BrandIcons.globe,
|
||||||
heroTitle: 'domain.screen_title'.tr(),
|
heroTitle: 'domain.screen_title'.tr(),
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_getStateCard(dnsCubit.dnsState, () {
|
_getStateCard(
|
||||||
context.read<DnsRecordsCubit>().fix();
|
dnsCubit.dnsState,
|
||||||
}),
|
() {
|
||||||
|
context.read<DnsRecordsCubit>().fix();
|
||||||
|
},
|
||||||
|
),
|
||||||
const SizedBox(height: 16.0),
|
const SizedBox(height: 16.0),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
|
@ -150,7 +153,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
|
||||||
dnsRecord.description.tr(),
|
dnsRecord.description.tr(),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
dnsRecord.name,
|
dnsRecord.displayName ?? dnsRecord.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,128 +1,6 @@
|
||||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
enum DnsRecordsCategory {
|
|
||||||
services,
|
|
||||||
email,
|
|
||||||
other,
|
|
||||||
}
|
|
||||||
|
|
||||||
class DesiredDnsRecord {
|
|
||||||
const DesiredDnsRecord({
|
|
||||||
required this.name,
|
|
||||||
required this.content,
|
|
||||||
this.type = 'A',
|
|
||||||
this.description = '',
|
|
||||||
this.category = DnsRecordsCategory.services,
|
|
||||||
this.isSatisfied = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String name;
|
|
||||||
final String type;
|
|
||||||
final String content;
|
|
||||||
final String description;
|
|
||||||
final DnsRecordsCategory category;
|
|
||||||
final bool isSatisfied;
|
|
||||||
|
|
||||||
DesiredDnsRecord copyWith({
|
|
||||||
final String? name,
|
|
||||||
final String? type,
|
|
||||||
final String? content,
|
|
||||||
final String? description,
|
|
||||||
final DnsRecordsCategory? category,
|
|
||||||
final bool? isSatisfied,
|
|
||||||
}) =>
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: name ?? this.name,
|
|
||||||
type: type ?? this.type,
|
|
||||||
content: content ?? this.content,
|
|
||||||
description: description ?? this.description,
|
|
||||||
category: category ?? this.category,
|
|
||||||
isSatisfied: isSatisfied ?? this.isSatisfied,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DesiredDnsRecord> getDesiredDnsRecords(
|
|
||||||
final String? domainName,
|
|
||||||
final String? ipAddress,
|
|
||||||
final String? dkimPublicKey,
|
|
||||||
) {
|
|
||||||
if (domainName == null || ipAddress == null) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: domainName,
|
|
||||||
content: ipAddress,
|
|
||||||
description: 'record.root',
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: 'api.$domainName',
|
|
||||||
content: ipAddress,
|
|
||||||
description: 'record.api',
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: 'cloud.$domainName',
|
|
||||||
content: ipAddress,
|
|
||||||
description: 'record.cloud',
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: 'git.$domainName',
|
|
||||||
content: ipAddress,
|
|
||||||
description: 'record.git',
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: 'meet.$domainName',
|
|
||||||
content: ipAddress,
|
|
||||||
description: 'record.meet',
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: 'social.$domainName',
|
|
||||||
content: ipAddress,
|
|
||||||
description: 'record.social',
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: 'password.$domainName',
|
|
||||||
content: ipAddress,
|
|
||||||
description: 'record.password',
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: 'vpn.$domainName',
|
|
||||||
content: ipAddress,
|
|
||||||
description: 'record.vpn',
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: domainName,
|
|
||||||
content: domainName,
|
|
||||||
description: 'record.mx',
|
|
||||||
type: 'MX',
|
|
||||||
category: DnsRecordsCategory.email,
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: '_dmarc.$domainName',
|
|
||||||
content: 'v=DMARC1; p=none',
|
|
||||||
description: 'record.dmarc',
|
|
||||||
type: 'TXT',
|
|
||||||
category: DnsRecordsCategory.email,
|
|
||||||
),
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: domainName,
|
|
||||||
content: 'v=spf1 a mx ip4:$ipAddress -all',
|
|
||||||
description: 'record.spf',
|
|
||||||
type: 'TXT',
|
|
||||||
category: DnsRecordsCategory.email,
|
|
||||||
),
|
|
||||||
if (dkimPublicKey != null)
|
|
||||||
DesiredDnsRecord(
|
|
||||||
name: 'selector._domainkey.$domainName',
|
|
||||||
content: dkimPublicKey,
|
|
||||||
description: 'record.dkim',
|
|
||||||
type: 'TXT',
|
|
||||||
category: DnsRecordsCategory.email,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
DnsRecord? extractDkimRecord(final List<DnsRecord> records) {
|
DnsRecord? extractDkimRecord(final List<DnsRecord> records) {
|
||||||
DnsRecord? dkimRecord;
|
DnsRecord? dkimRecord;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue