Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Tests for core_message_inbound to test Variable Envelope Return Path functionality.
  19   *
  20   * @package    core_message
  21   * @copyright  2014 Andrew Nicols <andrew@nicols.co.uk>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  require_once (__DIR__ . '/fixtures/inbound_fixtures.php');
  27  
  28  /**
  29   * Tests for core_message_inbound to test Variable Envelope Return Path functionality.
  30   *
  31   * @copyright  2014 Andrew Nicols <andrew@nicols.co.uk>
  32   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class core_message_inbound_testcase extends advanced_testcase {
  35  
  36      /**
  37       * Perform setup tasks generic to each test.
  38       * This includes:
  39       * * configuring the messageinbound_mailbox.
  40       */
  41      public function setUp(): void {
  42          global $CFG;
  43  
  44          $this->resetAfterTest(true);
  45  
  46          // Setup the default Inbound Message mailbox settings.
  47          $CFG->messageinbound_domain = 'example.com';
  48          $CFG->messageinbound_enabled = true;
  49  
  50          // Must be no longer than 15 characters.
  51          $CFG->messageinbound_mailbox = 'moodlemoodle123';
  52      }
  53  
  54      /**
  55       * Helper to create a new Inbound Message handler.
  56       *
  57       * @param $handlerclass The class of the handler to create
  58       * @param $enabled Whether the handler should be enabled
  59       * @param $component The component
  60       * @param $namepace The namepace
  61       */
  62      public function helper_create_handler($handlerclass, $enabled = true, $component = 'core_test', $namespace = '\\core\\test\\') {
  63          global $DB;
  64  
  65          $classname = $namespace . $handlerclass;
  66          $record = \core\message\inbound\manager::record_from_handler(new $classname());
  67          $record->component = $component;
  68          $record->enabled = $enabled;
  69          $record->id = $DB->insert_record('messageinbound_handlers', $record);
  70          $handler = \core_message_inbound_test_manager::handler_from_record($record);
  71  
  72          return $handler;
  73      }
  74  
  75      /**
  76       * Test that the enabled check perform as expected.
  77       */
  78      public function test_is_enabled() {
  79          global $CFG;
  80  
  81          // First clear all of the settings set in the setUp.
  82          $CFG->messageinbound_domain = null;
  83          $CFG->messageinbound_enabled = null;
  84          $CFG->messageinbound_mailbox = null;
  85  
  86          $this->assertFalse(\core\message\inbound\manager::is_enabled());
  87  
  88          // Check whether only setting the enabled flag keeps it disabled.
  89          $CFG->messageinbound_enabled = true;
  90          $this->assertFalse(\core\message\inbound\manager::is_enabled());
  91  
  92          // Check that the mailbox entry on it's own does not enable Inbound Message handling.
  93          $CFG->messageinbound_mailbox = 'moodlemoodle123';
  94          $CFG->messageinbound_domain = null;
  95          $this->assertFalse(\core\message\inbound\manager::is_enabled());
  96  
  97          // And that the domain on it's own does not.
  98          $CFG->messageinbound_domain = 'example.com';
  99          $CFG->messageinbound_mailbox = null;
 100          $this->assertFalse(\core\message\inbound\manager::is_enabled());
 101  
 102          // And that an invalid mailbox does not.
 103          $CFG->messageinbound_mailbox = '';
 104          $CFG->messageinbound_domain = 'example.com';
 105          $this->assertFalse(\core\message\inbound\manager::is_enabled());
 106  
 107          // And that an invalid domain does not.
 108          $CFG->messageinbound_domain = '';
 109          $CFG->messageinbound_mailbox = 'moodlemoodle123';
 110          $this->assertFalse(\core\message\inbound\manager::is_enabled());
 111  
 112          // Finally a test that ensures that all settings correct enables the system.
 113          $CFG->messageinbound_mailbox = 'moodlemoodle123';
 114          $CFG->messageinbound_domain = 'example.com';
 115          $CFG->messageinbound_enabled = true;
 116  
 117          $this->assertTrue(\core\message\inbound\manager::is_enabled());
 118      }
 119  
 120      /**
 121       * Test that data items conform to RFCs 5231, and 5322 standards for
 122       * addressing, and to RFC 5233 for sub-addressing.
 123       */
 124      public function test_address_constraints() {
 125          $handler = $this->helper_create_handler('handler_one');
 126  
 127          // Using the handler created, generate an address for our data entry.
 128          $processor = new core_message_inbound_test_helper();
 129          $processor->set_handler($handler->classname);
 130  
 131          // Generate some IDs for the data and generate addresses for them.
 132          $dataids = array(
 133              -1,
 134              0,
 135              42,
 136              1073741823,
 137              2147483647,
 138          );
 139  
 140          $user = $this->getDataGenerator()->create_user();
 141          foreach ($dataids as $dataid) {
 142              $processor->set_data($dataid);
 143              $address = $processor->generate($user->id);
 144              $this->assertNotNull($address);
 145              $this->assertTrue(strlen($address) > 0, 'No address generated.');
 146              $this->assertTrue(strpos($address, '@') !== false, 'No domain found.');
 147              $this->assertTrue(strpos($address, '+') !== false, 'No subaddress found.');
 148  
 149              // The localpart must be less than 64 characters.
 150              list($localpart) = explode('@', $address);
 151              $this->assertTrue(strlen($localpart) <= 64, 'Localpart section of address too long');
 152  
 153              // And the data section should be no more than 48 characters.
 154              list(, $datasection) = explode('+', $localpart);
 155              $this->assertTrue(strlen($datasection) <= 48, 'Data section of address too long');
 156          }
 157      }
 158  
 159      /**
 160       * Test that the generated e-mail addresses are sufficiently random by
 161       * testing the multiple handlers, multiple users, and multiple data
 162       * items.
 163       */
 164      public function test_address_uniqueness() {
 165          // Generate a set of handlers. These are in two components, and each
 166          // component has two different generators.
 167          $handlers = array();
 168          $handlers[] = $this->helper_create_handler('handler_one', true, 'core_test');
 169          $handlers[] = $this->helper_create_handler('handler_two', true, 'core_test');
 170          $handlers[] = $this->helper_create_handler('handler_three', true, 'core_test_example');
 171          $handlers[] = $this->helper_create_handler('handler_four', true, 'core_test_example');
 172  
 173          // Generate some IDs for the data and generate addresses for them.
 174          $dataids = array(
 175              0,
 176              42,
 177              1073741823,
 178              2147483647,
 179          );
 180  
 181          $users = array();
 182          for ($i = 0; $i < 5; $i++) {
 183              $users[] = $this->getDataGenerator()->create_user();
 184          }
 185  
 186          // Store the addresses for later comparison.
 187          $addresses = array();
 188  
 189          foreach ($handlers as $handler) {
 190              $processor = new core_message_inbound_test_helper();
 191              $processor->set_handler($handler->classname);
 192  
 193              // Check each dataid.
 194              foreach ($dataids as $dataid) {
 195                  $processor->set_data($dataid);
 196  
 197                  // Check each user.
 198                  foreach ($users as $user) {
 199                      $address = $processor->generate($user->id);
 200                      $this->assertFalse(isset($addresses[$address]));
 201                      $addresses[$address] = true;
 202                  }
 203              }
 204          }
 205      }
 206  
 207      /**
 208       * Test address parsing of a generated address.
 209       */
 210      public function test_address_parsing() {
 211          $dataid = 42;
 212  
 213          // Generate a handler to use for this set of tests.
 214          $handler = $this->helper_create_handler('handler_one');
 215  
 216          // And a user.
 217          $user = $this->getDataGenerator()->create_user();
 218  
 219          // Using the handler created, generate an address for our data entry.
 220          $processor = new core_message_inbound_test_helper();
 221          $processor->set_handler($handler->classname);
 222          $processor->set_data($dataid);
 223          $address = $processor->generate($user->id);
 224  
 225          // We should be able to parse the address.
 226          $parser = new core_message_inbound_test_helper();
 227          $parser->process($address);
 228          $parsedresult = $parser->get_data();
 229          $this->assertEquals($user->id, $parsedresult->userid);
 230          $this->assertEquals($dataid, $parsedresult->datavalue);
 231          $this->assertEquals($dataid, $parsedresult->data->datavalue);
 232          $this->assertEquals($handler->id, $parsedresult->handlerid);
 233          $this->assertEquals($handler->id, $parsedresult->data->handler);
 234      }
 235  
 236      /**
 237       * Test address parsing of an address with an unrecognised format.
 238       */
 239      public function test_address_validation_invalid_format_failure() {
 240          // Create test data.
 241          $user = $this->getDataGenerator()->create_user();
 242          $handler = $this->helper_create_handler('handler_one');
 243          $dataid = 42;
 244  
 245          $parser = new core_message_inbound_test_helper();
 246  
 247          $generator = new core_message_inbound_test_helper();
 248          $generator->set_handler($handler->classname);
 249  
 250          // Check that validation fails when no address has been processed.
 251          $result = $parser->validate($user->email);
 252          $this->assertEquals(\core\message\inbound\address_manager::VALIDATION_INVALID_ADDRESS_FORMAT, $result);
 253  
 254          // Test that an address without data fails validation.
 255          $parser->process('bob@example.com');
 256          $result = $parser->validate($user->email);
 257          $this->assertEquals(\core\message\inbound\address_manager::VALIDATION_INVALID_ADDRESS_FORMAT, $result);
 258  
 259          // Test than address with a subaddress but invalid data fails with VALIDATION_UNKNOWN_DATAKEY.
 260          $parser->process('bob+nodata@example.com');
 261          $result = $parser->validate($user->email);
 262          $this->assertEquals(\core\message\inbound\address_manager::VALIDATION_INVALID_ADDRESS_FORMAT, $result);
 263      }
 264  
 265      /**
 266       * Test address parsing of an address with an unknown handler.
 267       */
 268      public function test_address_validation_unknown_handler() {
 269          global $DB;
 270  
 271          // Create test data.
 272          $user = $this->getDataGenerator()->create_user();
 273          $handler = $this->helper_create_handler('handler_one');
 274          $dataid = 42;
 275  
 276          $parser = new core_message_inbound_test_helper();
 277  
 278          $generator = new core_message_inbound_test_helper();
 279          $generator->set_handler($handler->classname);
 280          $generator->set_data($dataid);
 281          $address = $generator->generate($user->id);
 282  
 283          // Remove the handler record to invalidate it.
 284          $DB->delete_records('messageinbound_handlers', array(
 285              'id' => $handler->id,
 286          ));
 287  
 288          $parser->process($address);
 289          $result = $parser->validate($user->email);
 290          $expectedfail = \core\message\inbound\address_manager::VALIDATION_UNKNOWN_HANDLER;
 291          $this->assertEquals($expectedfail, $result & $expectedfail);
 292      }
 293  
 294      /**
 295       * Test address parsing of an address with a disabled handler.
 296       */
 297      public function test_address_validation_disabled_handler() {
 298          global $DB;
 299  
 300          // Create test data.
 301          $user = $this->getDataGenerator()->create_user();
 302          $handler = $this->helper_create_handler('handler_one');
 303          $dataid = 42;
 304  
 305          $parser = new core_message_inbound_test_helper();
 306  
 307          $generator = new core_message_inbound_test_helper();
 308          $generator->set_handler($handler->classname);
 309          $generator->set_data($dataid);
 310          $address = $generator->generate($user->id);
 311  
 312          // Disable the handler.
 313          $record = \core\message\inbound\manager::record_from_handler($handler);
 314          $record->enabled = false;
 315          $DB->update_record('messageinbound_handlers', $record);
 316  
 317          $parser->process($address);
 318          $result = $parser->validate($user->email);
 319          $expectedfail = \core\message\inbound\address_manager::VALIDATION_DISABLED_HANDLER;
 320          $this->assertEquals($expectedfail, $result & $expectedfail);
 321      }
 322  
 323      /**
 324       * Test address parsing of an address for an invalid user.
 325       */
 326      public function test_address_validation_invalid_user() {
 327          global $DB;
 328  
 329          // Create test data.
 330          $user = $this->getDataGenerator()->create_user();
 331          $handler = $this->helper_create_handler('handler_one');
 332          $dataid = 42;
 333  
 334          $parser = new core_message_inbound_test_helper();
 335  
 336          $generator = new core_message_inbound_test_helper();
 337          $generator->set_handler($handler->classname);
 338          $generator->set_data($dataid);
 339          $address = $generator->generate(-1);
 340  
 341          $parser->process($address);
 342          $result = $parser->validate($user->email);
 343          $expectedfail = \core\message\inbound\address_manager::VALIDATION_UNKNOWN_USER;
 344          $this->assertEquals($expectedfail, $result & $expectedfail);
 345      }
 346  
 347      /**
 348       * Test address parsing of an address for a disabled user.
 349       */
 350      public function test_address_validation_disabled_user() {
 351          global $DB;
 352  
 353          // Create test data.
 354          $user = $this->getDataGenerator()->create_user();
 355          $handler = $this->helper_create_handler('handler_one');
 356          $dataid = 42;
 357  
 358          $parser = new core_message_inbound_test_helper();
 359  
 360          $generator = new core_message_inbound_test_helper();
 361          $generator->set_handler($handler->classname);
 362          $generator->set_data($dataid);
 363          $address = $generator->generate($user->id);
 364  
 365          // Unconfirm the user.
 366          $user->confirmed = 0;
 367          $DB->update_record('user', $user);
 368  
 369          $parser->process($address);
 370          $result = $parser->validate($user->email);
 371          $expectedfail = \core\message\inbound\address_manager::VALIDATION_DISABLED_USER;
 372          $this->assertEquals($expectedfail, $result & $expectedfail);
 373      }
 374  
 375      /**
 376       * Test address parsing of an address for an invalid key.
 377       */
 378      public function test_address_validation_invalid_key() {
 379          global $DB;
 380  
 381          // Create test data.
 382          $user = $this->getDataGenerator()->create_user();
 383          $handler = $this->helper_create_handler('handler_one');
 384          $dataid = 42;
 385  
 386          $parser = new core_message_inbound_test_helper();
 387  
 388          $generator = new core_message_inbound_test_helper();
 389          $generator->set_handler($handler->classname);
 390          $generator->set_data($dataid);
 391          $address = $generator->generate($user->id);
 392  
 393          // Remove the data record to invalidate it.
 394          $DB->delete_records('messageinbound_datakeys', array(
 395              'handler' => $handler->id,
 396              'datavalue' => $dataid,
 397          ));
 398  
 399          $parser->process($address);
 400          $result = $parser->validate($user->email);
 401          $expectedfail = \core\message\inbound\address_manager::VALIDATION_UNKNOWN_DATAKEY;
 402          $this->assertEquals($expectedfail, $result & $expectedfail);
 403      }
 404  
 405      /**
 406       * Test address parsing of an address for an expired key.
 407       */
 408      public function test_address_validation_expired_key() {
 409          global $DB;
 410  
 411          // Create test data.
 412          $user = $this->getDataGenerator()->create_user();
 413          $handler = $this->helper_create_handler('handler_one');
 414          $dataid = 42;
 415  
 416          $parser = new core_message_inbound_test_helper();
 417  
 418          $generator = new core_message_inbound_test_helper();
 419          $generator->set_handler($handler->classname);
 420          $generator->set_data($dataid);
 421          $address = $generator->generate($user->id);
 422  
 423          // Expire the key by setting it's expiry time in the past.
 424          $key = $DB->get_record('messageinbound_datakeys', array(
 425              'handler' => $handler->id,
 426              'datavalue' => $dataid,
 427          ));
 428  
 429          $key->expires = time() - 3600;
 430          $DB->update_record('messageinbound_datakeys', $key);
 431  
 432          $parser->process($address);
 433          $result = $parser->validate($user->email);
 434          $expectedfail = \core\message\inbound\address_manager::VALIDATION_EXPIRED_DATAKEY;
 435          $this->assertEquals($expectedfail, $result & $expectedfail);
 436      }
 437  
 438      /**
 439       * Test address parsing of an address for an invalid hash.
 440       */
 441      public function test_address_validation_invalid_hash() {
 442          global $DB;
 443  
 444          // Create test data.
 445          $user = $this->getDataGenerator()->create_user();
 446          $handler = $this->helper_create_handler('handler_one');
 447          $dataid = 42;
 448  
 449          $parser = new core_message_inbound_test_helper();
 450  
 451          $generator = new core_message_inbound_test_helper();
 452          $generator->set_handler($handler->classname);
 453          $generator->set_data($dataid);
 454          $address = $generator->generate($user->id);
 455  
 456          // Expire the key by setting it's expiry time in the past.
 457          $key = $DB->get_record('messageinbound_datakeys', array(
 458              'handler' => $handler->id,
 459              'datavalue' => $dataid,
 460          ));
 461  
 462          $key->datakey = 'invalid value';
 463          $DB->update_record('messageinbound_datakeys', $key);
 464  
 465          $parser->process($address);
 466          $result = $parser->validate($user->email);
 467          $expectedfail = \core\message\inbound\address_manager::VALIDATION_INVALID_HASH;
 468          $this->assertEquals($expectedfail, $result & $expectedfail);
 469      }
 470  
 471      /**
 472       * Test address parsing of an address for an invalid sender.
 473       */
 474      public function test_address_validation_invalid_sender() {
 475          global $DB;
 476  
 477          // Create test data.
 478          $user = $this->getDataGenerator()->create_user();
 479          $handler = $this->helper_create_handler('handler_one');
 480          $dataid = 42;
 481  
 482          $parser = new core_message_inbound_test_helper();
 483  
 484          $generator = new core_message_inbound_test_helper();
 485          $generator->set_handler($handler->classname);
 486          $generator->set_data($dataid);
 487          $address = $generator->generate($user->id);
 488  
 489          $parser->process($address);
 490          $result = $parser->validate('incorrectuser@example.com');
 491          $expectedfail = \core\message\inbound\address_manager::VALIDATION_ADDRESS_MISMATCH;
 492          $this->assertEquals($expectedfail, $result & $expectedfail);
 493      }
 494  
 495      /**
 496       * Test address parsing of an address for an address which is correct.
 497       */
 498      public function test_address_validation_success() {
 499          global $DB;
 500  
 501          // Create test data.
 502          $user = $this->getDataGenerator()->create_user();
 503          $handler = $this->helper_create_handler('handler_one');
 504          $dataid = 42;
 505  
 506          $parser = new core_message_inbound_test_helper();
 507  
 508          $generator = new core_message_inbound_test_helper();
 509          $generator->set_handler($handler->classname);
 510          $generator->set_data($dataid);
 511          $address = $generator->generate($user->id);
 512  
 513          $parser->process($address);
 514          $result = $parser->validate($user->email);
 515          $this->assertEquals(\core\message\inbound\address_manager::VALIDATION_SUCCESS, $result);
 516  
 517      }
 518  
 519      /**
 520       * Test that a handler with no default expiration does not have an
 521       * expiration time applied.
 522       */
 523      public function test_default_hander_expiry_unlimited() {
 524          global $DB;
 525  
 526          // Set the default expiry of the handler to 0 - no expiration.
 527          $expiration = 0;
 528  
 529          // Create test data.
 530          $user = $this->getDataGenerator()->create_user();
 531          $handler = $this->helper_create_handler('handler_one');
 532  
 533          $record = \core\message\inbound\manager::record_from_handler($handler);
 534          $record->defaultexpiration = $expiration;
 535          $DB->update_record('messageinbound_handlers', $record);
 536  
 537          // Generate an address for the handler.
 538          $dataid = 42;
 539  
 540          $generator = new core_message_inbound_test_helper();
 541          $generator->set_handler($handler->classname);
 542          $generator->set_data($dataid);
 543          $address = $generator->generate($user->id);
 544  
 545          // Check that the datakey created matches the expirytime.
 546          $key = $DB->get_record('messageinbound_datakeys', array('handler' => $record->id, 'datavalue' => $dataid));
 547  
 548          $this->assertNull($key->expires);
 549      }
 550  
 551      /**
 552       * Test application of the default expiry on a handler.
 553       */
 554      public function test_default_hander_expiry_low() {
 555          global $DB;
 556  
 557          // Set the default expiry of the handler to 60 seconds.
 558          $expiration = 60;
 559  
 560          // Create test data.
 561          $user = $this->getDataGenerator()->create_user();
 562          $handler = $this->helper_create_handler('handler_one');
 563  
 564          $record = \core\message\inbound\manager::record_from_handler($handler);
 565          $record->defaultexpiration = $expiration;
 566          $DB->update_record('messageinbound_handlers', $record);
 567  
 568          // Generate an address for the handler.
 569          $dataid = 42;
 570  
 571          $generator = new core_message_inbound_test_helper();
 572          $generator->set_handler($handler->classname);
 573          $generator->set_data($dataid);
 574          $address = $generator->generate($user->id);
 575  
 576          // Check that the datakey created matches the expirytime.
 577          $key = $DB->get_record('messageinbound_datakeys', array('handler' => $record->id, 'datavalue' => $dataid));
 578  
 579          $this->assertEquals($key->timecreated + $expiration, $key->expires);
 580      }
 581  
 582      /**
 583       * Test application of the default expiry on a handler.
 584       */
 585      public function test_default_hander_expiry_medium() {
 586          global $DB;
 587  
 588          // Set the default expiry of the handler to 3600 seconds.
 589          $expiration = 3600;
 590  
 591          // Create test data.
 592          $user = $this->getDataGenerator()->create_user();
 593          $handler = $this->helper_create_handler('handler_one');
 594  
 595          $record = \core\message\inbound\manager::record_from_handler($handler);
 596          $record->defaultexpiration = $expiration;
 597          $DB->update_record('messageinbound_handlers', $record);
 598  
 599          // Generate an address for the handler.
 600          $dataid = 42;
 601  
 602          $generator = new core_message_inbound_test_helper();
 603          $generator->set_handler($handler->classname);
 604          $generator->set_data($dataid);
 605          $address = $generator->generate($user->id);
 606  
 607          // Check that the datakey created matches the expirytime.
 608          $key = $DB->get_record('messageinbound_datakeys', array('handler' => $record->id, 'datavalue' => $dataid));
 609  
 610          $this->assertEquals($key->timecreated + $expiration, $key->expires);
 611      }
 612  
 613  }
 614  
 615  /**
 616   * A helper function for unit testing to expose protected functions in the core_message_inbound API for testing.
 617   *
 618   * @copyright  2014 Andrew Nicols <andrew@nicols.co.uk>
 619   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 620   */
 621  class core_message_inbound_test_helper extends \core\message\inbound\address_manager {
 622      /**
 623       * The validate function.
 624       *
 625       * @param string $address
 626       * @return int
 627       */
 628      public function validate($address) {
 629          return parent::validate($address);
 630      }
 631  
 632      /**
 633       * The get_data function.
 634       *
 635       * @return stdClass
 636       */
 637      public function get_data() {
 638          return parent::get_data();
 639      }
 640  
 641      /**
 642       * The address processor function.
 643       *
 644       * @param string $address
 645       * @return void
 646       */
 647      public function process($address) {
 648          return parent::process($address);
 649      }
 650  }
 651  
 652  /**
 653   * A helper function for unit testing to expose protected functions in the core_message_inbound API for testing.
 654   *
 655   * @copyright  2014 Andrew Nicols <andrew@nicols.co.uk>
 656   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 657   */
 658  class core_message_inbound_test_manager extends \core\message\inbound\manager {
 659      /**
 660       * Helper to fetch make the handler_from_record public for unit testing.
 661       *
 662       * @param $record The handler record to fetch
 663       */
 664      public static function handler_from_record($record) {
 665          return parent::handler_from_record($record);
 666      }
 667  }