net-tools/mailing

Composer 库,用于使用 PHP 处理电子邮件


README

Composer 库,用于使用 PHP 发送电子邮件

此包包含所有必需的类,以便以面向对象的方式轻松使用 PHP 构建电子邮件。

支持附件和嵌入。

安装说明

要安装 net-tools/mailing 包,只需通过 composer 需要: require net-tools/mailing:^1.0.0

如何使用?

快速发送电子邮件

要轻松发送电子邮件,只需获取具有默认发送策略的 Mailer 实例,并调用 expressSendmail 方法。如果没有附件要发送,则省略最后一个参数。

Mailer::getDefault()->expressSendmail(
  '<b>This is a</b> test', 
  'from-user@test.com', 
  'recipient@test.com', 
  'This is a subject', 
  array('/home/tmp/invoice.pdf')
);

电子邮件技术部分(text/plain、text/html、multipart/alternative、multipart/mixed)将自动创建;默认发送策略通过 PHP 内置 Mail() 函数发送电子邮件。

构建电子邮件

如果您在发送电子邮件时需要更多控制,则可以使用 Mailer 构建它们。

$mail = Mailer::addTextHtmlFromText('\*\*This is a\*\* test');
$mail = Mailer::addAttachment($mail, '/home/tmp/invoice.pdf', 'your_invoice.pdf', 'application/pdf');
Mailer::getDefault()->sendmail($mail, 'from-user@test.com', 'recipient@test.com', 'This is a subject');

要使用 SMTP 协议(或 MailSenders 子文件夹中的任何其他电子邮件发送策略)发送电子邮件,请使用适当的 MailSender 对象创建 Mailer(而不是通过 getDefault 获取)。

$smtpmailer = new Mailer(new MailSenders\SMTP(array('host'=>'mysmtphost.com', 'username'=>'user', 'password'=>'1234')));
$smtpmailer->sendmail($mail, 'from-user@test.com', 'recipient@test.com', 'This is a subject');

解析 EML 文件/字符串以创建 MailContent 对象

有时您有一封电子邮件并想将其显示在屏幕上。然而,您不能直接输出原始内容。您必须解析电子邮件内容以提取适当的部分(通常是 text/html 部分)以及必要的附件(multipart/mixed 部分)。

要解析电子邮件,请使用 EmlReader 类和 fromStringfromFile 静态方法。它们将返回一个 MailContent 对象

// assuming that $email is a very simple email with a multipart/alternative content
$mail = EmlReader::parseString($email);

// this line prints MailMultipart (class name of the MailContent object)
echo get_class($mail);

// the following lines extract the text/plain and text/html sub-parts
$textplain_content = $mail->getPart(0)->toString();
$htmlpart_content = $mail->getPart(1)->toString();

如果您的电子邮件包含附件或嵌入,不要忘记调用 destroy 静态方法来删除在解析过程中创建的临时文件以存储附件和嵌入

EmlReader::destroy($mail);

使用队列发送

有时我们不想一次性发送大量电子邮件,我们可能希望将它们排队到某个地方,然后稍后发送,可能通过批量方式。这是 MailSenderQueue 子文件夹的目的。它包含一个 StoreQueue 类;第一个是队列子系统的外观,第二个代表特定的队列。

要排队项目

// create a Store object to manage queues
$store = new MailSenderQueue\Store('~/home/path_to_queue_subsystem_root');

// create a new queue, which sends emails through batches of 75 items
$queue = $store->createQueue('title_of_queue', 75);
$id = $queue->id;

// create an email content with text/plain and text/html parts
$mail = Mailer::addTextHtmlFromText('\*\*This is a\*\* test');

// then send email (of course this last line is usually called within a loop, to queue all items at once
$queue->push($mail, 'sender@domain.tld', 'recipient_here@domain.tld', 'Email subject here');

然后在稍后,可能在另一个脚本/调用中

// reopen the same store
$store = new MailSenderQueue\Store('~/home/path_to_queue_subsystem_root');

// getting queue with `$id` (saved from above call)
$queue = $store->getQueue($id);

// send a batch
$queue->send(Mailer::getDefault());

请参阅 API 参考以获取有关 Store 和 Queue 对象的完整详细信息(删除队列、处理错误、列出队列和收件人)。

管理邮件发送策略

当 Mailer 对象构建时,接受一个 MailSenders\MailSenderIntf 对象,该对象是通过它发送电子邮件的策略。它可以 MailSenders\PHPMail(使用内置的 mail() 函数)或 MailSenders\SMTP。每个策略可能有一些参数(对于 SMTP,这些是主机/用户/密码数据)。

有时,有多个 SMTP 策略(通过多个主机发送电子邮件)。为了处理所有这些发送策略,我们创建了一个 MailSendersFacade

  • 数据(策略参数)存储在一个 JSON 字符串中
  • 策略列表以字符串形式存储在 PHP 数组中

JSON 和字符串使得更新参数变得更容易,并且可以存储在文件、数据库或硬编码中;其次,创建邮件发送策略简化了,因为所有参数都已预先定义在 JSON 数据中;我们只需调用一个方法来获取当前策略,并使用适当的参数进行初始化。

创建外观对象(这是我们用来列出策略或获取一个准备好与 Mailer 类一起使用的对象)

// list of strategies with an optionnal paramaters set name
$msenders = ['SMTP:params1', 'PHPMail'];

// setting data for all strategies (json-formatted string)
$msdata = '{"SMTP:params1":{"className":"SMTP","host":"value1","username":"value2","password":"value3"}, "PHPMail":{}}';

// active strategy
$ms = 'SMTP:params1';

// create the facade object, through a list of sending strategies proxies (we don't create real `MailSenders\MailSenderIntf` objects), described with json structure
$f = MailSendersFacade\Facade::facadeProxiesFromJson($msenders, $msdata, $ms);

// ... do some stuff such as listing mail senders 

// now, get the active mail sender and create the concrete `MailSenders\MailSenderIntf` object, passing it to Mailer constructor
$m = new Mailer($f->getActiveMailSender());

MailSendersFacade 类的典型用法是

  • 向最终用户列出邮件发送策略:在 Facade 对象上调用 getProxies() 方法
  • 获取当前的邮件发送策略代理:在 Facade 对象上调用 getActiveProxy() 方法
  • 获取一个基于当前策略代理的真实 MailSender 对象,并使用所需的参数进行初始化:在 Facade 对象上调用 getActiveMailSender() 方法(Json数据中定义的参数将自动应用)

关于代理的一些说明。在这个外观设计模式中,我们列出邮件发送策略(用例:展示一个策略列表,并允许最终用户选择一个);然而,创建 MailSender 类(如 MailSenders\SMTP)的真实实例在这里并不真正有用,因为我们只想要一个策略及其参数的列表,不多也不少。因此,我们使用代理,即在外观设计模式中表示实际发送策略的对象;这些代理是轻量级的,所以这非常适合这种用例。我们还拥有一种特殊的代理,Proxies\Quota 类,它使得能够记录使用策略发送的每一封邮件并计算配额(配额的实现需要编码,但我们提供了一个 PdoQuotaInterface,这可以作为记录到数据库的起点)。当我们确实需要真实的邮件发送策略时,我们可以在代理对象上调用 getMailSender(),它将根据提供的Json数据中的参数创建真实对象,然后我们得到一个可以与 Mailer 构造函数一起使用的对象。

通过 MailSenderHelpers\MailSenderHelper 发送

有时,创建电子邮件内容、添加BCC、主题、replyTo头或处理队列可能会很困难。MailSenderHelpers 子系统就是为了抽象化所有这些。

$mailer = Mailer::getDefault();

// first, we create a helper object, with minimum parameters (mailer object, body content, sender, recipient subject, optional parameters)
$msh = new MailSenderHelpers\MailSenderHelper($mailer, 'raw mail as text', 'text/plain', 'from@me.com', 'subject of email', $params);
// OR : $msh = new MailSenderHelpers\MailSenderHelper($mailer, 'mail as <b>html</b>', 'text/html', 'from@me.com', 'subject of email', $params);

// prepare the mail : checking required parameters set, building text/html and text/plain parts (from respectively text/plain or text/html body content) 
$mailContent = $msh->render(null);

// send the email rendered
$msh->send($mailContent, 'recipient@here.com');

当然,有趣的是可选的最后参数 $params,因为它可能包含

  • 一个 template 参数(构造函数体的内容插入到模板中,替换任何 %content% 字符串
  • 一个 bcc 参数,以将电子邮件发送给收件人及其 BCC(作为字符串提供)
  • 一个 testMode 参数;如果设置为 True,则在 send 调用期间不会将电子邮件发送到真实收件人,而是发送到测试收件人(见下文)
  • 一个 testRecipients 参数;如果 testMode 等于 True,则是一个测试电子邮件的 PHP 数组,用于发送电子邮件
  • 一个 replyTo 参数;如果设置为电子邮件字符串,它将在电子邮件中插入一个特定的头,以便回答应返回到另一个地址
  • 一个 toOverride 参数;如果设置,所有电子邮件都将发送到该地址(用于调试目的?)
  • 一个 queue 参数;如果设置,将创建一个名为提供的队列,并将 send 调用中的电子邮件推送到队列
  • 一个 queueParams 参数;如果使用队列,这是 Store 对象构造函数参数的关联数组(队列子系统的根和批处理计数)

最有趣的是队列参数,因为它使得可以使用相同的接口(MailSenderHelper 类)直接发送电子邮件或通过队列发送电子邮件。

PHPUnit

要使用 PHPUnit 进行测试,请将 -c 配置选项指向 /phpunit.xml 配置文件。