ez-php/mail 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

ez-php/mail

最新稳定版本:1.11.1

Composer 安装命令:

composer require ez-php/mail

包简介

Transactional mail module for the ez-php framework — SMTP, log, and null drivers

README 文档

README

Transactional mail module for the ez-php framework. Delivers outgoing messages via a pluggable driver — SMTP (native PHP, no library required), Log (dev/CI), or Null (silent discard).

Installation

composer require ez-php/mail

Quick Start

Register the provider in provider/modules.php:

use EzPhp\Mail\MailServiceProvider;

$app->register(MailServiceProvider::class);

Add config values to config/mail.php:

return [
    'driver'       => env('MAIL_DRIVER', 'null'),
    'host'         => env('MAIL_HOST', '127.0.0.1'),
    'port'         => (int) env('MAIL_PORT', 587),
    'username'     => env('MAIL_USERNAME', ''),
    'password'     => env('MAIL_PASSWORD', ''),
    'encryption'   => env('MAIL_ENCRYPTION', 'tls'),
    'from_address' => env('MAIL_FROM_ADDRESS', ''),
    'from_name'    => env('MAIL_FROM_NAME', ''),
    'log_path'     => env('MAIL_LOG_PATH', ''),
];

Send a message:

use EzPhp\Mail\Mail;
use EzPhp\Mail\Mailable;

Mail::send(
    (new Mailable())
        ->to('alice@example.com', 'Alice')
        ->subject('Welcome!')
        ->text('Hello Alice, welcome aboard.')
        ->html('<p>Hello Alice, <strong>welcome aboard.</strong></p>')
);

Drivers

Driver MAIL_DRIVER Description
SMTP smtp Delivers via a real SMTP server (RFC 5321, pure PHP)
Mailgun mailgun Mailgun v3 REST API via cURL; no third-party SDK
SendGrid sendgrid SendGrid v3 Mail Send API via cURL; no third-party SDK
Log log Writes a summary to a log file; safe for dev/CI
Null null Silently discards every message (default)

SMTP

MAIL_DRIVER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=user@example.com
MAIL_PASSWORD=secret
MAIL_ENCRYPTION=tls        # tls | ssl | none
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="My App"

Supports TLS via STARTTLS (port 587), implicit SSL (port 465), and plain-text (port 25). Authentication is AUTH LOGIN; omit MAIL_USERNAME to skip authentication.

Mailgun

MAIL_DRIVER=mailgun
MAIL_MAILGUN_DOMAIN=mg.example.com
MAIL_MAILGUN_API_KEY=key-xxxxxxxxxxxxxxxxxxxx
MAIL_MAILGUN_REGION=us           # us (default) or eu
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="My App"

Delivers via the Mailgun HTTP API v3. US region uses api.mailgun.net; EU region uses api.eu.mailgun.net. Attachments are sent as multipart/form-data.

SendGrid

MAIL_DRIVER=sendgrid
MAIL_SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxx
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="My App"

Delivers via the SendGrid v3 Mail Send API. Attachments are base64-encoded and sent inline in the JSON payload.

Log

MAIL_DRIVER=log
MAIL_LOG_PATH=/var/www/html/storage/logs/mail.log

When MAIL_LOG_PATH is empty, messages are written via error_log().

Mailable

Mailable is a fluent builder that can be used inline or extended per-message type:

// Inline
$mail = (new Mailable())
    ->to('bob@example.com', 'Bob')
    ->from('noreply@example.com', 'My App')   // overrides driver default
    ->subject('Your Invoice')
    ->text('Please find your invoice attached.')
    ->html('<p>Please find your invoice <strong>attached</strong>.</p>')
    ->attach('/path/to/invoice.pdf', 'Invoice-2026-01.pdf');

// Extended
class InvoiceMail extends Mailable
{
    public function __construct(User $user, string $invoicePath)
    {
        $this->to($user->email, $user->name)
             ->subject('Your Invoice')
             ->text('Please find your invoice attached.')
             ->attach($invoicePath);
    }
}

Methods

Method Description
to(string $address, string $name = '') Set recipient
from(string $address, string $name = '') Override sender (uses driver default when not called)
subject(string $subject) Set subject line
text(string $body) Set plain-text body
html(string $body) Set HTML body
attach(string $path, string $name = '') Add file attachment

Combining text() and html() produces a multipart/alternative message. Adding attachments wraps the content in multipart/mixed.

Static Facade

Mail::send(Mailable $mailable) delegates to the driver bound by MailServiceProvider.

In tests, inject a spy driver directly:

use EzPhp\Mail\Mail;
use EzPhp\Mail\Mailable;
use EzPhp\Mail\MailerInterface;

// Arrange
$spy = new class implements MailerInterface {
    public array $sent = [];
    public function send(Mailable $mailable): void { $this->sent[] = $mailable; }
};
Mail::setMailer($spy);

// Act
Mail::send((new Mailable())->to('a@b.com')->subject('Hi')->text('body'));

// Assert
assert(count($spy->sent) === 1);

// Teardown
Mail::resetMailer();

MIME Support

MimeBuilder constructs RFC 2822 / MIME messages internally. It handles:

  • text/plain (quoted-printable)
  • text/html (quoted-printable)
  • multipart/alternative (text + HTML)
  • multipart/mixed (any of the above + attachments)
  • RFC 2047 encoding for non-ASCII subject lines and display names
  • Base64-encoded attachments with MIME type detection via mime_content_type()

Queue Integration

Mail delivery is synchronous by default — Mail::send() blocks until the driver finishes. To dispatch mail asynchronously, wrap the call in a queue job:

use EzPhp\Contracts\JobInterface;
use EzPhp\Mail\Mail;
use EzPhp\Mail\Mailable;

final class SendMailJob implements JobInterface
{
    public function __construct(private readonly Mailable $mailable) {}

    public function handle(): void
    {
        Mail::send($this->mailable);
    }
}

// Dispatch from a controller or service
$queue->push(new SendMailJob(
    (new Mailable())
        ->to($user->email, $user->name)
        ->subject('Welcome!')
        ->text('Hello, welcome aboard.')
));

The Mailable is serialized with the job. Mail::send() inside handle() uses whatever driver is registered in the worker process — typically SmtpDriver in production and NullDriver or LogDriver in development.

Note: Queue-backed delivery is an application-layer concern. The ez-php/mail package has no dependency on ez-php/queue.

Local Development with Mailpit

Mailpit is a local SMTP mail catcher with a web UI. All outgoing mail is captured and displayed without being delivered to real recipients.

1 — Add Mailpit to docker-compose.yml

services:
  mailpit:
    image: axllent/mailpit
    container_name: my-app-mailpit
    ports:
      - "1025:1025"   # SMTP
      - "8025:8025"   # Web UI
    environment:
      MP_SMTP_AUTH_ACCEPT_ANY: 1
      MP_SMTP_AUTH_ALLOW_INSECURE: 1

2 — Configure the SMTP driver to point at Mailpit

MAIL_DRIVER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_ENCRYPTION=none
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_FROM_ADDRESS=dev@example.com
MAIL_FROM_NAME="My App (dev)"

3 — Open the Mailpit web UI

Navigate to http://localhost:8025 in your browser. Every message sent via Mail::send() appears here instantly.

4 — SMTP integration tests

To run the Mailpit smoke tests in ez-php/mail itself:

MAILPIT_HOST=127.0.0.1 MAILPIT_SMTP_PORT=1025 MAILPIT_API_PORT=8025 \
  vendor/bin/phpunit --group mailpit

The three Mailpit tests are skipped automatically when MAILPIT_HOST is not set.

统计信息

  • 总下载量: 110
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-22

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固