2amigos/mail-service

Slim 3 邮件API微服务

dev-master 2019-03-22 07:48 UTC

This package is auto-updated.

Last update: 2024-09-22 19:42:02 UTC


README

Mail API Service

邮件服务是一个使用mustache模板发送邮件的邮件微服务。它被构建来允许我们的开发团队在涉及微服务基础设施的项目中避免反复配置邮件。它是由两个独立的应用程序组合而成的,一个是由Symfony的CI应用程序,另一个是使用Slim3构建的API,因为它使用了队列技术。

项目使用Monolog进行日志记录,Fractal作为序列化器,Tactitian作为命令总线,gettext进行翻译,基本访问认证Json Web Tokens进行认证(这是可选的),以及Zend filter进行数据过滤和验证。

包含Docker composePostman collection文件,便于开发,尽管开发过程中不一定严格需要docker,因为可以使用PHP内置服务器。

项目试图遵循DDD原则。

安装

使用composer安装最新版本。

$ composer create-project --no-interaction --stability=dev 2amigos/mail-service app

如果您是从私有仓库使用(以下以github url为例)。

$ composer create-project --no-interaction --stability=dev 2amigos/mail-service app --repository-url=https://github.com/2amigos/mail-service

配置

该项目使用环境文件来配置秘密,因此您必须在项目的根目录下创建一个名为.env的文件。已经提供了一个包含所有必需环境值的.env.example文件。修改该文件并将其保存为根目录下的.env

默认情况下,API应用程序配置为在基本认证过程中工作。它使用用户数组来此目的,但您可以轻松更改此行为,通过创建自己的或使用库中提供的HttpBasicAuthentication中间件来配置authenticator选项。查看PdoAuthenticator

如果认证成功,操作将返回一个用于后续调用的Json Web Token。

认证或作用域的使用是可选的。如果您不希望使用此类设置,只需删除HttpBasicAuthenticationJwtAuthenticationScopeMiddleware中间件的中间件配置。

应用程序最重要的部分是其views,它们需要位于views/txtviews/html子目录中。它们的名字已经说明了每个目录应该包含什么类型的模板。

它还通过使用 gettext 支持多语言。已提供示例翻译文件和模板,以帮助您了解其工作原理。我们还添加了一个命令,用于与优秀的本地化管理平台 POEditor 一起使用。该命令将为您导入翻译并转换文件为 .php 文件。要从 POEditor 导入所需翻译到您的项目中,请使用以下命令

$ ./bin/console import-translations:run --api-token={POEDITOR_TOKEN} --project={PROJECT_ID} --languages=es,de --delay=3

其中 {POEDITOR_TOKEN} 和 {PROJECT_ID} 分别是您的令牌和项目 ID。

翻译将自动导入到 ./i18n/ 文件夹。

为了与翻译一起工作,我们还包含了一个帮助类,用于处理 Mustache,该类将解析内容并尝试获取 {{#i18n}}{{/i18n}} 标签内的翻译文本。请参阅本项目提供的示例视图。

用法

为了示例起见,请转到应用的 public 文件夹,并像这样启动内置的 PHP 服务器

php -S localhost:8080

现在我们可以访问 http://127.0.0.1:8080 上的 api。

获取令牌

要获取令牌,请使用以下

$ curl "https://127.0.0.1:8080/token" \
    --request POST \
    --include \
    --insecure \
    --header "Content-Type: application/json" \
    --data '["mail.all"]' \
    --user test:test

HTTP/1.1 201 Created
Content-Type: application/json

{
    "data": {
        "token": "XXXXXXXXXX",
        "expires": 1550271641
    }
}

发送电子邮件(到队列中)

使用 token,您现在可以使用 application/form-data 提交请求来发送电子邮件。

curl -X POST \
  http://127.0.0.1:8080/mail/send \
  -H 'Authorization: Bearer YOUR_TOKEN_HERE' \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Postman-Token: 22bf2715-35e4-41ee-a04b-fd8beddcdd62' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F from=noreply@example.com \
  -F to=user@example.com \
  -F 'subject=Testing micro-services' \
  -F template=hello-world \
  -F 'data[name]=World' \
  -F language=es \
  -F 'attachments[]=@/path/to/image/to/attach/41835188_10217308479844850_6484466208170049536_o.jpg'
  

上述命令将在默认配置在 runtime 文件夹的队列目录中创建一个电子邮件消息。

参数

  • from: 可选。消息来自谁。如果没有指定,邮件消息将使用名为 MAIL_NO_REPLY_EMAIL 的环境变量进行配置(请参阅 .env.example 文件)。
  • to: 必需。消息的收件人。
  • subject: 必需。这是发送者将电子邮件内容主题设置为的内容。
  • template: 必需。模板的名称。例如,如果我们使用 registration 设置此参数,则系统将验证是否可以在 views/txtviews/html 文件夹中找到名为 registration.mustache 的 mustache 模板。
  • language: 可选。如果名称已翻译,请将此参数设置为要翻译的消息的语言代码。例如,如果您将其设置为 es,则将尝试从 i18n/es/messages.php 文件加载翻译。有关加载翻译的更多信息,请参阅 src\Infrastructure\Mustache\Helpers\TranslatorHelper

从队列中发送电子邮件

我们使用 Symfony 的 SwiftMailer 扩展包 来简化从队列发送电子邮件的任务,因为它附带了一些有用的命令。从项目根目录在终端中键入 $ ./bin/console,将显示以下命令

Available commands:
  about                      Displays information about the current project
  help                       Displays help for a command
  list                       Lists commands
 assets
  assets:install             Installs bundles web assets under a public directory
 cache
  cache:clear                Clears the cache
  cache:pool:clear           Clears cache pools
  cache:pool:delete          Deletes an item from a cache pool
  cache:pool:prune           Prunes cache pools
  cache:warmup               Warms up an empty cache
 config
  config:dump-reference      Dumps the default configuration for an extension
 debug
  debug:autowiring           Lists classes/interfaces you can use for autowiring
  debug:config               Dumps the current configuration for an extension
  debug:container            Displays current services for an application
  debug:event-dispatcher     Displays configured listeners for an application
  debug:router               Displays current routes for an application
  debug:swiftmailer          Displays current mailers for an application
 enqueue
  enqueue:consume            [enq:c] A client's worker that processes messages. By default it connects to default queue. It select an appropriate message processor based on a message headers
  enqueue:produce            Sends an event to the topic
  enqueue:routes             [debug:enqueue:routes] A command lists all registered routes.
  enqueue:setup-broker       [enq:sb] Setup broker. Configure the broker, creates queues, topics and so on.
  enqueue:transport:consume  A worker that consumes message from a broker. To use this broker you have to explicitly set a queue to consume from and a message processor service
 import-translations
  import-translations:run    Import POEditor translations command
 lint
  lint:yaml                  Lints a file and outputs encountered errors
 router
  router:match               Helps debug routes by simulating a path info match
 swiftmailer
  swiftmailer:email:send     Send simple email message
  swiftmailer:spool:send     Sends emails from the spool

要从队列中发送电子邮件,只需在服务器上配置一个 cron 作业,定期运行以下命令

$ ./bin/console swiftmailer:spool:send --message-limit=10

现在,我们必须说,虽然 spooling 是 SwiftMailer 的一个很好的功能,但这种技术不适合需要发送大量电子邮件的应用程序。在这种情况下,我们强烈建议使用如 php-enqueue 这样的优秀队列库,并使用最适合您知识和需求的中介。我们推荐 RabbitMQ,因为它附带了一个管理界面,您可以在其中查看诸如发送了多少封电子邮件、有多少封失败了等等的信息,以及轻松添加/删除所需的工作者以应对可能的巨大负载。它也是 开源的

我们提供了一个使用 php-enqueue/enqueue-bundle 的工作示例,该示例包含一组非常实用的命令,因此您不需要重复这些工作,结合其 文件系统传输。以下章节解释了如何使用所提供的队列系统。

发送电子邮件(到文件系统队列)

首先我们需要做的是修改 commandBus 定位映射,并使用 mail.send.queue.handler 而不是 mail.send.spool.handler

 $map = [
         CreateTokenCommand::class => 'token.create.handler',
         SendMessageCommand::class => 'mail.send.queue.handler', // must be set like this
     ];

这就完成了。使用相同的上一个调用,这次消息将发送到运行时文件夹中配置的队列。

从文件系统队列发送电子邮件

如我们之前所说,php-enqueue/enqueue-bundle 附带了一系列非常实用的命令。有关这些命令的完整参考,请参阅其 文档

用于消费队列中所有消息的命令是 enqueue:consume

$ ./bin/console enqueue:consume mail --no-interaction -vvv --receive-timeout=60000 

结合两者的优点

该库还附带了一个自定义队列,因此您可以使用 php-enqueue 与 Swiftmailer。

为了使用它,您需要在代码上进行一些更改

修改 mail.send.spool.handler

我们需要在 ./config/api/dependencies.php 文件中使用已配置的 SendMesssageSpoolHandler 来使用我们的自定义 EnqueueSpool 组件。

$container['mail.send.spool.handler'] = function ($container) {
    return new SendMessageSpoolHandler(
        $container['enqueue.mailer'], // <--- here is the modification
        $container['mustache'],
        $container['mustache.i18n.helper'],
        $container['fs']
    );
};

修改 services.yaml

然后在 ./config/console/services.yaml 中,我们应该重构文件,使其看起来像这样

swiftmailer.mailer.spool_mailer.spool.custom:
        class: App\Infrastructure\SwiftMailer\EnqueueSpool 
        arguments:
           $context: @enqueue.fs.context
           $queue: 'enqueue.app.mail'
           
        # class: App\Infrastructure\SwitftMailer\FileSpool # commented setting! 
        # arguments:
        #   $path: '%kernel.project_dir%/runtime/spool/default'

    enqueue.mail.processor:
        class: App\Application\Console\Processor\SendMailProcessor
        public: true
        arguments:
            $mailer: '@swiftmailer.mailer.enqueue_mailer'
            $mustache: '@mustache.engine.mail'
            $translatorHelper: '@mustache.i18n.helper'
        tags:
            - { name: 'enqueue.processor', command: '__command__', processorName: 'mail' }

    enqueue.fs.context: 
        class: Enqueue\Fs\FsContext
        arguments:
            $storeDir: '%kernel.project_dir%/runtime/queue'
            $preFetchCount: 1
            $chmod: 600
            $pollingInterval: 100

这就完成了,使用方法简单地遵循上述 从/到队列发送电子邮件 的指南。

贡献

要贡献,请阅读我们的 贡献指南

鸣谢

许可证

BSD许可证(BSD)。有关更多信息,请参阅 许可证文件

2amigOS!
软件之外
www.2amigos.us