File size: 2,756 Bytes
d2897cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
<?php

namespace Mautic\EmailBundle\Helper;

use Mautic\EmailBundle\EmailEvents;
use Mautic\EmailBundle\Event\EmailValidationEvent;
use Mautic\EmailBundle\Exception\InvalidEmailException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

class EmailValidator
{
    public function __construct(
        protected TranslatorInterface $translator,
        protected EventDispatcherInterface $dispatcher
    ) {
    }

    /**
     * Validate that an email is the correct format, doesn't have invalid characters, a MX record is associated with the domain, and
     * leverage integrations to validate.
     *
     * @param bool $doDnsCheck
     *
     * @throws InvalidEmailException
     */
    public function validate($address, $doDnsCheck = false): void
    {
        if (!$this->isValidFormat($address)) {
            throw new InvalidEmailException($address, $this->translator->trans('mautic.email.address.invalid_format', ['%email%' => $address ?: '?']));
        }

        if ($this->hasValidCharacters($address)) {
            throw new InvalidEmailException($address, $this->translator->trans('mautic.email.address.invalid_characters', ['%email%' => $address]));
        }

        if ($doDnsCheck && !$this->hasValidDomain($address)) {
            throw new InvalidEmailException($address, $this->translator->trans('mautic.email.address.invalid_domain', ['%email%' => $address]));
        }

        $this->doPluginValidation($address);
    }

    /**
     * Validates that email is in an acceptable format.
     *
     * @returns bool
     */
    public function isValidFormat($address): bool
    {
        return !empty($address) && filter_var($address, FILTER_VALIDATE_EMAIL);
    }

    /**
     * Validates that email does not have invalid characters.
     *
     * @returns bool
     */
    public function hasValidCharacters($address)
    {
        $invalidChar = strpbrk($address, '^&*%');

        return $invalidChar ? substr($invalidChar, 0, 1) : $invalidChar;
    }

    /**
     * Validates if the domain of an email.
     *
     * @returns bool
     */
    public function hasValidDomain($address): bool
    {
        [$user, $domain] = explode('@', $address);

        return checkdnsrr($domain, 'MX');
    }

    /**
     * Validate using 3rd party integrations.
     *
     * @throws InvalidEmailException
     */
    public function doPluginValidation($address): void
    {
        $event = $this->dispatcher->dispatch(
            new EmailValidationEvent($address),
            EmailEvents::ON_EMAIL_VALIDATION
        );

        if (!$event->isValid()) {
            throw new InvalidEmailException($address, $event->getInvalidReason());
        }
    }
}