Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117918986
D4692.1775421292.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
D4692.1775421292.diff
View Options
diff --git a/src/app/Listeners/SqlDebug.php b/src/app/Listeners/SqlDebug.php
--- a/src/app/Listeners/SqlDebug.php
+++ b/src/app/Listeners/SqlDebug.php
@@ -68,6 +68,8 @@
$serialized = array_map(function ($entry) use ($ipv) {
if ($entry instanceof \DateTime) {
return $entry->format('Y-m-d h:i:s');
+ } elseif (is_bool($entry)) {
+ return $entry ? 'true' : 'false';
} elseif ($ipv && is_string($entry) && strlen($entry) == ($ipv == 6 ? 16 : 4)) {
// binary IP address? use HEX representation
return '0x' . bin2hex($entry);
diff --git a/src/app/Policy/Greylist/Request.php b/src/app/Policy/Greylist/Request.php
--- a/src/app/Policy/Greylist/Request.php
+++ b/src/app/Policy/Greylist/Request.php
@@ -6,6 +6,7 @@
class Request
{
+ protected $connect;
protected $header;
protected $netID;
protected $netType;
@@ -19,6 +20,11 @@
protected $whitelist;
protected $request = [];
+ /**
+ * Class constructor
+ *
+ * @param array $request Request input
+ */
public function __construct($request)
{
$this->request = $request;
@@ -30,14 +36,17 @@
}
}
- public function headerGreylist()
+ /**
+ * Get request state headers (Received-Greylist) - after self::shouldDefer() call
+ */
+ public function headerGreylist(): string
{
if ($this->whitelist) {
if ($this->whitelist->sender_local) {
return sprintf(
- "Received-Greylist: sender %s whitelisted since %s",
+ "Received-Greylist: sender %s whitelisted since %s (UTC)",
$this->sender,
- $this->whitelist->created_at->toDateString()
+ $this->whitelist->created_at->toDateTimeString()
);
}
@@ -49,20 +58,23 @@
);
}
- $connect = $this->findConnectsCollection()->orderBy('created_at')->first();
-
- if ($connect) {
+ if ($this->connect) {
return sprintf(
"Received-Greylist: greylisted from %s until %s.",
- $connect->created_at,
- $this->timestamp
+ $this->connect->created_at->toDateTimeString(),
+ $this->timestamp->toDateTimeString()
);
}
return "Received-Greylist: no opinion here";
}
- public function shouldDefer()
+ /**
+ * Connection check regarding greylisting policy
+ *
+ * @return bool True if the message should be put off, False otherwise
+ */
+ public function shouldDefer(): bool
{
list($this->netID, $this->netType) = \App\Utils::getNetFromAddress($this->request['client_address']);
@@ -82,11 +94,13 @@
$this->senderLocal = substr($this->senderLocal, 0, 255);
}
- // Purge all old information if we have no recent entries
- $noEntry = false;
- if (!$this->findConnectsCollectionRecent()->exists()) {
+ // Get the most recent entry
+ $connect = $this->findConnectsCollection()->first();
+
+ // Purge all old information if we have no recent entry
+ if ($connect && $connect->updated_at < $this->timestamp->copy()->subDays(7)) {
$this->findConnectsCollection()->delete();
- $noEntry = true;
+ $connect = null;
}
// See if the recipient opted-out of the feature
@@ -100,80 +114,52 @@
// the following block is to maintain statistics and state ...
// determine if the sender domain is a whitelist from this network
- $this->whitelist = Whitelist::where(
- [
- 'sender_domain' => $this->senderDomain,
- 'net_id' => $this->netID,
- 'net_type' => $this->netType
- ]
- )->first();
+ $this->whitelist = Whitelist::where('sender_domain', $this->senderDomain)
+ ->where('net_id', $this->netID)
+ ->where('net_type', $this->netType)
+ ->first();
+
+ $cutoffDate = $this->timestamp->copy()->subDays(7)->startOfDay();
- $cutoffDate = $this->timestamp->copy()->subDays(7);
+ DB::beginTransaction();
+
+ // Whitelist older than a month, delete it
+ if ($this->whitelist && $this->whitelist->updated_at < $this->timestamp->copy()->subMonthsWithoutOverflow(1)) {
+ $this->whitelist->delete();
+ $this->whitelist = null;
+ }
+ $all = Connect::where('sender_domain', $this->senderDomain)
+ ->where('net_id', $this->netID)
+ ->where('net_type', $this->netType)
+ ->where('updated_at', '>=', $cutoffDate->toDateTimeString());
+
+ // "Touch" the whitelist if exists
if ($this->whitelist) {
- if ($this->whitelist->updated_at < $this->timestamp->copy()->subMonthsWithoutOverflow(1)) {
- $this->whitelist->delete();
- } else {
+ // For performance reasons do not update timestamp more than once per 1 minute
+ // FIXME: Such granularity should be good enough, right? It might be a problem
+ // if you wanted to compare this timestamp with mail log entries.
+ if ($this->whitelist->updated_at < $this->timestamp->copy()->subMinute()) {
$this->whitelist->updated_at = $this->timestamp;
$this->whitelist->save(['timestamps' => false]);
-
- Connect::where(
- [
- 'sender_domain' => $this->senderDomain,
- 'net_id' => $this->netID,
- 'net_type' => $this->netType,
- 'greylisting' => true
- ]
- )
- ->whereDate('updated_at', '>=', $cutoffDate)
- ->update(
- [
- 'greylisting' => false,
- 'updated_at' => $this->timestamp
- ]
- );
-
- return false;
}
- } else {
- $count = Connect::where(
- [
- 'sender_domain' => $this->senderDomain,
- 'net_id' => $this->netID,
- 'net_type' => $this->netType
- ]
- )
- ->whereDate('updated_at', '>=', $cutoffDate)
- ->limit(4)->count();
+ $all->where('greylisting', true)
+ ->update(['greylisting' => false, 'updated_at' => $this->timestamp]);
+
+ $enabled = false;
+ } elseif ($all->count() >= 4) {
// Automatically create a whitelist if we have at least 5 (4 existing plus this) messages from the sender
- if ($count >= 4) {
- $this->whitelist = Whitelist::create(
- [
- 'sender_domain' => $this->senderDomain,
- 'net_id' => $this->netID,
- 'net_type' => $this->netType,
- 'created_at' => $this->timestamp,
- 'updated_at' => $this->timestamp
- ]
- );
+ $this->whitelist = Whitelist::create([
+ 'sender_domain' => $this->senderDomain,
+ 'net_id' => $this->netID,
+ 'net_type' => $this->netType,
+ 'created_at' => $this->timestamp,
+ 'updated_at' => $this->timestamp
+ ]);
- Connect::where(
- [
- 'sender_domain' => $this->senderDomain,
- 'net_id' => $this->netID,
- 'net_type' => $this->netType,
- 'greylisting' => true
- ]
- )
- ->whereDate('updated_at', '>=', $cutoffDate)
- ->update(
- [
- 'greylisting' => false,
- 'updated_at' => $this->timestamp
- ]
- );
- }
+ $all->where('greylisting', true)
+ ->update(['greylisting' => false, 'updated_at' => $this->timestamp]);
}
// TODO: determine if the sender (individual) is a whitelist
@@ -181,13 +167,14 @@
// TODO: determine if the sender is a penpal of any of the recipients. First recipient wins.
if (!$enabled) {
+ DB::commit();
return false;
}
$defer = true;
- // Retrieve the entry for the sender/recipient/net combination
- if (!$noEntry && ($connect = $this->findConnectsCollection()->first())) {
+ // Update/Create an entry for the sender/recipient/net combination
+ if ($connect) {
$connect->connect_count += 1;
// TODO: The period of time for which the greylisting persists is configurable.
@@ -199,8 +186,7 @@
$connect->save();
} else {
- Connect::create(
- [
+ $connect = Connect::create([
'sender_local' => $this->senderLocal,
'sender_domain' => $this->senderDomain,
'net_id' => $this->netID,
@@ -210,35 +196,28 @@
'recipient_type' => $this->recipientType,
'created_at' => $this->timestamp,
'updated_at' => $this->timestamp
- ]
- );
+ ]);
}
+ $this->connect = $connect;
+
+ DB::commit();
+
return $defer;
}
- private function findConnectsCollection()
+ protected function findConnectsCollection()
{
- $collection = Connect::where(
- [
+ return Connect::where([
'sender_local' => $this->senderLocal,
'sender_domain' => $this->senderDomain,
'recipient_hash' => $this->recipientHash,
'net_id' => $this->netID,
'net_type' => $this->netType,
- ]
- );
-
- return $collection;
- }
-
- private function findConnectsCollectionRecent()
- {
- return $this->findConnectsCollection()
- ->where('updated_at', '>=', $this->timestamp->copy()->subDays(7));
+ ]);
}
- private function recipientFromRequest()
+ protected function recipientFromRequest()
{
$recipients = \App\Utils::findObjectsByRecipientAddress($this->request['recipient']);
@@ -265,7 +244,7 @@
return $recipient;
}
- public function senderFromRequest()
+ protected function senderFromRequest()
{
return \App\Utils::normalizeAddress($this->request['sender']);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 5, 8:34 PM (11 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18834395
Default Alt Text
D4692.1775421292.diff (10 KB)
Attached To
Mode
D4692: Improve greylist handler
Attached
Detach File
Event Timeline