noumenia/libmilterphp
最新稳定版本:2.7
Composer 安装命令:
composer require noumenia/libmilterphp
包简介
libMilterPHP is a Postfix/Sendmail Milter library implementation in PHP.
README 文档
README
_ _ _ __ __ _ _ _ ____ _ _ ____
| (_) |__ | \/ (_) | |_ ___ _ __| _ \| | | | _ \
| | | '_ \| |\/| | | | __/ _ \ '__| |_) | |_| | |_) |
| | | |_) | | | | | | || __/ | | __/| _ | __/
|_|_|_.__/|_| |_|_|_|_| \___|_| |_| |_| |_|_|
libMilterPHP is a Postfix/Sendmail Milter library implementation in PHP.
Features
- High-performance multi-process
- Low memory footprint
- Strict coding standards
- Support for all milter protocol version 2 commands
- Listen on IP address/port or UNIX sockets
- Support for signals
- Proper memory-resident daemon
Requirements
- PHP 8.0, 8.1, 8.2, 8.3, 8.4, 8.5
- libSDManagerPHP
Install with RPM packages
You may install libMilterPHP via the copr repository, for Alma/Rocky/Oracle Enterprise Linux and Fedora, simply use:
dnf copr enable mksanthi/noumenia
dnf install libMilterPHP
Install with Composer
You may install libMilterPHP with composer, to get the latest version use:
composer require noumenia/libmilterphp
Install manually
Download the repository and copy the libMilterPHP project directory in the appropriate place within your project or within an accessibe location, for example under /usr/share/php.
How to use
Loading libraries (RPM package)
Load and initialize the library by loading the common.inc.php file, for each required library:
require_once("/usr/share/php/libLoggerPHP/controller/common.inc.php");
require_once("/usr/share/php/libSDManagerPHP/controller/common.inc.php");
require_once("/usr/share/php/libMilterPHP/controller/common.inc.php");
Loading libraries (composer)
require_once("./vendor/autoload.php");
PHP class
Create your custom class and extend the milter library \libMilterPHP\Milter:
class MilterTestDaemon extends \libMilterPHP\Milter { ... }
Implement your callback functions
Implement all or some of the available callback functions, within your custom class, these functions are:
public function smficAbort(array $message): void // Required
public function smficBody(array $message): void
public function smficConnect(array $message): void
public function smficMacro(array $message): void // Required
public function smficBodyeob(array $message): void // Required
public function smficHelo(array $message): void
public function smficHeader(array $message): void
public function smficMail(array $message): void
public function smficEoh(array $message): void
public function smficRcpt(array $message): void
public function smficQuit(array $message): void // Required
Instantiate your custom class
Instantiate your custom class and pass the configuration parameters to the constructor. These parameters are:
// Create milter object
$milter = new MilterTestDaemon(
"postfix", // Daemon user owner
"mail", // Daemon group owner
"/run/daemon.pid", // PID file
1024, // Process limit
"unix:///run/daemon.sock", // Connection string ("unix:///path/to/file.sock" or "inet:port@IP")
10, // Socket/Stream timeout in seconds
array(SMFIF_QUARANTINE), // Supported actions (array of SMFIF_* constants)
array(SMFIP_NOBODY) // Ignored content (array of SMFIP_* constants)
);
Accept connections
Finally, call the acceptConnections() method, to start the daemon in the foreground:
// Accept connections
$milter->acceptConnections();
Sample milter
The following is a sample milter daemon that checks the FROM and matches it with a known spammer address.
#!/usr/bin/env php
<?php
/**
* Milter test daemon
*
* @copyright Noumenia (C) 2019 - All rights reserved - Software Development - www.noumenia.gr
* @license GNU GPL v3.0
* @package libMilterPHP
* @subpackage miltertestdaemon
*/
if(is_file(__DIR__ . "/vendor/autoload.php")) {
// Autoload via composer
require_once(__DIR__ . "/vendor/autoload.php");
} else {
// Autoload via RPM packages
require_once("/usr/share/php/libLoggerPHP/controller/common.inc.php");
require_once("/usr/share/php/libSDManagerPHP/controller/common.inc.php");
require_once("/usr/share/php/libMilterPHP/controller/common.inc.php");
}
class MilterTestDaemon extends \libMilterPHP\Milter {
/**
* SMFIC_ABORT - Abort current filter checks
* @param array{size: int, command: string, binary: string} $message Message array
* @return void
*/
public function smficAbort(array $message): void
{
// No-op
}
/**
* SMFIC_MAIL - MAIL FROM: information - use SMFIP_NOMAIL to suppress
* @param array{size: int, command: string, binary: string, args: array<string>} $message Message array
* @return void
*/
public function smficMail(array $message): void
{
// Mark this email for quarantine
if(preg_match('/spameri@tiscali\.it/i', strval($message['args'][0])) === 1)
$reply = array('command' => SMFIR_QUARANTINE, 'data' => array('reason' => "Spammer in quarantine!"));
else
$reply = array('command' => SMFIR_CONTINUE, 'data' => array());
$this->reply($reply);
// Since SMFIR_QUARANTINE is a "Modification" action, the MTA is waiting for further commands...
// So continue processing
// Use the helper function
$this->replyContinue();
// Or use the reply function directly
//$reply = array('command' => SMFIR_CONTINUE, 'data' => array());
//$this->reply($reply);
}
/**
* SMFIC_BODYEOB - End of body marker
* @param array{size: int, command: string, binary: string} $message Message array
* @return void
*/
public function smficBodyeob(array $message): void
{
// Use the helper function
$this->replyContinue();
// Or use the reply function directly
//$reply = array('command' => SMFIR_CONTINUE, 'data' => array());
//$this->reply($reply);
// Here is an example for a rejection
//$this->replyReject("Blocked by MilterTestDaemon");
}
}
// Create milter object
$milter = new MilterTestDaemon(
"miltertestuser", // Daemon user owner
"mail", // Daemon group owner
"/run/daemon.pid", // PID file
1024, // Process limit
"unix:///run/daemon.sock", // Connection string ("unix:///path/to/file.sock" or "inet:port@IP")
10, // Socket/Stream timeout in seconds
array(SMFIF_QUARANTINE), // Supported actions (array of SMFIF_* constants)
array( // Ignored content (array of SMFIP_* constants)
SMFIP_NOCONNECT,
SMFIP_NOHELO,
SMFIP_NORCPT,
SMFIP_NOBODY,
SMFIP_NOHDRS,
SMFIP_NOEOH
)
);
// Accept connections
$milter->acceptConnections();
Notes about SMFIF_* actions
The supported actions array uses SMFIF_* constants, to define which actions MAY be taken by the milter. This is an essential part of the milter/MTA conversation, to define what actions the MTA will expect from the milter. All constants are defined within the libMilterPHP/controller/constants.inc.php file.
Notes about SMFIP_* ignored content
The ignored content array uses SMFIP_* constants, to inform the MTA which parts of the SMTP conversation should NOT be sent to the milter. This feature saves a lot of bandwidth and CPU usage by both the MTA and the milter. All constants are defined within the libMilterPHP/controller/constants.inc.php file.
Notes about SMFIR_* response codes
These constants define various responses that the milter can give to the MTA. The ones marked as "Modification" only make changes to the email data, after a modification the MTA expects the milter to provide another response. The ones marked as "Accept/reject" give a final indication about the email and allow the milter and MTA to end their conversation.
| Constant | Value | Modification | Accept/reject | Asynchronous |
|---|---|---|---|---|
| SMFIR_ADDRCPT | + | [X] | [ ] | [ ] |
| SMFIR_DELRCPT | - | [X] | [ ] | [ ] |
| SMFIR_ACCEPT | a | [ ] | [X] | [ ] |
| SMFIR_REPLBODY | b | [X] | [ ] | [ ] |
| SMFIR_CONTINUE | c | [ ] | [X] | [ ] |
| SMFIR_DISCARD | d | [ ] | [X] | [ ] |
| SMFIR_ADDHEADER | h | [X] | [ ] | [ ] |
| SMFIR_CHGHEADER | m | [X] | [ ] | [ ] |
| SMFIR_PROGRESS | p | [ ] | [ ] | [X] |
| SMFIR_QUARANTINE | q | [X] | [ ] | [ ] |
| SMFIR_REJECT | r | [ ] | [X] | [ ] |
| SMFIR_TEMPFAIL | t | [ ] | [X] | [ ] |
| SMFIR_REPLYCODE | y | [ ] | [X] | [ ] |
Notes about the milter communication protocol
The milter communication protocol runs over UNIX sockets or over an IP/port connection. It uses the following binary format:
size = uint32 (the size of the command+data)
command = char (a one character command)
data = data[size-1] (the data)
For example, the MTA could send a message that in hex looks like:
+----------+---------+--------------------------------+
| size | command | data... |
+----------+---------+----------+----------+----------+
| 0000000d | 4f | 00000006 | 000001ff | 001fffff |
+----------+---------+----------+----------+----------+
The libMilterPHP library will first read the first 4 bytes of the message and interpret it as a uint32 number, which indicates the size of the message that is expected. The library will then keep reading for the whole message and once done, it will separate the command from the data. The command will be used to call the equivalent callback function with the data as a parameter.
Design diagram
The following diagram shows a simplified view of the libMilterPHP implementation.
+----------------+ +-------------------+
| | | |
| common.inc.php | +---+-> | constants.inc.php |
| | | | |
+----------------+ | +-------------------+
|
Constants | Set system constants
Autoloader | Set milter protocol constants
Initialize logging |
|
| +----------------------------------------+
| | |
+-> | NoumeniaLibMilterPHPAutoloader.inc.php |
| | |
| +----------------------------------------+
|
| Define the autoloader function
|
| +-----------------+ use
| | | <-----> libLoggerPHP\Log
+-> | loginit.inc.php | <-----> libLoggerPHP\LogDestinationNull
| | <-----> libLoggerPHP\LogDestinationSyslog
+-----------------+
Set log destination
Set message priority
+----------------+ extends
| | <-----> libSDManager\SocketManager
| Milter.inc.php |
| | use
+----------------+ +-----> +---------------------+
| |
__construct() | ReplyHelper.inc.php |
reply() | |
processChild() +---------------------+
replyAddRecipient()
replyDeleteRecipient()
replyAccept()
replyReplaceBodyChunk()
replyContinue()
replyDiscard()
replyAddHeader()
replyChangeHeader()
replyDeleteHeader()
replyProgress()
replyQuarantine()
replyReject()
replyTempFail()
replyReplyCode()
Related projects
- Aetolos - Virtual hosting at your... command line!
- guardian-milter - Multi-purpose security milter.
- bravos - Log file security parser.
- mmDbDaemon is a memory-resident MaxMind Database reader implementation in PHP.
- libMilterPHP is a Postfix/Sendmail Milter library implementation in PHP.
- libSDManagerPHP provides a portable daemon with a Sockets and Streams manager.
- libLoggerPHP is a logging library implementation in PHP.
统计信息
- 总下载量: 68
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 1
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: GPL-3.0-only
- 更新时间: 2022-12-08