This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of EmailChecker. |
||
5 | * |
||
6 | * (c) Corrado Ronci <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace sorciulus\EmailChecker; |
||
13 | |||
14 | use sorciulus\EmailChecker\Exception\SmtpCheckerException; |
||
15 | use sorciulus\EmailChecker\MxChecker; |
||
16 | use \Graze\TelnetClient\Exception\TelnetException; |
||
0 ignored issues
–
show
|
|||
17 | use \miyahan\network\Telnet; |
||
18 | /** |
||
19 | * This Class check the email address is valid |
||
20 | * through commands executed on the SMTP Server |
||
21 | */ |
||
22 | class SmtpChecker implements SmtpInterface |
||
23 | { |
||
24 | /** |
||
25 | * Instance of Telnet class |
||
26 | * @var object Telnet |
||
27 | */ |
||
28 | private $client; |
||
29 | |||
30 | /** |
||
31 | * The domain of SMTP Server |
||
32 | * @var string |
||
33 | */ |
||
34 | private $domain; |
||
35 | |||
36 | /** |
||
37 | * Response Code SMTP Server |
||
38 | * @var integer |
||
39 | */ |
||
40 | private $code; |
||
41 | |||
42 | /** |
||
43 | * The given email is valid or not. |
||
44 | * @var boolean |
||
45 | */ |
||
46 | private $isValid; |
||
47 | |||
48 | /** |
||
49 | * List of command and response executed |
||
50 | * @var array |
||
51 | */ |
||
52 | private $debug = []; |
||
53 | |||
54 | /** |
||
55 | * The sender of SMTP check email |
||
56 | * @var string |
||
57 | */ |
||
58 | private $sender = "[email protected]"; |
||
59 | |||
60 | // some smtp response codes |
||
61 | const SMTP_CONNECT_SUCCESS = 220; |
||
62 | const SMTP_QUIT_SUCCESS = 221; |
||
63 | const SMTP_GENERIC_SUCCESS = 250; |
||
64 | const SMTP_USER_NOT_LOCAL = 251; |
||
65 | const SMTP_CANNOT_VRFY = 252; |
||
66 | const SMTP_SERVICE_UNAVAILABLE = 421; |
||
67 | // 450 Requested mail action not taken: mailbox unavailable (e.g., |
||
68 | // mailbox busy or temporarily blocked for policy reasons) |
||
69 | const SMTP_MAIL_ACTION_NOT_TAKEN = 450; |
||
70 | // 451 Requested action aborted: local error in processing |
||
71 | const SMTP_MAIL_ACTION_ABORTED = 451; |
||
72 | // 452 Requested action not taken: insufficient system storage |
||
73 | const SMTP_REQUESTED_ACTION_NOT_TAKEN = 452; |
||
74 | // 500 Syntax error (may be due to a denied command) |
||
75 | const SMTP_SYNTAX_ERROR = 500; |
||
76 | // 502 Comment not implemented |
||
77 | const SMTP_NOT_IMPLEMENTED = 502; |
||
78 | // 503 Bad sequence of commands (may be due to a denied command) |
||
79 | const SMTP_BAD_SEQUENCE = 503; |
||
80 | // 550 Requested action not taken: mailbox unavailable (e.g., mailbox |
||
81 | // not found, no access, or command rejected for policy reasons) |
||
82 | const SMTP_MBOX_UNAVAILABLE = 550; |
||
83 | const SMTP_USER_NOT_LOCAL_FORWARD = 551; |
||
84 | // 552 Requested mail action aborted: exceeded storage allocation |
||
85 | const SMTP_EXCEEDED_STORAGE_ALLOCAION = 552; |
||
86 | //553 Requested action not taken: mailbox name not allowed (e.g., |
||
87 | //mailbox syntax incorrect) |
||
88 | const SMTP_MBOX_NAME_NOT_ALLOWED = 553; |
||
89 | // 554 Seen this from hotmail MTAs, in response to RSET :( |
||
90 | const SMTP_TRANSACTION_FAILED = 554; |
||
91 | |||
92 | /** |
||
93 | * @param array $domains List of SMTP domains |
||
94 | * @param boolean $sender Set sender of STMP command |
||
95 | * @param integer $timeout Timeout of the stream |
||
96 | * |
||
97 | * @throws SmtpCheckerException when all domain not valid |
||
98 | */ |
||
99 | function __construct(MxInterface $domains, $sender = "", int $timeout = 10) |
||
100 | { |
||
101 | foreach ($domains->getRecordMx() as $domain) { |
||
102 | try { |
||
103 | $this->debug = ["Connect to : ".$domain["target"]." on port 25"]; |
||
104 | $this->client = new Telnet($domain["target"], 25, $timeout); |
||
105 | $this->domain = $domain; |
||
106 | break; |
||
107 | } catch (\Exception $ex) { |
||
108 | continue; |
||
109 | } |
||
110 | } |
||
111 | if (empty($this->getDomain())) { |
||
112 | throw new SmtpCheckerException("Error Processing Request ".$ex->getMessage()); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
113 | } |
||
114 | |||
115 | if (!empty($sender)) { |
||
116 | $this->setSender($sender); |
||
117 | } |
||
118 | $this->sayHello(); |
||
119 | $this->setFrom(); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Sets the The sender of SMTP check email. |
||
124 | * |
||
125 | * @param string $sender the sender |
||
126 | * |
||
127 | * @return void |
||
128 | */ |
||
129 | private function setSender($sender) |
||
130 | { |
||
131 | if (!filter_var($sender, FILTER_VALIDATE_EMAIL)) { |
||
132 | throw new SmtpCheckerException("Email Sender not valid"); |
||
133 | } |
||
134 | $this->sender = $sender; |
||
135 | |||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Gets the value of sender. |
||
140 | * |
||
141 | * @return string |
||
142 | */ |
||
143 | private function getSender() |
||
144 | { |
||
145 | return $this->sender; |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Gets the value of domain. |
||
150 | * |
||
151 | * @return array |
||
152 | */ |
||
153 | private function getDomain() |
||
154 | { |
||
155 | return $this->domain; |
||
0 ignored issues
–
show
|
|||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Gets the value of getDomain in object. |
||
160 | * |
||
161 | * @return object |
||
162 | */ |
||
163 | private function getDomainObj() |
||
164 | { |
||
165 | return (object) $this->getDomain(); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Send command HELO to SMTP Server |
||
170 | * |
||
171 | * @return void |
||
172 | * |
||
173 | * @throws SmtpCheckerException when the SMTP server return error |
||
174 | */ |
||
175 | View Code Duplication | private function sayHello() |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
176 | { |
||
177 | $host = $this->getDomainObj()->host; |
||
178 | try{ |
||
179 | $status = $this->commandExec(sprintf("HELO %s", $host)); |
||
180 | if (!in_array(self::SMTP_GENERIC_SUCCESS, $status)) { |
||
181 | $this->disconnect(); |
||
182 | throw new SmtpCheckerException("SMTP Status unexpected: ".implode(",", $status), $this->getDebug()); |
||
183 | } |
||
184 | }catch (\Exception $ex) { |
||
185 | throw new SmtpCheckerException("Error Processing Request ".$ex->getMessage(), $this->getDebug()); |
||
186 | } |
||
187 | |||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Set MAIL FROM to SMTP Server |
||
192 | * |
||
193 | * @return void |
||
194 | * |
||
195 | * @throws SmtpCheckerException when the SMTP server return error |
||
196 | */ |
||
197 | View Code Duplication | private function setFrom() |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
198 | { |
||
199 | try{ |
||
200 | $status = $this->commandExec(sprintf("MAIL FROM:<%s>", $this->getSender())); |
||
201 | if (!in_array(self::SMTP_GENERIC_SUCCESS, $status)) { |
||
202 | $this->disconnect(); |
||
203 | throw new SmtpCheckerException("SMTP Status unexpected: ".implode(",", $status), $this->getDebug()); |
||
204 | } |
||
205 | }catch (\Exception $ex) { |
||
206 | throw new SmtpCheckerException("Error Processing Request setFrom : ".$ex->getMessage(), $this->getDebug()); |
||
207 | } |
||
208 | |||
209 | } |
||
210 | |||
211 | /** |
||
212 | * Wrapper to Telnet Client to Execute SMTP command, will return the status code |
||
213 | * |
||
214 | * @param string $command command execute |
||
215 | * @return array SMPT status |
||
216 | */ |
||
217 | private function commandExec($command) |
||
218 | { |
||
219 | $this->debug[] = $command; |
||
220 | $exec = $this->client->exec($command); |
||
221 | return $this->getResponseStatus($exec); |
||
222 | } |
||
223 | |||
224 | /** |
||
225 | * Get response status code of previous SMTP request |
||
226 | * |
||
227 | * @return array $status The status of SMTP request |
||
228 | * |
||
229 | * @throws SmtpCheckerException when the SMTP server return unknown error |
||
230 | */ |
||
231 | private function getResponseStatus($output) |
||
232 | { |
||
233 | $status = []; |
||
234 | $strout = explode("\n", $output); |
||
235 | if (empty($strout)) { |
||
236 | $strout = [$output]; |
||
237 | } |
||
238 | foreach ($strout as $str) { |
||
239 | $this->debug[] = $str; |
||
240 | if(preg_match('/^[0-9]{3}/', $str, $match)) { |
||
241 | $status[] = current($match); |
||
242 | } |
||
243 | } |
||
244 | if(empty($status)) { |
||
245 | throw new SmtpCheckerException("SMTP Status request Unknown, ". $output, $this->getDebug()); |
||
246 | } |
||
247 | return $status; |
||
248 | } |
||
249 | |||
250 | |||
251 | /** |
||
252 | * Close connection to SMTP Server |
||
253 | * |
||
254 | * @return void |
||
255 | */ |
||
256 | private function disconnect() |
||
257 | { |
||
258 | $this->client->exec("quit"); |
||
259 | $this->client->disconnect(); |
||
260 | $this->debug[] = "QUIT"; |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * Set RCPT command to SMTP server |
||
265 | * |
||
266 | * @param string $email The email to validate |
||
267 | * @return self |
||
268 | * |
||
269 | * @throws SmtpCheckerException when the SMTP server return error |
||
270 | */ |
||
271 | public function validate($email) |
||
272 | { |
||
273 | try{ |
||
274 | $command = sprintf("RCPT TO:<%s>", $email); |
||
275 | $exec = $this->client->exec($command); |
||
276 | $this->debug[] = $command; |
||
277 | $status = $this->getResponseStatus($exec); |
||
278 | $this->disconnect(); |
||
279 | $this->code = end($status); |
||
280 | $this->isValid = false; |
||
281 | if (in_array($this->getCode(), [self::SMTP_USER_NOT_LOCAL, self::SMTP_GENERIC_SUCCESS])) { |
||
282 | $this->isValid = true; |
||
283 | } |
||
284 | return $this; |
||
285 | }catch (\Exception $ex) { |
||
286 | throw new SmtpCheckerException("Error Processing Request Validate : ".$ex->getMessage(), $this->getDebug()); |
||
287 | } |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Gets the value of code. |
||
292 | * |
||
293 | * @return integer |
||
294 | */ |
||
295 | public function getCode() |
||
296 | { |
||
297 | return (int) $this->code; |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Gets the value of isValid. |
||
302 | * |
||
303 | * @return boolean |
||
304 | */ |
||
305 | public function isValid() |
||
306 | { |
||
307 | return $this->isValid; |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * Gets the value of debug. |
||
312 | * |
||
313 | * @return array |
||
314 | */ |
||
315 | public function getDebug() |
||
316 | { |
||
317 | return $this->debug; |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * Gets the value of message. |
||
322 | * |
||
323 | * @return string |
||
324 | */ |
||
325 | public function getMessage() |
||
326 | { |
||
327 | $code = $this->getCode(); |
||
328 | $messages = [ |
||
329 | self::SMTP_CONNECT_SUCCESS => "SMTP connect Success", |
||
330 | self::SMTP_QUIT_SUCCESS => "Quit Success", |
||
331 | self::SMTP_GENERIC_SUCCESS => "SMTP Generic Success", |
||
332 | self::SMTP_USER_NOT_LOCAL => "SMTP User not local", |
||
333 | self::SMTP_CANNOT_VRFY => "SMTP Cannot VRFY user", |
||
334 | self::SMTP_SERVICE_UNAVAILABLE => "SMTP Service not available", |
||
335 | self::SMTP_MAIL_ACTION_NOT_TAKEN => "SMTP mailbox busy or temporarily blocked for policy reasons", |
||
336 | self::SMTP_MAIL_ACTION_ABORTED => "SMTP Requested action aborted: local error in processing", |
||
337 | self::SMTP_REQUESTED_ACTION_NOT_TAKEN => "SMTP Requested action not taken: insufficient system storage", |
||
338 | self::SMTP_SYNTAX_ERROR => "SMTP Syntax error, command unrecognized", |
||
339 | self::SMTP_NOT_IMPLEMENTED => "SMTP Command not implemented", |
||
340 | self::SMTP_BAD_SEQUENCE => "SMTP Bad sequence of commands", |
||
341 | self::SMTP_MBOX_UNAVAILABLE => "SMTP Requested action not taken: mailbox unavailable", |
||
342 | self::SMTP_USER_NOT_LOCAL_FORWARD => "SMTP User not local", |
||
343 | self::SMTP_EXCEEDED_STORAGE_ALLOCAION => "SMTP Requested mail action aborted: exceeded storage allocation", |
||
344 | self::SMTP_MBOX_NAME_NOT_ALLOWED => "Requested action not taken: mailbox name not allowed", |
||
345 | self::SMTP_TRANSACTION_FAILED => "SMTP Transaction failed" |
||
346 | ]; |
||
347 | |||
348 | return |
||
349 | (array_key_exists($code, $messages)) |
||
350 | ? $messages[$code] |
||
351 | : "Unknown message from SMTP"; |
||
352 | } |
||
353 | } |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths