taitava / silverstripe-emailqueue
一个模块,允许您在后台进程中发送电子邮件,检查已发送的电子邮件,并监控和取消队列和计划中的电子邮件。还包含一个电子邮件模板结构,使您的电子邮件相关代码更容易通过自定义类和.ss模板文件进行管理。
Requires
- silverstripe/cms: ~3.1
- silverstripe/framework: ~3.1
Suggests
- silverstripe/crontask: Process the email queue automatically.
- silverstripe/dashboard: Monitor the email queue in the backend.
This package is auto-updated.
Last update: 2024-09-12 10:04:57 UTC
README
这是一个模块,允许您在后台进程中发送电子邮件,检查已发送的电子邮件,并监控和取消队列和计划中的电子邮件。还包含一个电子邮件模板结构,使您的电子邮件相关代码更容易通过自定义类和.ss模板文件进行管理。请注意,此模块将电子邮件消息存储在数据库中。
维护者联系方式
Jarkko Linnanvirta posti (at) taitavasti (dot) fi (英语或芬兰语) www.taitavasti.fi (仅芬兰语)
需求
- SilverStripe 3.1.0 或更高版本
- 可选:silverstripe/crontask 非常推荐,但不是必需的。如果已安装,则电子邮件队列将自动处理(即发送电子邮件)。如果没有安装,您需要自行从命令行运行
EmailQueueProcessor
任务,或定义一个cron作业来执行此操作。 - 可选:unclecheese/silverstripe-dashboard 建议您可以在管理面板中查看已发送的内容和当前排队等待发送的内容。
安装
composer require taitava/silverstripe-emailqueue
文档
请注意以下重要事项:此模块不会更改默认SilverStripe电子邮件消息的发送方式(例如,“忘记密码”电子邮件消息)。此模块也不会影响通过UserForms模块发送的电子邮件消息。也许在未来,谁知道呢。想法是您可以为此模块的自定义电子邮件消息使用此模块。
因此,如果您使用以下常规方法发送电子邮件消息
$email = new Email; $email->setTo('the.recipient@domain.tld'); $email->setFrom('the.sender@domain.tld'); $email->setSubject('My subject'); $email->setBody($this->renderWith('MyEmailMessageTemplate.ss')); $email->send();
每次使用此方法发送电子邮件消息时,它都将使用SilverStripe的常规电子邮件发送过程。因此,安装此模块时不会发生变化。
当您想使用此模块进行电子邮件发送和队列时,您需要修改您的代码,如下所示。让我们首先为我们的电子邮件消息定义一个新的类
class MyEmailMessage extends EmailTemplate { protected $is_internal_message = false; // Set this to true if you want to automatically set the 'To' address to a preconfigured admin receiver address. protected function init() { $this->setSubject('My subject'); } }
然后是一个模板文件 MyEmailMessage.ss
<h1>$Subject</h1>
Hi $YourName, this is just me sending a message to you.
然后让我们实例化消息
$email = new MyEmailMessage; $recipient_member = Member::currentUser(); $email->setRenderingVariables([ 'YourName' => $recipient_member->getName(), ]); $email->setTo($recipient_member); // Note that now we can use a Member object as the recipient. See below for more info. Normal email addresses are accepted too! $email->send();
您可以在YAML配置中配置默认的发送者
Email: admin_email: 'the.sender@domain.tld' # This is SilverStripe's default 'From' address, and QueuedEmails uses the same setting too QueuedEmail: admin_to_address: 'the.recipient@domain.tld' # This is used as a 'To' address if an EmailTemplate subclass has defined $is_internal_message as true.
如您所见,我们已将 Member
对象传递给 setTo()
方法,而不是常规的电子邮件地址。使用此模块,您始终可以使用以下任一项作为电子邮件地址
- 一个常规字符串,如 'me@somewhere.tld'。
- Member类的对象(电子邮件地址将从“Email”字段中获取,不能配置其他字段)。
- 实现
EmailAddressProvider
接口的任何类的对象。在这种情况下,该类应包含一个名为getEmailAddresses()
的方法,该方法返回一个电子邮件地址数组(因此,如果您愿意,可以发送给多个收件人)。
正如你可能已经猜到的,EmailTemplate
类扩展了 SilverStripe 的 Email
类,因此在 EmailTemplate
类中也有相同的方法。当排队中的消息被发送时,Email
类也用于处理实际发送部分,所以我们并不是在重新发明轮子。
要从队列中退出?
调用 $email->send()
并不会实际发送消息。它只会排队。如果你想例外地立即发送消息,可以调用 $email->send($message_id=null, $queue=false)
,它会完全跳过排队并立即发送。请注意,在这种情况下,邮件消息甚至不会被存储到数据库中,因此你无法监控已发送的消息。
那么我的排队邮件何时会被发送?
谁知道它们是否会被发送。
开玩笑的。如果你已经在使用 CronTask 模块,那么实际上你不需要做什么来发送你的消息。如果没有,需要一点准备。安装该模块,然后在你的服务器环境中定义一个 cron 作业,如下所示,在命令行中
主机名:~$ nano /etc/cron.d/silverstripe
* * * * * www-data php /var/www/my-silverstripe-project/framework/cli-script.php dev/cron
然后你就可以开始了。如果你需要更多关于设置 cron 任务的详细信息,请参阅上面的链接。
实际上回答这个问题,你可以配置队列处理(即发送邮件)的间隔
EmailQueueProcessorCronTask: frequency: 10 # In minutes. This is the default value EmailQueueProcessor: max_email_messages: 50 # How many messages to send at once.
在哪里可以看到排队和已发送的邮件?
目前唯一的选择是使用 Dashboard 模块。只需安装它,然后在你的网页浏览器中创建一个 DashboardEmailQueue
类的新仪表板面板。这不是最好的解决方案,但至少它提供了快速查看邮件发送是否正常工作或队列是否堆积的方法。(如果堆积了,请,请不要尝试创建一个自动化的邮件消息来提醒你发送邮件没有工作! :D )。
安排稍后发送的邮件(以及取消发送)
如果你希望,可以安排特定的邮件消息在稍后时间发送。在你的 EmailTemplate
子类中这样做
class MyEmailMessage extends EmailTemplate { /* * @return DateTime|null */ protected function getSendingSchedule() { $datetime = new DateTime; $datetime->modify('+3 hours'); // Send after three hours return $datetime; // Or send immediately: // return null; } }
请注意,发送时间不是按分钟精确的。这是因为邮件队列每十分钟(默认)处理一次,可能有很多消息需要处理,所以你不能确定你的消息是在 12:00、12:01 还是 12:02 等等。你定义的时间表示消息可以发送的最早时间。理论上,你的消息可能比预定时间晚一年才发送。
你甚至可以 取消发送预定的邮件。例如,如果你发送的是关于新发布的博客文章的通知邮件,但你最终因为某种原因取消了发布,你可以在你的代码中调用 EmailQueue::ScheduledEmails()
来获取一个等待发送时间的 DataList
的邮件,然后删除这些记录,这样它们就永远不会发送。
我已经发送过类似的消息吗?
在发送自动化消息时,可能会出现这样的情况:你反复给同一个收件人发送相同的消息。在简单的案例中,例如 "用户在表单中点击按钮 -> 将表单发送到电子邮件地址",这不是问题。但如果有问题,例如,邮件消息是由每天运行的 cron 任务创建的:"获取12个月未访问此应用的成员列表,并发送我们想念他们的电子邮件。"
如果您仅选择一年前(或更长时间)最后登录日期的成员列表,您将每天向他们发送一条新消息。一个解决方案可能是只包括恰好365天前(在24小时内)登录的成员,但如果有例如服务器因维护一天而停机,并且那天没有运行cron任务,这可能会引发其他问题。或者您不确定您今天是否已经运行过它,并且只想以防万一重新运行。这就是您想知道是否已经发送过类似消息的时候。
您可以通过以下方式轻松完成
// Some data that will be used in the email message body $some_data_object_id = 123; $some_other_variable = 'ABC'; // Create a unique "key" that can be used to identify our message $recipient_member = Member::currentUser(); $unique_string = $recipient_member->ID.'-'.$some_data_object_id.'-'.$some_other_variable; // Have we already sent a message with the same key? if (EmailQueue::CheckUniqueString(MyEmailMessage::class, $unique_string)) { // Already sent!!! } else { // Not sent yet, so let's send it! $email = new MyEmailMessage; $email->setTo($recipient_member); $email->setRenderingVariables([ 'some_data_object_id' => $some_data_object_id, 'some_other_variable' => $some_other_variable, ]); /** @var EmailQueue $email_queue_record */ $email_queue_record = $email->send(); // Remember to write the key to the database! $email_queue_record->UniqueString = $unique_string; $email_queue_record->write(); }
关于开发和测试环境的一些说明
此模块具有保护机制,以防止在开发和测试阶段意外向 unintended addresses 发送电子邮件消息(例如,向客户端电子邮件地址,这些地址可能已在您的应用程序数据库中定义)。
您需要访问您网站的应用程序的“SiteConfig”部分(在管理员面板中为“设置”),然后转到“EmailQueue”选项卡。在那里您可以看到一个字段,可以定义允许的收件人列表。此列表仅在开发和测试环境中使用。
这不是最佳解决方案,因为有人可能希望使用YAML配置而不是在SiteConfig中定义此列表,但现在就是这样,以后可以改进。
待办事项
- 将代码升级以支持SilverStripe 4。
- 创建用户界面以管理/删除存储在数据库中的所有电子邮件消息。目前只能查看(如果您已安装仪表板模块)。
- 也许可以添加对SilverStripe Queued Jobs模块的支持?这可以替代当前支持的CronTask模块。
- 支持YAML的开发/测试电子邮件白名单(参见上述部分)。同时,使此功能可关闭。