/
delete-corrupt-mail-using-POP3.php
178 lines (154 loc) · 4.2 KB
/
delete-corrupt-mail-using-POP3.php
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<?php
/*
* Fix mail by deleting corrupted mails.
*
* POP3 protocol refer RFC1939 (http://tools.ietf.org/rfc/rfc1939.txt)
* POP3 Extension Mechanism refer RFC2449(http://tools.ietf.org/rfc/rfc2449.txt)
* Using TLS with POP3 refer RFC2595(http://tools.ietf.org/rfc/rfc2595.txt), not implemented.
* POP3 AUTH refer RFC5034(http://tools.ietf.org/rfc/rfc5034.txt), not implemented.
* see also RFC4422 for Simple Authentication and Security Layer (SASL).
*
* Use USER and PASS for authentication.
* CAUTION: message transmit in pure text, so be careful when using.
*/
$host = "127.0.0.1";
$port = "110"; // secure port is 995
if ($argc != 3) {
print "Usage: \n";
print "\t" . $argv[0] . " user pass\n";
print "\n";
exit;
}
$username = $argv[1];
$password = $argv[2];
function sendQuery($socket, $CMD, $data = '')
{
$data = trim($data);
if (empty($data)) {
$send = "$CMD\r\n";
} else {
$send = "$CMD $data\r\n";
}
socket_send($socket, $send, strlen($send), 0);
return;
}
function getResult($socket, $CMD = '')
{
$retBuffer = '';
while(($len = @socket_recv($socket, $buffer, 1024, 0)) >0) {
//print $buffer;
//print "\n";
$retBuffer .= $buffer;
$n = strlen($retBuffer);
if (($CMD == 'LIST' || $CMD == 'RETR' || $CMD == 'CAPA' || $CMD == 'TOP' || $CMD == 'UIDL') &&
($retBuffer[0] == '+' && $retBuffer[1] == 'O' && $retBuffer[2] == 'K') &&
! ($retBuffer[$n-1] == "\n" && $retBuffer[$n-2] == "\r" && $retBuffer[$n-3] == '.')) {
// POP3协议返回数据
// 第一行为状态码 +OK 或者 -ERR
// 若有数据,数据以 ".\r\n" 结束
$buffer = '';
continue;
}
break;
}
return $retBuffer;
}
function getConnection($host, $port)
{
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
or die("Unable to create socket\n");
socket_connect($socket, $host, $port);
$r = getResult($socket); // Get greeting info
print $r;
return $socket;
}
function getLoginSession($host, $port, $user, $pass)
{
$socket = getConnection($host, $port);
sendQuery($socket, 'USER', $user);
$r = getResult($socket, 'USER');
print $r;
sendQuery($socket, 'PASS', $pass);
$r = getResult($socket, 'PASS');
print $r;
return $socket;
}
function getMailIdList($socket)
{
sendQuery($socket, 'LIST');
$r = getResult($socket, 'LIST');
$lines = explode("\r\n", $r);
$lines = array_filter($lines);
$arrMailId = array();
foreach($lines as $v) {
if ($v[0] == '+' && $v[1] == 'O' && $v[2] == 'K') continue;
if ($v[0] == '.') continue;
$v = trim($v);
if (empty($v)) continue;
$mid = explode(' ', $v);
//print "$v\n";
$arrMailId[] = $mid[0];
}
return $arrMailId;
}
function checkMailCorrupt($socket, $mailId)
{
sendQuery($socket, 'TOP', "$mailId 0");
$r = getResult($socket, 'TOP');
$r = trim($r);
if ($r == '-ERR Message corrupted') {
print "$mailId $r\n";
return 1;
} else if ($r[0] == '-' && $r[1] == 'E' && $r[2] == 'R' && $r[3] == 'R') {
print "$mailId $r\n";
return 2;
}
return 0;
}
function deleteMail($socket, $mailId)
{
sendQuery($socket, 'DELE', "$mailId");
$r = getResult($socket, 'DELE');
print "DELE $mailId " . $r;
return;
}
function quitAndClose(& $socket)
{
sendQuery($socket, 'QUIT');
$r = getResult($socket, 'QUIT');
socket_close($socket);
$socket = null;
print $r;
return;
}
// START
// get mail id list
$socket = getLoginSession($host, $port, $username, $password);
$arrMailId = getMailIdList($socket);
quitAndClose($socket);
$totalMail = count($arrMailId);
print "\nTotal mail count $totalMail\n\n";
// delete corrupt mail
// 删除之后id会重新补齐,所以从最大id开始
// 同一封邮件id在不同会话之间不一定相同, 但可以通过UIDL来获得邮件唯一ID标识
// 所以邮件客户端会先获取UIDL, 然后再获取LIST, 最后RETR获取邮件
$totalCorrupt = 0;
$cur = $totalMail - 1;
while ($cur >= 0) {
$n = 6;
$socket = getLoginSession($host, $port, $username, $password);
while(($n > 0) && ($cur >= 0)) {
$id = $arrMailId[$cur];
$r = checkMailCorrupt($socket, $id);
if ($r == 1) {
$totalCorrupt ++;
deleteMail($socket, $id);
$n --;
} else if ($r != 0) {
$n --;
}
$cur --;
}
quitAndClose($socket);
}
print "\nTotal mail corrupt count $totalCorrupt\n\n";