1
|
|
|
<?php |
2
|
|
|
function getIP($header,$mxserver,$msa) { |
3
|
|
|
/* Get submission server's IP from header's mail */ |
4
|
|
|
/* Each line must end with /r/n */ |
5
|
|
|
/* IP is the first one written by your mxserver */ |
6
|
|
|
|
7
|
|
|
$ip = FALSE; |
8
|
|
|
$host = FALSE; |
9
|
|
|
$dateR = FALSE; |
10
|
|
|
if ( preg_match_all('/^Received:\sfrom(?:.|\r\n\s)*?[\[\(]\s*(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})[\]\)](?:.|\r\n\s)+\s+by(?:\s|\r\n\s+)(?P<host>\S+).*(?:\s|\r\n\s\s)+.*;\s+(?P<date>.*)/m',$header,$received) ) { |
11
|
|
|
for ($i = count($received[0])-1;$i>=0;$i--) { |
12
|
|
|
# print "Examine ".$received[0][$i]."\n"; |
13
|
|
|
if ( preg_match($msa,$received['host'][$i]) ) |
14
|
|
|
$dateR = $received['date'][$i]; |
15
|
|
|
foreach ($mxserver as $mx) { |
16
|
|
|
if (!$ip) |
17
|
|
|
if ($mx == $received['host'][$i]) { |
18
|
|
|
$host = $received['host'][$i]; |
19
|
|
|
$ip = $received['ip'][$i]; |
20
|
|
|
} |
21
|
|
|
} |
22
|
|
|
} |
23
|
|
|
} |
24
|
|
|
if ( preg_match ('/\r\nDate:\s(?P<date>.*)\r\n/',$header,$dateC) != 1) |
25
|
|
|
$dateC['date'] = 'Not found'; |
26
|
|
|
if ( preg_match ('/\r\nMessage\-I(?:D|d):\s(?P<mid>.*)\r\n/',$header,$mid) != 1) |
27
|
|
|
$mid['mid'] = NULL; |
28
|
|
|
return array($ip,$host,$dateR,$dateC['date'],$mid['mid']); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
function updateReport ($ip,$uid,$ipcount,$uidcount,$hostname,$dateC,$msgid,$dateL) { |
32
|
|
|
|
33
|
|
|
return sprintf ('<tr><td nowrap>%s</td><td nowrap>%s</td><td>%s</td><td>%s</td><td>%u</td><td>%u</td><td>%s</td><td>%s</td></tr>'."\n",$dateL,$dateC,$uid,$ip,$uidcount,$ipcount,$hostname,htmlentities($msgid) ); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
function updatebadReport ( $uid,$dateC,$msgid,$dateL,$text ) { |
37
|
|
|
return sprintf ('<tr><td nowrap>%s</td><td nowrap>%s</td><td>%s</td><td>%s</td><td nowrap>%s</td></tr>'."\n",$dateL,$dateC,$uid,htmlentities($msgid),$text ); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
|
41
|
|
|
function summaryBadReport ($uidvet) { |
42
|
|
|
$nuid = $uidvet['count']; |
43
|
|
|
if ( empty($uidvet) ) return NULL; |
44
|
|
|
$return = '<hr><h3>Statistics by UID</h3><table><tr><th>UID</th><th>Learned times</th></tr>'."\n"; |
45
|
|
|
|
46
|
|
|
/* Remove count index */ |
47
|
|
|
$uids = array_keys($uidvet['uid']); |
48
|
|
|
$totlearn = 0; |
49
|
|
|
|
50
|
|
|
foreach ( $uids as $uid ) { |
51
|
|
|
$totlearn += $uidvet['uid']["$uid"]['count'];; |
52
|
|
|
$return .= sprintf ('<tr><td>%s</td><td>%u</td></tr>',$uid,$uidvet['uid']["$uid"]['count']); |
53
|
|
|
} |
54
|
|
|
$return .= sprintf ('<tr><th>%s</th><th>%u</th></tr></table>','TOT',$totlearn); |
55
|
|
|
$return .= sprintf ('<p>%s : %u</p>','Unique UID',$nuid); |
56
|
|
|
|
57
|
|
|
return $return; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
|
61
|
|
|
function array_msort($array, $cols) |
62
|
|
|
{ |
63
|
|
|
$colarr = array(); |
64
|
|
|
foreach ($cols as $col => $order) { |
65
|
|
|
$colarr[$col] = array(); |
66
|
|
|
foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); } |
67
|
|
|
} |
68
|
|
|
$eval = 'array_multisort('; |
69
|
|
|
foreach ($cols as $col => $order) { |
70
|
|
|
$eval .= '$colarr[\''.$col.'\'],'.$order.','; |
71
|
|
|
} |
72
|
|
|
$eval = substr($eval,0,-1).');'; |
73
|
|
|
eval($eval); |
74
|
|
|
$ret = array(); |
75
|
|
|
foreach ($colarr as $col => $arr) { |
76
|
|
|
foreach ($arr as $k => $v) { |
77
|
|
|
$k = substr($k,1); |
78
|
|
|
if (!isset($ret[$k])) $ret[$k] = $array[$k]; |
79
|
|
|
if (isset ($array[$k][$col])) $ret[$k][$col] = $array[$k][$col]; |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
return $ret; |
83
|
|
|
|
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
|
87
|
|
|
function summaryReportAndList ($cf,$myconn,$tables,$category,$vet,$key) { |
88
|
|
|
$nk = $vet['count']; |
89
|
|
|
|
90
|
|
|
if ( empty($vet) ) return NULL; |
91
|
|
|
|
92
|
|
|
$return = sprintf('<h3>Statistics by %s</h3><table><tr><th>%s</th><th>Learned by</th><th>Learned times</th><th title="This field doesn\'t say if this %s is currently listed, but it says if this %s has listed now!">Listed Now</th></tr>'."\n", strtoupper($key),strtoupper($key),$key,$key); |
93
|
|
|
|
94
|
|
|
$values = array_keys($vet["$key"]); |
95
|
|
|
|
96
|
|
|
foreach ( $values as $value ) { |
97
|
|
|
if ( $value == 'count' ) continue; |
98
|
|
|
$nlearn = $vet["$key"]["$value"]['count']; |
99
|
|
|
unset($vet["$key"]["$value"]['count']); |
100
|
|
|
$quantity = $cf["listing$key"]['quantity']["$category"]; /* In searchAndList this value is |
101
|
|
|
passed by reference and modified */ |
102
|
|
|
$nuid = count($vet["$key"]["$value"]); |
103
|
|
|
if ( !$cf["listing$key"]['onlyReport']["$category"] ) { |
104
|
|
|
if ( ($nlearn >= $cf["listing$key"]['threshold']["$category"])&&($nuid >= $cf["listing$key"]['thresholduid']["$category"]) ) { |
105
|
|
|
$reason = sprintf( |
106
|
|
|
'The %s <%s> has been listed because was marked %u times as %s by %u different accounts during last %u days.', |
107
|
|
|
strtoupper($key),$value,$nlearn,$category,$nuid,$cf['imap']['oldestday']); |
108
|
|
|
$listed = searchAndList ($myconn,$cf['syslog']['user'],$tables,$cf["listing$key"]['list']["$category"],$value,$cf["listing$key"]['unit']["$category"],$quantity,$reason); |
109
|
|
|
} |
110
|
|
|
else $listed = FALSE; |
111
|
|
|
} |
112
|
|
|
else $listed = FALSE; |
113
|
|
|
$nowlist = array( TRUE => array( |
114
|
|
|
'style' => 'id=\'ipfound\'', |
115
|
|
|
'name' => 'YES', |
116
|
|
|
), |
117
|
|
|
FALSE => array( |
118
|
|
|
'style' => 'id=\'\'', |
119
|
|
|
'name' => 'No', |
120
|
|
|
), |
121
|
|
|
NULL => array( |
122
|
|
|
'style' => 'id=\'\'', |
123
|
|
|
'name' => 'No', |
124
|
|
|
) |
125
|
|
|
); |
126
|
|
|
|
127
|
|
|
$return .='<tr><td rowspan="'.$nuid.'">'.$value.'</td>'; |
128
|
|
|
$return .= sprintf ('<td>%s</td><td rowspan="'.$nuid.'">%u</td><td rowspan="'.$nuid.'" '.$nowlist["$listed"]['style'].'>%s</td></tr>',$vet["$key"]["$value"][0],$nlearn,$nowlist["$listed"]['name']); |
129
|
|
|
$rowuid=NULL; |
130
|
|
|
for ($j=1;$j<$nuid;$j++) $rowuid .= '<tr><td>%s</td></tr>'; |
131
|
|
|
array_shift($vet["$key"]["$value"]); |
132
|
|
|
$return .= vsprintf ($rowuid,$vet["$key"]["$value"]); |
133
|
|
|
|
134
|
|
|
} |
135
|
|
|
$return .= sprintf ('<tr><th title="unique %s">%u</th><th title="unique uids">%u</th><th>%u</th></table>',$key,$vet["$key"]['count'],$vet['uid']['count'],$nk); |
136
|
|
|
|
137
|
|
|
|
138
|
|
|
/* Statistics by UID */ |
139
|
|
|
/* Not used for listing purpose, but useful to you! */ |
140
|
|
|
$return .= sprintf('<h3>Statistics by UID</h3><table><tr><th>UID</th><th>%s learned</th><th>Learned times</th></tr>'."\n",$key); |
141
|
|
|
$uids = array_keys($vet['uid']); |
142
|
|
|
foreach ( $uids as $uid ) { |
143
|
|
|
if ( $uid == 'count' ) continue; |
144
|
|
|
$nlearn = $vet['uid']["$uid"]['count']; |
145
|
|
|
unset ( $vet['uid']["$uid"]['count'] ); |
146
|
|
|
$nip = count($vet['uid']["$uid"]); |
147
|
|
|
$return .='<tr><td rowspan="'.$nip.'">'.$uid.'</td>'; |
148
|
|
|
$return .= sprintf ('<td>%s</td><td rowspan="'.$nip.'">%u</td></tr>',$vet['uid']["$uid"][0],$nlearn); |
149
|
|
|
$rowuid=NULL; |
150
|
|
|
for ($j=1;$j<$nip;$j++) $rowuid .= '<tr><td>%s</td></tr>'; |
151
|
|
|
array_shift($vet['uid']["$uid"]); |
152
|
|
|
$return .= vsprintf ($rowuid,$vet['uid']["$uid"]); |
153
|
|
|
|
154
|
|
|
} |
155
|
|
|
$return .= sprintf ('<tr><th title="unique uids">%u</th><th title="unique %s">%u</th><th>%u</th></table>', |
156
|
|
|
$vet['uid']['count'],$key,$vet["$key"]['count'],$nk); |
157
|
|
|
|
158
|
|
|
|
159
|
|
|
return $return; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
|
163
|
|
|
function splunksearch ($service,$message_id,$date) { |
164
|
|
|
|
165
|
|
|
// Run a blocking search |
166
|
|
|
$searchQueryBlocking = 'search (message_id="'. addslashes( $message_id ) . |
167
|
|
|
'" OR sasl_username) | transaction message_id queue_id maxspan=3m maxpause=2m | search sasl_username message_id=* | table sasl_username'; |
168
|
|
|
|
169
|
|
|
/* Doesn't work on Splunk 6.6 for HTTP exceptions |
170
|
|
|
// A blocking search returns the job when the search is done |
171
|
|
|
$job = $service->getJobs()->create($searchQueryBlocking, array( |
172
|
|
|
'exec_mode' => 'blocking', |
173
|
|
|
'earliest_time' => date("c",strtotime ($date)-120), |
174
|
|
|
'latest_time' => date("c",strtotime ($date)+60) |
175
|
|
|
)); |
176
|
|
|
|
177
|
|
|
if ($job['resultCount'] == 0) return FALSE; |
178
|
|
|
|
179
|
|
|
// Get job results |
180
|
|
|
$resultSearch = $job->getResults(); |
181
|
|
|
*/ |
182
|
|
|
|
183
|
|
|
// A one shot search |
184
|
|
|
$searchParams = array( |
185
|
|
|
'earliest_time' => date("c",strtotime ($date)-120), |
186
|
|
|
'latest_time' => date("c",strtotime ($date)+60) |
187
|
|
|
); |
188
|
|
|
|
189
|
|
|
// Run a oneshot search that returns the job's results |
190
|
|
|
$resultsStream = $service->oneshotSearch($searchQueryBlocking, $searchParams); |
191
|
|
|
$resultSearch = new Splunk_ResultsReader($resultsStream); |
192
|
|
|
|
193
|
|
|
// Use the built-in XML parser to display the job results |
194
|
|
|
foreach ($resultSearch as $result) |
195
|
|
|
{ |
196
|
|
|
if ($result instanceof Splunk_ResultsFieldOrder) |
|
|
|
|
197
|
|
|
{ |
198
|
|
|
// More than one field attribute returned by search |
199
|
|
|
// You must redefine the search |
200
|
|
|
if ( count($result->getFieldNames()) > 1 ) return FALSE; |
201
|
|
|
} |
202
|
|
|
else if ($result instanceof Splunk_ResultsMessage) |
|
|
|
|
203
|
|
|
{ |
204
|
|
|
// I don't want messages in my search |
205
|
|
|
return FALSE; |
206
|
|
|
} |
207
|
|
|
else if (is_array($result)) |
208
|
|
|
{ |
209
|
|
|
// Process a row |
210
|
|
|
foreach ($result as $key => $valueOrValues) |
211
|
|
|
{ |
212
|
|
|
if (is_array($valueOrValues)) |
213
|
|
|
{ |
214
|
|
|
return FALSE; |
215
|
|
|
} |
216
|
|
|
else |
217
|
|
|
{ |
218
|
|
|
return $valueOrValues; |
219
|
|
|
#print " {$key} => {$value}\r\n"; |
220
|
|
|
} |
221
|
|
|
} |
222
|
|
|
} |
223
|
|
|
else |
224
|
|
|
{ |
225
|
|
|
#print "Unknow result type"; |
226
|
|
|
return FALSE; |
227
|
|
|
} |
228
|
|
|
} |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/* |
232
|
|
|
Function to read body taken from |
233
|
|
|
https://www.electrictoolbox.com/php-imap-message-body-attachments/ |
234
|
|
|
*/ |
235
|
|
|
|
236
|
|
|
function flattenParts($messageParts, $flattenedParts = array(), $prefix = '', $index = 1, $fullPrefix = true) { |
237
|
|
|
|
238
|
|
|
foreach($messageParts as $part) { |
239
|
|
|
$flattenedParts[$prefix.$index] = $part; |
240
|
|
|
if(isset($part->parts)) { |
241
|
|
|
if($part->type == 2) { |
242
|
|
|
$flattenedParts = flattenParts($part->parts, $flattenedParts, $prefix.$index.'.', 0, false); |
243
|
|
|
} |
244
|
|
|
elseif($fullPrefix) { |
245
|
|
|
$flattenedParts = flattenParts($part->parts, $flattenedParts, $prefix.$index.'.'); |
246
|
|
|
} |
247
|
|
|
else { |
248
|
|
|
$flattenedParts = flattenParts($part->parts, $flattenedParts, $prefix); |
249
|
|
|
} |
250
|
|
|
unset($flattenedParts[$prefix.$index]->parts); |
251
|
|
|
} |
252
|
|
|
$index++; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
return $flattenedParts; |
256
|
|
|
|
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
function getPart($connection, $messageNumber, $partNumber, $encoding) { |
260
|
|
|
|
261
|
|
|
$data = imap_fetchbody($connection, $messageNumber, $partNumber); |
262
|
|
|
switch($encoding) { |
263
|
|
|
case 0: return $data; // 7BIT |
|
|
|
|
264
|
|
|
case 1: return $data; // 8BIT |
|
|
|
|
265
|
|
|
case 2: return $data; // BINARY |
|
|
|
|
266
|
|
|
case 3: return base64_decode($data); // BASE64 |
|
|
|
|
267
|
|
|
case 4: return quoted_printable_decode($data); // QUOTED_PRINTABLE |
|
|
|
|
268
|
|
|
case 5: return $data; // OTHER |
|
|
|
|
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
|
272
|
|
|
} |
273
|
|
|
/***********************************/ |
274
|
|
|
|
275
|
|
|
function getDomains ($text,$exclude) { |
276
|
|
|
/* Pattern from https://mathiasbynens.be/demo/url-regex */ |
277
|
|
|
/* Current choice: @gruber */ |
278
|
|
|
$pattern = '#\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#iS'; |
279
|
|
|
$ret = array(); |
280
|
|
|
$num_found = preg_match_all($pattern, $text, $out); |
281
|
|
|
if ( ($num_found !== FALSE) && ($num_found>0) ) { |
282
|
|
|
foreach ($out[0] as $url) { |
283
|
|
|
$dom=parse_url($url, PHP_URL_HOST); |
284
|
|
|
if (!( empty($dom) || in_array($dom,$exclude) )) |
285
|
|
|
$ret[] = $dom; |
286
|
|
|
} |
287
|
|
|
} |
288
|
|
|
print_r($out[0]); |
289
|
|
|
return array_values(array_unique($ret)); |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
function parseURL ($connection,$messageNumber, $exclusionList) { |
293
|
|
|
$message = ''; |
294
|
|
|
$structure = imap_fetchstructure($connection, $messageNumber); |
295
|
|
|
if (isset($structure->parts)) { |
296
|
|
|
$flattenedParts = flattenParts($structure->parts); |
297
|
|
|
foreach($flattenedParts as $partNumber => $part) { |
298
|
|
|
|
299
|
|
|
switch($part->type) { |
300
|
|
|
|
301
|
|
|
case 0: |
302
|
|
|
// the HTML or plain text part of the email |
303
|
|
|
$message .= getPart($connection, $messageNumber, $partNumber, $part->encoding); |
304
|
|
|
break; |
305
|
|
|
|
306
|
|
|
case 1: |
307
|
|
|
// multi-part headers, can ignore |
308
|
|
|
|
309
|
|
|
break; |
310
|
|
|
case 2: |
311
|
|
|
// attached message headers, can ignore |
312
|
|
|
break; |
313
|
|
|
|
314
|
|
|
case 3: // application |
315
|
|
|
case 4: // audio |
316
|
|
|
case 5: // image |
317
|
|
|
case 6: // video |
318
|
|
|
case 7: // other |
319
|
|
|
break; |
320
|
|
|
|
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
} |
324
|
|
|
} |
325
|
|
|
else |
326
|
|
|
$message = getPart($connection, $messageNumber, 1, $structure->encoding); |
327
|
|
|
|
328
|
|
|
if ( !empty($message) ) |
329
|
|
|
return getDomains($message, $exclusionList); |
330
|
|
|
return array(); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
function humanKey($key) { |
334
|
|
|
switch($key) { |
335
|
|
|
case 'ip': |
336
|
|
|
return 'ips'; |
337
|
|
|
case 'dom': |
338
|
|
|
return 'domains'; |
339
|
|
|
} |
340
|
|
|
return $key; |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
function writeFileHeader($f,$conf,$key,$type,$rtime) { |
344
|
|
|
fwrite( $f, file_get_contents(dirname(__FILE__) . '/' . $conf['report']['reportTemplateHeader']) ); |
345
|
|
|
fwrite( $f,sprintf('<h1> Report of %s %s</h1><h5>%s</h5><h2>Detailed Report</h2>',$type, strtoupper(humanKey($key)),$rtime) ); |
346
|
|
|
if ($conf["listing$key"]['onlyReport']["$type"]) { |
347
|
|
|
fwrite( $f,sprintf('<p>None of the below %s have been listed because listing is not active in configuration.</p>', |
348
|
|
|
strtoupper(humanKey($key))) ); |
349
|
|
|
syslog(LOG_INFO, sprintf('%s: Report only for %s %s: no listing activated in configuration.', |
350
|
|
|
$conf['syslog']['user'],$type,humanKey($key)) |
351
|
|
|
); |
352
|
|
|
} |
353
|
|
|
fwrite( $f,sprintf('<table><tr><th title="taken from Received header" nowrap>Date of Learn</th><th title="taken from Date header" nowrap>Date of Write</th><th nowrap>UID</th><th nowrap>%s</th><th title="How many times this uid learns">#UID</th><th title="Number of times this learned %s appears in different mails">#%s</th><th nowrap>Received by</th><th>Message-Id</th></tr>', |
354
|
|
|
strtoupper($key),strtoupper($key),strtoupper($key)) ); |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
|
358
|
|
|
function imapReport ($cf,$myconnArray,$splunkconn,$tables,$type) { |
359
|
|
|
$file = dirname(__FILE__) . '/' . $cf['report']['reportFile']["$type"]; |
360
|
|
|
$filed = dirname(__FILE__) . '/' . $cf['report']['reportDomFile']["$type"]; |
361
|
|
|
$fileb= dirname(__FILE__) . '/' . $cf['report']['badreportFile']["$type"]; |
362
|
|
|
$m_mail = imap_open('{'.$cf['imap']['mailhost'].':143/imap/novalidate-cert/authuser='.$cf['imap']['authuser'].'}'.$cf['imap']['folder']["$type"], $cf['imap']['account'],$cf['imap']['authpassword'], OP_READONLY) |
363
|
|
|
or syslog (LOG_EMERG, $cf['syslog']['user'].': Error in IMAP connection to <'.$cf['imap']['mailhost'].'>: ' . imap_last_error()); |
|
|
|
|
364
|
|
|
if ( !$m_mail ) exit(254); |
365
|
|
|
|
366
|
|
|
|
367
|
|
|
syslog (LOG_INFO,$cf['syslog']['user'].': Successfully connected to <'.$cf['imap']['mailhost'].">; Reading $type messages of last ".$cf['imap']['oldestday'].' days...'); |
368
|
|
|
//get all messages |
369
|
|
|
$dateTh = date ( "d-M-Y", strToTime ( '-'.$cf['imap']['oldestday'].' days' ) ); |
370
|
|
|
$dateN = date ( "d-M-Y", strToTime ( "now" ) ); |
371
|
|
|
$m_search=imap_search ($m_mail, "SINCE \"$dateTh\" BEFORE \"$dateN\"" ); |
372
|
|
|
|
373
|
|
|
// Order results starting from newest message |
374
|
|
|
if ( empty($m_search) ) { |
375
|
|
|
syslog (LOG_INFO,$cf['syslog']['user'].": No mail found in $type folder. No reports written for $type."); |
376
|
|
View Code Duplication |
if ( $ierr = imap_errors() ) |
377
|
|
|
foreach ( $ierr as $thiserr ) |
378
|
|
|
syslog (LOG_ERR, $cf['syslog']['user'].": IMAP Error: $thiserr"); |
379
|
|
View Code Duplication |
if ( $ierr = imap_alerts() ) |
380
|
|
|
foreach ( $ierr as $thiserr ) |
381
|
|
|
syslog (LOG_ALERT, $cf['syslog']['user'].": IMAP Alert: $thiserr"); |
382
|
|
|
imap_close( $m_mail ); |
383
|
|
|
if ( file_exists( $file ) ) unlink ($file); |
384
|
|
|
if ( file_exists( $filed ) ) unlink ($filed); |
385
|
|
|
if ( file_exists( $fileb ) ) unlink ($fileb); |
386
|
|
|
return FALSE; |
387
|
|
|
} |
388
|
|
|
$nmes = count ($m_search); |
389
|
|
|
syslog (LOG_INFO,$cf['syslog']['user'].": Found $nmes mail in $type folder."); |
390
|
|
|
if ($nmes>0) rsort($m_search); |
391
|
|
|
|
392
|
|
|
// Create report file |
393
|
|
|
|
394
|
|
|
$fp = fopen($file, 'w'); |
395
|
|
|
$fpd= fopen($filed, 'w'); |
396
|
|
|
$fpb= fopen($fileb, 'w'); |
397
|
|
|
$lastup = "Last Update: " . date ("d F Y H:i", time()); |
398
|
|
|
writeFileHeader($fp,$cf,'ip',$type,$lastup); |
399
|
|
|
writeFileHeader($fpd,$cf,'dom',$type,$lastup); |
400
|
|
|
|
401
|
|
|
fwrite( $fpb,file_get_contents(dirname(__FILE__) . '/' . $cf['report']['reportTemplateHeader']) ); |
402
|
|
|
fwrite( $fpb,"<h1> Report of bad reported $type mails</h1><h5>$lastup</h5><h2>Detailed Report</h2>" ); |
403
|
|
|
fwrite( $fpb,'<table><tr><th title="taken from Received header" nowrap>Date Learn</th><th title="taken from Date header" nowrap>Date Received</th><th nowrap>UID</th><th>Message-Id</th><th title="Why is this a bad report?">Reason</th></tr>' ); |
404
|
|
|
|
405
|
|
|
$ipuid = array(); |
406
|
|
|
$ipuid['count'] = 0; |
407
|
|
|
$ipuid['uid'] = array(); |
408
|
|
|
$ipuid['ip'] = array(); |
409
|
|
|
$ipuid['ip']['count'] = 0; |
410
|
|
|
$ipuid['uid']['count'] = 0; |
411
|
|
|
$domuid = array(); |
412
|
|
|
$domuid['count'] = 0; |
413
|
|
|
$domuid['dom'] = array(); |
414
|
|
|
$domuid['dom']['count'] = 0; |
415
|
|
|
$domuid['uid'] = array(); |
416
|
|
|
$domuid['uid']['count'] = 0; |
417
|
|
|
$uidbad = array(); |
418
|
|
|
$uidbad['count'] = 0; |
419
|
|
|
$uidbad['uid'] = array(); |
420
|
|
|
|
421
|
|
|
// loop for each message |
422
|
|
|
foreach ($m_search as $onem) { |
423
|
|
|
|
424
|
|
|
//get imap header info for obj thang |
425
|
|
|
//$headers = imap_headerinfo($m_mail, $onem); |
426
|
|
|
//$head = imap_fetchheader($m_mail, $headers->Msgno); |
427
|
|
|
$head = imap_fetchheader($m_mail, $onem ); |
428
|
|
|
//$obj = imap_rfc822_parse_headers( $head); |
429
|
|
|
|
430
|
|
|
list ($ip,$host,$dateReceived,$dateClient,$mid) = getIP( $head,$cf['mx_hostname']['mx'],$cf['msa']['msalearn'] ); |
431
|
|
|
if (empty($mid)) { |
432
|
|
|
$uid='NA'; |
433
|
|
|
syslog (LOG_ERR, $cf['syslog']['user'].": Error retrieving data for empty Message-ID."); |
434
|
|
|
} else { |
435
|
|
|
if ($dateReceived === FALSE) { |
436
|
|
|
$uid='unauthenticated'; |
437
|
|
|
syslog (LOG_ERR, $cf['syslog']['user'].": Error retrieving date for $mid. Maybe this mail was not submitted to Learner MSA"); |
438
|
|
|
} else |
439
|
|
|
if ( !($uid = splunksearch ($splunkconn, trim($mid,'<>'), $dateReceived)) ) { |
440
|
|
|
syslog (LOG_ERR, $cf['syslog']['user'].": Error retrieving uid from Splunk log for $mid."); |
441
|
|
|
$uid='unknown'; |
442
|
|
|
} |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
/* Extract domains url in body */ |
446
|
|
|
$domains = parseURL ($m_mail,$onem,$cf['listingdom']['exclude']); |
447
|
|
|
|
448
|
|
|
/* Update count of each ip */ |
449
|
|
|
if ($host and ($uid!='NA') and ($uid!='unauthenticated') and ($uid!='unknown')) { /* IP is received by MX servers and learned by valid uid */ |
450
|
|
|
$ipuid['count']++; //number of right messages |
451
|
|
|
|
452
|
|
View Code Duplication |
if (in_array($uid,array_keys($ipuid['uid']))) { |
453
|
|
|
$ipuid['uid']["$uid"]['count']++; //number of learn by this uid |
454
|
|
|
if (!in_array($ip,$ipuid['uid']["$uid"])) |
455
|
|
|
$ipuid['uid']["$uid"][]=$ip; //ips learned by this uid |
456
|
|
|
} |
457
|
|
|
else { |
458
|
|
|
$ipuid['uid']["$uid"]['count'] = 1; |
459
|
|
|
$ipuid['uid']["$uid"][]=$ip; |
460
|
|
|
$ipuid['uid']['count']++; //number of unique uids |
461
|
|
|
} |
462
|
|
|
|
463
|
|
View Code Duplication |
if (in_array($ip,array_keys($ipuid['ip']))) { |
464
|
|
|
$ipuid['ip']["$ip"]['count']++; //number of time this ip appears in different messages |
465
|
|
|
if (!in_array($uid,$ipuid['ip']["$ip"])) |
466
|
|
|
$ipuid['ip']["$ip"][]=$uid; //uids that learned this ip |
467
|
|
|
} |
468
|
|
|
else { |
469
|
|
|
$ipuid['ip']["$ip"]['count'] = 1; |
470
|
|
|
$ipuid['ip']["$ip"][]=$uid; |
471
|
|
|
$ipuid['ip']['count']++; //number of unique ips |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
foreach ($domains as $dom) { |
475
|
|
|
$domuid['count']++; |
476
|
|
View Code Duplication |
if (in_array($uid,array_keys($domuid['uid']))) { |
|
|
|
|
477
|
|
|
$domuid['uid']["$uid"]['count']++; //number of learn by this uid |
478
|
|
|
if (!in_array($dom,$domuid['uid']["$uid"])) |
479
|
|
|
$domuid['uid']["$uid"][]=$dom; //domains learned by this uid |
480
|
|
|
} |
481
|
|
|
else { |
482
|
|
|
$domuid['uid']["$uid"]['count'] = 1; |
483
|
|
|
$domuid['uid']["$uid"][]=$dom; |
484
|
|
|
$domuid['uid']['count']++; //number of unique uids |
485
|
|
|
} |
486
|
|
|
|
487
|
|
View Code Duplication |
if (in_array($dom,array_keys($domuid['dom']))) { |
|
|
|
|
488
|
|
|
$domuid['dom']["$dom"]['count']++; //number of learn with this domain |
489
|
|
|
if (!in_array($uid,$domuid['dom']["$dom"])) |
490
|
|
|
$domuid['dom']["$dom"][]=$uid; //uids that learned this domain |
491
|
|
|
} |
492
|
|
|
else { |
493
|
|
|
$domuid['dom']["$dom"]['count'] = 1; |
494
|
|
|
$domuid['dom']["$dom"][]=$uid; |
495
|
|
|
$domuid['dom']['count']++; //number of unique domains |
496
|
|
|
} |
497
|
|
|
|
498
|
|
|
fwrite($fpd, |
499
|
|
|
updateReport ( |
500
|
|
|
$dom,$uid,$domuid['dom']["$dom"]['count'], |
501
|
|
|
$domuid['uid']["$uid"]['count'],$host, |
502
|
|
|
$dateClient,$mid,$dateReceived |
503
|
|
|
) |
504
|
|
|
); |
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
/* Update HTML report */ |
508
|
|
|
fwrite($fp,updateReport ( $ip,$uid,$ipuid['ip']["$ip"]['count'],$ipuid['uid']["$uid"]['count'],$host,$dateClient,$mid,$dateReceived) ); |
509
|
|
|
} |
510
|
|
|
else { /* Bad learn */ |
511
|
|
|
|
512
|
|
|
if (in_array($uid,array_keys($uidbad['uid']))) |
513
|
|
|
$uidbad['uid']["$uid"]['count']++; //number of bad learn by this uid |
514
|
|
|
else { |
515
|
|
|
$uidbad['uid']["$uid"]['count'] = 1; |
516
|
|
|
$uidbad['uid']["$uid"][]=$uid; |
517
|
|
|
$uidbad['count']++; //numeber of unique bad uids |
518
|
|
|
} |
519
|
|
|
/* The reason of bad report */ |
520
|
|
|
if ($host === FALSE) $reason = 'This mail was not received by recognized MX host'; |
521
|
|
|
if ($dateReceived === FALSE) $reason = 'This mail was not submitted to recognized MSA for learn'; |
522
|
|
|
if ($uid=='unknown') $reason = 'The uid of this mail was not found in splunk log'; |
523
|
|
|
if (!isset($reason)) $reason = '?'; |
524
|
|
|
|
525
|
|
|
fwrite( $fpb,updatebadReport ( $uid,$dateClient,$mid,$dateReceived,$reason ) ); |
526
|
|
|
} |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
|
530
|
|
|
//close report file and mailbox |
531
|
|
|
|
532
|
|
|
/* Summary Report */ |
533
|
|
|
$ipuid['ip'] = array_msort( $ipuid['ip'], array('count'=>SORT_DESC) ); |
534
|
|
|
$ipuid['uid'] = array_msort( $ipuid['uid'], array('count'=>SORT_DESC) ); |
535
|
|
|
$domuid['dom'] = array_msort( $domuid['dom'], array('count'=>SORT_DESC) ); |
536
|
|
|
$domuid['uid'] = array_msort( $domuid['uid'], array('count'=>SORT_DESC) ); |
537
|
|
|
$uidbad['uid'] = array_msort( $uidbad['uid'], array('count'=>SORT_DESC) ); |
538
|
|
|
|
539
|
|
|
fwrite($fp, '</table>'); |
540
|
|
|
fwrite($fpd, '</table>'); |
541
|
|
|
fwrite($fp, '<hr><h2>Summary Report</h2><h5>Listing policy: ip must be learned at least '.$cf['listingip']['threshold']["$type"].' times from at least '.$cf['listingip']['thresholduid']["$type"].' different valid uids.</h5>' ); |
542
|
|
|
fwrite($fpd, '<hr><h2>Summary Report</h2><h5>Listing policy: domains must be learned at least '.$cf['listingdom']['threshold']["$type"].' times from at least '.$cf['listingdom']['thresholduid']["$type"].' different valid uids.</h5>' ); |
543
|
|
|
|
544
|
|
|
/* Make MYSQL connection */ |
545
|
|
|
if ( $cf['listingip']['onlyReport']["$type"] && $cf['listingdom']['onlyReport']["$type"] ) |
546
|
|
|
$mysqli = NULL; |
547
|
|
|
else { |
548
|
|
|
$mysqli = new mysqli($myconnArray['dbhost'], $myconnArray['userdb'], $myconnArray['pwd'], $myconnArray['db'], $myconnArray['dbport']); |
549
|
|
|
if ($mysqli->connect_error) { |
550
|
|
|
syslog (LOG_EMERG, $cf['syslog']['user'].': Connect Error (' . $mysqli->connect_errno . ') ' |
551
|
|
|
. $mysqli->connect_error); |
552
|
|
|
exit (254); |
553
|
|
|
} |
554
|
|
|
syslog(LOG_INFO, $cf['syslog']['user'].': Successfully mysql connected to ' . $mysqli->host_info) ; |
555
|
|
|
} |
556
|
|
|
/***********************/ |
557
|
|
|
|
558
|
|
|
fwrite($fp, summaryReportAndList ($cf,$mysqli,$tables,$type,$ipuid, 'ip') ); |
559
|
|
|
fwrite($fp,file_get_contents(dirname(__FILE__) . '/' . $cf['report']['reportTemplateFooter'])); |
560
|
|
|
fclose($fp); |
561
|
|
|
|
562
|
|
|
fwrite($fpd, summaryReportAndList ($cf,$mysqli,$tables,$type,$domuid, 'dom') ); |
563
|
|
|
fwrite($fpd,file_get_contents(dirname(__FILE__) . '/' . $cf['report']['reportTemplateFooter'])); |
564
|
|
|
fclose($fpd); |
565
|
|
|
|
566
|
|
|
if ( !($cf['listingip']['onlyReport']["$type"] && $cf['listingdom']['onlyReport']["$type"]) ) |
567
|
|
|
$mysqli->close(); |
568
|
|
|
|
569
|
|
|
fwrite($fpb, '</table>'); |
570
|
|
|
fwrite( $fpb,summaryBadReport( $uidbad ) ); |
571
|
|
|
fwrite($fpb,file_get_contents(dirname(__FILE__) . '/' . $cf['report']['reportTemplateFooter'])); |
572
|
|
|
fclose($fpb); |
573
|
|
|
syslog (LOG_INFO,$cf['syslog']['user'].': Report files written. Listing job for '.$type.' terminated.'); |
574
|
|
|
|
575
|
|
View Code Duplication |
if ( $ierr = imap_errors() ) |
576
|
|
|
foreach ( $ierr as $thiserr ) |
577
|
|
|
syslog (LOG_ERR, $cf['syslog']['user'].": IMAP Error: $thiserr"); |
578
|
|
View Code Duplication |
if ( $ierr = imap_alerts() ) |
579
|
|
|
foreach ( $ierr as $thiserr ) |
580
|
|
|
syslog (LOG_ALERT, $cf['syslog']['user'].": IMAP Alert: $thiserr"); |
581
|
|
|
imap_close($m_mail); |
582
|
|
|
} |
583
|
|
|
?> |
584
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.