87 lines
2.6 KiB
Dart
87 lines
2.6 KiB
Dart
import 'package:sharedinbox/core/models/account.dart';
|
|
import 'package:sharedinbox/core/repositories/account_repository.dart';
|
|
import 'package:sharedinbox/core/utils/logger.dart';
|
|
import 'package:sharedinbox/data/imap/managesieve_client.dart';
|
|
|
|
/// Returns true if the endpoint accepts a ManageSieve handshake.
|
|
typedef ManageSieveProbeFn = Future<bool> Function({
|
|
required String host,
|
|
required int port,
|
|
required bool useTls,
|
|
});
|
|
|
|
Future<bool> _defaultManageSieveProbe({
|
|
required String host,
|
|
required int port,
|
|
required bool useTls,
|
|
}) async {
|
|
try {
|
|
final client = await ManageSieveClient.connect(
|
|
host: host,
|
|
port: port,
|
|
useTls: useTls,
|
|
);
|
|
try {
|
|
await client.logout();
|
|
} catch (_) {
|
|
/* best-effort */
|
|
}
|
|
return true;
|
|
} catch (e) {
|
|
log('ManageSieve probe failed for $host:$port — $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Probes whether [account]'s configured ManageSieve endpoint accepts a TCP
|
|
/// + STARTTLS handshake, and persists the result on the account row.
|
|
///
|
|
/// Runs after account add / edit so the IMAP/SMTP form can omit Sieve fields
|
|
/// for the common case (port 4190 on the IMAP host). The result drives whether
|
|
/// the "Email filters" menu item is shown for this account.
|
|
class ManageSieveProbeService {
|
|
ManageSieveProbeService(
|
|
this._accounts, {
|
|
ManageSieveProbeFn probeFn = _defaultManageSieveProbe,
|
|
}) : _probeFn = probeFn;
|
|
|
|
final AccountRepository _accounts;
|
|
final ManageSieveProbeFn _probeFn;
|
|
|
|
Future<void> probe(Account account) async {
|
|
if (account.type != AccountType.imap) return;
|
|
final host = account.manageSieveHost.trim().isNotEmpty
|
|
? account.manageSieveHost.trim()
|
|
: account.imapHost;
|
|
if (host.isEmpty) return;
|
|
final available = await _probeFn(
|
|
host: host,
|
|
port: account.manageSievePort,
|
|
useTls: account.manageSieveSsl,
|
|
);
|
|
if (account.manageSieveAvailable == available) return;
|
|
final updated = _withAvailability(account, available);
|
|
await _accounts.updateAccount(updated);
|
|
}
|
|
|
|
Account _withAvailability(Account a, bool available) => Account(
|
|
id: a.id,
|
|
displayName: a.displayName,
|
|
email: a.email,
|
|
username: a.username,
|
|
type: a.type,
|
|
imapHost: a.imapHost,
|
|
imapPort: a.imapPort,
|
|
imapSsl: a.imapSsl,
|
|
smtpHost: a.smtpHost,
|
|
smtpPort: a.smtpPort,
|
|
smtpSsl: a.smtpSsl,
|
|
manageSieveHost: a.manageSieveHost,
|
|
manageSievePort: a.manageSievePort,
|
|
manageSieveSsl: a.manageSieveSsl,
|
|
manageSieveAvailable: available,
|
|
jmapUrl: a.jmapUrl,
|
|
verbose: a.verbose,
|
|
);
|
|
}
|