hell-sh / mail-transfer
A library allowing you to easily write custom email servers and clients in PHP.
Requires
- php: >=7.1
- ext-openssl: *
- hell-sh/asyncore: ^2.1
- mlocati/spf-lib: ^3.1
Requires (Dev)
- hell-sh/nose: ^1.1
This package is auto-updated.
Last update: 2024-11-07 07:33:10 UTC
README
A library allowing you to easily write custom email servers and clients in PHP.
composer require hell-sh/mail-transfer:dev-senpai
Work In Progress!
The only reason I'm publishing this so early is so that I can build a custom server using "dev-senpai".
Some of the things that have yet to be done
- Multipart Content
- Attachments
- DKIM Subdomain Considerations
- Server: Dynamic & static SIZE
Examples
Server
<?php require "vendor/autoload.php"; (new Email\Server( __DIR__."/fullchain.pem", __DIR__."/privkey.pem", Email\Server::BIND_ADDR_ALL, [25], Email\Session::DEFAULT_READ_TIMEOUT, Email\Connection::LOGFUNC_ECHO ))->onEmailReceived(function(Email\Email $email, Email\Session $sender) { $subject = ($email->getSubject() ?: "(no subject)"); $classification = $email->getFirstHeaderValue("X-Classification"); echo "Received \"$subject\" from {$email->getSender()} ($classification)".PHP_EOL; }) ->loop();
Anti-Spam
While SPF, DKIM and DMARC are all great at preventing spoofing, the real problem is spam, and there is no 100% effective method to address it on the server, but blacklists are by far the most promising.
- If you want to go all-out on not only blocking spam but also teaching ISPs that turn a blind eye a lesson, UCEPROTECT is the way to go:
$server->setBlocklists(["dnsbl-1.uceprotect.net", "dnsbl-2.uceprotect.net", "dnsbl-3.uceprotect.net"]);
- If that's too extreme for you, consider only using their Level 1 or 2 lists.
- If you want to be more pragmatic, JustSpam.org seems good for blocking just spam:
$server->setBlocklists(["dnsbl.justspam.org"]);
Client
<?php require "vendor/autoload.php"; Email\Email::basic( new Email\Address("Sender <sender@localhost>"), new Email\Address("recipient@localhost"), /* Subject: */ "Saying hello to the world", new Email\ContentTextPlain("Hello, world!") )->sign(new Email\DkimKey("php", "file://".__DIR__."/dkim-private.pem")) ->sendToRecipient( Email\Client::DEFAULT_CONNECT_TIMEOUT, Email\Client::DEFAULT_READ_TIMEOUT, Email\Connection::LOGFUNC_ECHO ); Asyncore\Asyncore::loop();
Setup
So you can properly send emails.
First, make sure you're on a public machine with forward-confirmed reverse DNS records for IPv4 & IPv6 (or to put it more generally, any IP that your machine may use for outgoing connections). If this is not the case, there might be all sorts of subtle issues.
Next, use openssl via the terminal to generate an RSA keypair for DKIM:
openssl genrsa -out dkim-private.pem 2048 openssl rsa -in dkim-private.pem -out dkim-public.pem -pubout -outform PEM
Finally, set up the DNS records:
selector
is also the first parameter tonew Email\DkimKey
and basically is the name of the DKIM key.base64-encoded public key
means the actual content of thedkim-public.pem
in a single line and without the BEGIN & END KEY wrapping.policy
is what to do when an email is sent using this domain without being authenticated:reject
: Deny itquarantine
: Put it in spamnone
: Allow it
Some of the RFCs that have been referenced in the development of this software:
- RFC 2045 - MIME Pt. 1
- RFC 2047 - MIME Pt. 3
- RFC 4871 - DKIM
- RFC 5321 - ESMTP
- RFC 5322 - Internet Message Format
- RFC 7489 - DMARC
SPF is implemented by mlocati/spf-lib, published under the MIT license.