Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions plugins/identity_select/identity_select.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,15 @@ public function select($p)
}

$rcmail = rcmail::get_instance();
$identities = [];
foreach ($p['identities'] as $idx => $ident) {
$identities[$idx] = mb_strtolower($ident['email']);
}

foreach ((array) $rcmail->config->get('identity_select_headers', []) as $header) {
if ($emails = $this->get_email_from_header($p['message'], $header)) {
foreach ($p['identities'] as $idx => $ident) {
if (in_array($ident['email_ascii'], $emails)) {
foreach ($emails as $email) {
if (($idx = array_search(mb_strtolower($email), $identities)) !== false) {
$p['selected'] = $idx;
break 2;
}
Expand All @@ -83,16 +87,16 @@ protected function get_email_from_header($message, $header)
$value = $message->headers->get($header, false);

if (strtolower($header) == 'received') {
// find first email address in all Received headers
$email = null;
foreach ((array) $value as $entry) {
if (preg_match('/[\s\t]+for[\s\t]+<([^>]+)>/', $entry, $matches)) {
$email = $matches[1];
break;
// find all email addresses in all Received headers
$emails = [];
// reverse the header array as RFC 5321 requires additional Received headers are prepended
foreach (array_reverse((array) $value) as $entry) {
if (preg_match('/[\s\t]+for\s+<?([^\s>@]+@[^\s]+\.[^\s>;]+)>?/u', $entry, $matches)) {
$emails[] = $matches[1];
}
}

$value = $email;
$value = $emails;
}

return (array) $value;
Expand Down
45 changes: 45 additions & 0 deletions plugins/identity_select/tests/IdentitySelectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use PHPUnit\Framework\TestCase;

use function Roundcube\Tests\invokeMethod;

class IdentitySelectTest extends TestCase
{
/**
Expand All @@ -17,4 +19,47 @@ public function test_constructor()
$this->assertInstanceOf('identity_select', $plugin);
$this->assertInstanceOf('rcube_plugin', $plugin);
}

/**
* Test get_email_from_header() method
*/
public function test_get_email_from_header()
{
$rcube = \rcube::get_instance();
$plugin = new \identity_select($rcube->plugins);
$message = new \stdClass();

$headers = [
'Delivered-To' => 'user@example.com',
'Received' => 'from github.com ([10.48.109.45]) by smtp.github.com (Postfix) with ESMTPA id 8C9B4E0075'
. ' for <john@domain.tld>; Sat, 28 Nov 2020 22:45:44 -0800 (PST)',
];
$message->headers = \rcube_message_header::from_array($headers);
$result = invokeMethod($plugin, 'get_email_from_header', [$message, 'Delivered-To']);
$this->assertSame(['user@example.com'], $result);
$result = invokeMethod($plugin, 'get_email_from_header', [$message, 'Received']);
$this->assertSame(['john@domain.tld'], $result);

$headers = [
'Received' => [
'from mail.aliasprovider.com (mail.aliasprovider.com [198.51.100.20]) by smtp.example.com (Postfix) with ESMTP id 555AAA777'
. ' for chris.smith@example.com; Sun, 10 May 2026 16:00:01 -0400 (EDT)',
'from mail.external.com (mail.external.com [203.0.113.45]) by mail.aliasprovider.com (Postfix) with ESMTP id 444BBB666'
. ' for bob.smith@example.com; Sun, 10 May 2026 16:00:00 -0400 (EDT)',
'from client.mail.com (client.mail.com [192.0.2.10]) by mail.external.com (Postfix) with ESMTP id 333CCC555'
. ' for sales@example.com; Sun, 10 May 2026 15:59:58 -0400 (EDT)',
],
];
$message->headers = \rcube_message_header::from_array($headers);
$result = invokeMethod($plugin, 'get_email_from_header', [$message, 'Received']);
$this->assertSame(['sales@example.com', 'bob.smith@example.com', 'chris.smith@example.com'], $result);

$headers = [
'Received' => 'from mail.aliasprovider.com (mail.aliasprovider.com [198.51.100.20]) by smtp.example.com (Postfix) with ESMTP id 555AAA777'
. ' for <josé.müller@example.com>; Sun, 10 May 2026 16:30:01 -0400 (EDT)',
];
$message->headers = \rcube_message_header::from_array($headers);
$result = invokeMethod($plugin, 'get_email_from_header', [$message, 'Received']);
$this->assertSame(['josé.müller@example.com'], $result);
}
}
Loading