1 | <?php |
||||
2 | namespace Mezon\Pop3; |
||||
3 | |||||
4 | /** |
||||
5 | * Class Client |
||||
6 | * |
||||
7 | * @package Mezon |
||||
8 | * @subpackage Pop3Client |
||||
9 | * @author Dodonov A.A. |
||||
10 | * @version v.1.0 (2019/08/13) |
||||
11 | * @copyright Copyright (c) 2019, aeon.org |
||||
12 | */ |
||||
13 | |||||
14 | /** |
||||
15 | * POP3 protocol client. |
||||
16 | */ |
||||
17 | class Client |
||||
18 | { |
||||
19 | |||||
20 | /** |
||||
21 | * Connection |
||||
22 | * |
||||
23 | * @var resource |
||||
24 | */ |
||||
25 | private $connection = null; |
||||
26 | |||||
27 | /** |
||||
28 | * Method returns connection |
||||
29 | * |
||||
30 | * @param string $server |
||||
31 | * Server domain |
||||
32 | * @param string $login |
||||
33 | * Login |
||||
34 | * @param string $password |
||||
35 | * Password |
||||
36 | * @param int $timeOut |
||||
37 | * Timeout |
||||
38 | * @param int $port |
||||
39 | * Port number |
||||
40 | * @return resource connection |
||||
41 | */ |
||||
42 | protected function initConnection(string $server, string $login, string $password, int $timeOut = 5, int $port = 110) |
||||
0 ignored issues
–
show
The parameter
$login is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
43 | { |
||||
44 | $errorMessage = ''; |
||||
45 | $errorCode = 0; |
||||
46 | |||||
47 | $context = stream_context_create([ |
||||
48 | 'ssl' => [ |
||||
49 | 'verify_peer' => false |
||||
50 | ] |
||||
51 | ]); |
||||
52 | |||||
53 | $connection = stream_socket_client( |
||||
54 | $server . ":$port", |
||||
55 | $errorCode, |
||||
56 | $errorMessage, |
||||
57 | $timeOut, |
||||
58 | STREAM_CLIENT_CONNECT, |
||||
59 | $context); |
||||
60 | |||||
61 | if ($connection === false) { |
||||
62 | throw (new \Exception('Connection was not established', - 1)); |
||||
63 | } |
||||
64 | |||||
65 | return $connection; |
||||
66 | } |
||||
67 | |||||
68 | /** |
||||
69 | * Method connects to server |
||||
70 | * |
||||
71 | * @param string $server |
||||
72 | * Server domain |
||||
73 | * @param string $login |
||||
74 | * Login |
||||
75 | * @param string $password |
||||
76 | * Password |
||||
77 | * @param int $timeOut |
||||
78 | * Timeout |
||||
79 | * @param int $port |
||||
80 | * Port number |
||||
81 | */ |
||||
82 | public function connect(string $server, string $login, string $password, int $timeOut = 5, int $port = 110) |
||||
83 | { |
||||
84 | try { |
||||
85 | $this->connection = $this->initConnection($server, $login, $password, $timeOut, $port); |
||||
86 | |||||
87 | $result = fgets($this->connection, 1024); |
||||
88 | |||||
89 | if (substr($result, 0, 3) !== '+OK') { |
||||
90 | throw (new \Exception('Connection. ' . $result, 0)); |
||||
91 | } |
||||
92 | |||||
93 | fputs($this->connection, "USER $login\r\n"); |
||||
94 | |||||
95 | $result = fgets($this->connection, 1024); |
||||
96 | |||||
97 | if (substr($result, 0, 3) !== '+OK') { |
||||
98 | throw (new \Exception("USER $login " . $result, 0)); |
||||
99 | } |
||||
100 | |||||
101 | fputs($this->connection, "PASS $password\r\n"); |
||||
102 | |||||
103 | $result = fgets($this->connection, 1024); |
||||
104 | |||||
105 | if (substr($result, 0, 3) !== '+OK') { |
||||
106 | throw (new \Exception("PASS " . $result . $login, 0)); |
||||
107 | } |
||||
108 | } catch (\Exception $e) { |
||||
109 | throw ($e); |
||||
110 | } |
||||
111 | } |
||||
112 | |||||
113 | /** |
||||
114 | * Constructor |
||||
115 | * |
||||
116 | * @param string $server |
||||
117 | * Server domain |
||||
118 | * @param string $login |
||||
119 | * Login |
||||
120 | * @param string $password |
||||
121 | * Password |
||||
122 | * @param int $timeOut |
||||
123 | * Timeout |
||||
124 | * @param int $port |
||||
125 | * Port number |
||||
126 | */ |
||||
127 | public function __construct(string $server, string $login, string $password, int $timeOut = 5, int $port = 110) |
||||
128 | { |
||||
129 | $this->connect($server, $login, $password, $timeOut, $port); |
||||
130 | } |
||||
131 | |||||
132 | /** |
||||
133 | * Method returns emails count. |
||||
134 | */ |
||||
135 | public function getCount(): int |
||||
136 | { |
||||
137 | fputs($this->connection, "STAT\r\n"); |
||||
138 | |||||
139 | $result = fgets($this->connection, 1024); |
||||
140 | |||||
141 | if (substr($result, 0, 3) !== '+OK') { |
||||
142 | throw (new \Exception("STAT " . $result, 0)); |
||||
143 | } |
||||
144 | |||||
145 | $result = explode(' ', $result); |
||||
146 | |||||
147 | return intval($result[1]); |
||||
148 | } |
||||
149 | |||||
150 | /** |
||||
151 | * Method returns data from connection |
||||
152 | * |
||||
153 | * @return string Fetched data |
||||
154 | */ |
||||
155 | protected function getData(): string |
||||
156 | { |
||||
157 | $data = ''; |
||||
158 | |||||
159 | while (! feof($this->connection)) { |
||||
160 | $buffer = chop(fgets($this->connection, 1024)); |
||||
161 | |||||
162 | if (strpos($buffer, '-ERR') === 0) { |
||||
163 | throw (new \Exception(str_replace('-ERR ', '', $buffer), 0)); |
||||
164 | } |
||||
165 | |||||
166 | $data .= "$buffer\r\n"; |
||||
167 | |||||
168 | if (trim($buffer) == '.') { |
||||
169 | break; |
||||
170 | } |
||||
171 | } |
||||
172 | |||||
173 | return $data; |
||||
174 | } |
||||
175 | |||||
176 | /** |
||||
177 | * Method returns email's headers |
||||
178 | * |
||||
179 | * @param int $i |
||||
180 | * Number of the message |
||||
181 | * @return string Headers |
||||
182 | */ |
||||
183 | public function getMessageHeaders(int $i): string |
||||
184 | { |
||||
185 | fputs($this->connection, "TOP $i 3\r\n"); |
||||
186 | |||||
187 | return $this->getData(); |
||||
188 | } |
||||
189 | |||||
190 | /** |
||||
191 | * Method deletes email |
||||
192 | * |
||||
193 | * @param int $i |
||||
194 | * Number of the message |
||||
195 | * @return string Result of the deletion |
||||
196 | */ |
||||
197 | public function deleteMessage($i): string |
||||
198 | { |
||||
199 | fputs($this->connection, "DELE $i\r\n"); |
||||
200 | |||||
201 | return fgets($this->connection); |
||||
202 | } |
||||
203 | |||||
204 | /** |
||||
205 | * Method terminates session |
||||
206 | */ |
||||
207 | public function quit() |
||||
208 | { |
||||
209 | fputs($this->connection, "QUIT\r\n"); |
||||
210 | } |
||||
211 | |||||
212 | /** |
||||
213 | * Method parses subject with any prefix |
||||
214 | * |
||||
215 | * @param string $line |
||||
216 | * Line of the email |
||||
217 | * @param int $i |
||||
218 | * Line cursor |
||||
219 | * @param array $headers |
||||
220 | * Email headers |
||||
221 | * @param string $type |
||||
222 | * Mime type |
||||
223 | * @return string Decoded data |
||||
224 | */ |
||||
225 | protected function parseAnyType(string $line, int $i, array $headers, string $type): string |
||||
226 | { |
||||
227 | $subject = substr($line, 0, strlen($line) - 2); |
||||
228 | |||||
229 | $count = count($headers); |
||||
230 | for ($j = $i + 1; $j < $count; $j ++) { |
||||
231 | if (substr($headers[$j], 0, 1) == ' ') { |
||||
232 | $subject .= str_replace([ |
||||
233 | ' ' . $type, |
||||
234 | '?=' |
||||
235 | ], [ |
||||
236 | '', |
||||
237 | '' |
||||
238 | ], $headers[$j]); |
||||
239 | } else { |
||||
240 | return str_replace('Subject: ', '', iconv_mime_decode($subject . "?=\r\n", 0, "UTF-8")); |
||||
241 | } |
||||
242 | } |
||||
243 | |||||
244 | return ''; |
||||
245 | } |
||||
246 | |||||
247 | /** |
||||
248 | * Method returns message's subject |
||||
249 | * |
||||
250 | * @param int $i |
||||
251 | * Line number |
||||
252 | * @return string Decoded data |
||||
253 | */ |
||||
254 | public function getMessageSubject(int $i): string |
||||
255 | { |
||||
256 | $headers = $this->getMessageHeaders($i); |
||||
257 | |||||
258 | $headers = explode("\r\n", $headers); |
||||
259 | |||||
260 | foreach ($headers as $i => $line) { |
||||
261 | if (strpos($line, 'Subject: ') === 0) { |
||||
262 | if (strpos($line, '=?UTF-8?Q?') !== false) { |
||||
263 | return $this->parseAnyType($line, $i, $headers, '=?UTF-8?Q?'); |
||||
264 | } elseif (strpos($line, '=?UTF-8?B?') !== false) { |
||||
265 | return $this->parseAnyType($line, $i, $headers, '=?UTF-8?B?'); |
||||
266 | } |
||||
267 | } |
||||
268 | } |
||||
269 | |||||
270 | return ''; |
||||
271 | } |
||||
272 | |||||
273 | /** |
||||
274 | * Method returns true if the mail with the specified subject exists |
||||
275 | * |
||||
276 | * @param string $subject |
||||
277 | * Searching subject |
||||
278 | * @return bool Email exists |
||||
279 | */ |
||||
280 | public function messageWithSubjectExists(string $subject): bool |
||||
281 | { |
||||
282 | $count = $this->getCount(); |
||||
283 | |||||
284 | for ($i = 1; $i <= $count; $i ++) { |
||||
285 | $mailSubject = $this->getMessageSubject($i); |
||||
286 | |||||
287 | if ($subject == $mailSubject) { |
||||
288 | return true; |
||||
289 | } |
||||
290 | } |
||||
291 | |||||
292 | return false; |
||||
293 | } |
||||
294 | |||||
295 | /** |
||||
296 | * Method removes all the mails with the specified subject |
||||
297 | * |
||||
298 | * @param string $subject |
||||
299 | * subject of emails to be deleted |
||||
300 | */ |
||||
301 | public function deleteMessagesWithSubject(string $subject) |
||||
302 | { |
||||
303 | $count = $this->getCount(); |
||||
304 | |||||
305 | for ($i = 1; $i <= $count; $i ++) { |
||||
306 | $mailSubject = $this->getMessageSubject($i); |
||||
307 | |||||
308 | if ($subject == $mailSubject) { |
||||
309 | $this->deleteMessage($i); |
||||
310 | } |
||||
311 | } |
||||
312 | } |
||||
313 | |||||
314 | /** |
||||
315 | * Method returns Message-ID |
||||
316 | * |
||||
317 | * @param string $headers |
||||
318 | * email headers |
||||
319 | * @return string Message-ID |
||||
320 | */ |
||||
321 | public static function getMessageId(string $headers): string |
||||
322 | { |
||||
323 | $matches = []; |
||||
324 | |||||
325 | preg_match('/Message-ID: <([0-9a-zA-Z\.@\-]*)>/mi', $headers, $matches); |
||||
326 | |||||
327 | return $matches[1]; |
||||
328 | } |
||||
329 | } |
||||
330 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.