111 lines
3.2 KiB
PHP
111 lines
3.2 KiB
PHP
|
<?PHP
|
||
|
/**
|
||
|
* Contains a class for checking the validity of mail addresses and their
|
||
|
* hostnames, cached through the central noda DB.
|
||
|
*
|
||
|
* @author Joshua Ramon Enslin <joshua@museum-digital.de>
|
||
|
*/
|
||
|
declare(strict_types = 1);
|
||
|
|
||
|
/**
|
||
|
* Contains static functions for checking the validity of mail addresses.
|
||
|
*/
|
||
|
final class NodaMailChecker {
|
||
|
/**
|
||
|
* Splits a mail address and returns the hostname.
|
||
|
*
|
||
|
* @param string $mail_address Mail address.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public static function getDomainFromMailAddress(string $mail_address):string {
|
||
|
|
||
|
$mail_address = MD_STD_IN::sanitize_email($mail_address);
|
||
|
|
||
|
$addressParts = explode('@', $mail_address);
|
||
|
if (empty($addressParts[1])) {
|
||
|
throw new MDInvalidEmail("Failed to get mail domain");
|
||
|
}
|
||
|
$domain = $addressParts[1];
|
||
|
|
||
|
if (str_contains($domain, '.') === false) {
|
||
|
throw new MDInvalidEmail("Failed to find a dot in the mail domain");
|
||
|
}
|
||
|
|
||
|
return $domain;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if a mail hostname is accessible.
|
||
|
*
|
||
|
* @param string $mail_domain Hostname of the mail address.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public static function validateMailDomainAccessibility(string $mail_domain):string {
|
||
|
|
||
|
$mxRecords = [];
|
||
|
getmxrr($mail_domain, $mxRecords);
|
||
|
$mxRecords = array_diff($mxRecords, ['0.0.0.0', '', null]);
|
||
|
|
||
|
if (empty($mxRecords)) return "";
|
||
|
|
||
|
return MD_STD_IN::sanitize_text(implode(',', $mxRecords));
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if a mail hostname is accessible.
|
||
|
*
|
||
|
* @param MDMysqli $mysqli DB connection.
|
||
|
* @param string $mail_domain Hostname of the mail address.
|
||
|
*
|
||
|
* @return boolean
|
||
|
*/
|
||
|
public static function validateMailDomainAccessibilityCached(MDMysqli $mysqli, string $mail_domain):bool {
|
||
|
|
||
|
$result = $mysqli->query_by_stmt("SELECT `valid`, `hostname`
|
||
|
FROM `" . DATABASENAME_NODA . "`.`misc_mail_hostname_validity`
|
||
|
WHERE `hostname` = ?", "s", $mail_domain);
|
||
|
|
||
|
if ($cur = $result->fetch_row()) {
|
||
|
$result->close();
|
||
|
return (bool)$cur[0];
|
||
|
}
|
||
|
$result->close();
|
||
|
|
||
|
$target_hostnames = self::validateMailDomainAccessibility($mail_domain);
|
||
|
$validity = !empty($target_hostnames);
|
||
|
|
||
|
$insertStmt = $mysqli->do_prepare("INSERT
|
||
|
INTO `" . DATABASENAME_NODA . "`.`misc_mail_hostname_validity`
|
||
|
(`hostname`, `valid`, `resolved_hostnames`)
|
||
|
VALUES
|
||
|
(?, ?, ?)");
|
||
|
|
||
|
$insertStmt->bind_param("sis", $mail_domain, $validity, $target_hostnames);
|
||
|
$insertStmt->execute();
|
||
|
|
||
|
$insertStmt->close();
|
||
|
|
||
|
return $validity;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks a mail address for the validity of its hostname.
|
||
|
*
|
||
|
* @param MDMysqli $mysqli DB connection.
|
||
|
* @param string $mail_address Hostname of the mail address.
|
||
|
*
|
||
|
* @return boolean
|
||
|
*/
|
||
|
public static function validateMailByDomainAccessibilityCached(MDMysqli $mysqli, string $mail_address):bool {
|
||
|
|
||
|
$domain = self::getDomainFromMailAddress($mail_address);
|
||
|
return self::validateMailDomainAccessibilityCached($mysqli, $domain);
|
||
|
|
||
|
}
|
||
|
}
|