lua-resty-smtp

ngx_lua 模块的 HTTP 到 SMTP 桥接库

$ opm get duhoobo/lua-resty-smtp

lua-resty-smtp

我一定是疯了,想用 Nginx 发送邮件。

目的

使 Nginx 成为 HTTP 和 SMTP 之间的桥梁。

在 Nginx 的 lua 代码中使用lua-resty-smtp,你只需要使用你方便的 HTTP 客户端(例如curlwget、Python 的urllib2等)发出 HTTP 请求,就可以将邮件发送到你的 SMTP 服务器。

特性

  • 支持 SSL 连接(需要 lua-nginx-lua >= v0.9.11)

API

lua-resty-smtpLuaSocket 2.0.2 中的socket.smtp API 兼容,你可以查看 SMTP 获取其详细参考。

为了支持与 SMTP 服务器的 SSL 连接,添加了可选参数ssl

  • ssl: 应该是一个包含以下字段的表

lua-resty-smtp ==============

我一定是疯了,想用 Nginx 发送邮件。

目的 -------

使 Nginx 成为 HTTP 和 SMTP 之间的桥梁。

在 Nginx 的 lua 代码中使用 `lua-resty-smtp`,你只需要使用你方便的 HTTP 客户端(例如 `curl`、`wget`、Python 的 `urllib2` 等)发出 HTTP 请求,就可以将邮件发送到你的 SMTP 服务器。

特性 --------

* 基于 [LuaScoket 2.0.2](http://w3.impa.br/~diego/software/luasocket/home.html) 中的 `socket.smtp` 模块,并且与其 API 兼容

* 支持 SSL 连接(需要 lua-nginx-lua >= v0.9.11)

API ----

`lua-resty-smtp` 与 [LuaSocket 2.0.2](http://w3.impa.br/~diego/software/luasocket/home.html) 中的 `socket.smtp` API 兼容,你可以查看 [SMTP](http://w3.impa.br/~diego/software/luasocket/smtp.html) 获取其详细参考。

为了支持与 SMTP 服务器的 SSL 连接,添加了可选参数 `ssl`

* `ssl`: 应该是一个包含以下字段的表

    * `enable` - boolean - whether or not use SSL connection to SMTP server,
    default `false`;

    * `verify_cert` - boolean - whether or not to perform SSL verification,
    default `false`. When set to `true`, the server certificate will be verified
    according to the CA certificate specified by the
    [`lua_ssl_trusted_cerfificate`](http://wiki.nginx.org/HttpLuaModule#lua_ssl_trusted_certificate)
    directive.

额外过滤器 -------------

除了 LuaSocket 提供的底层过滤器外,还提供了两个过滤器

* `mime.ew`: 用于将非 ASCII 字符串编码为 [Encoded-Word](http://en.wikipedia.org/wiki/MIME#Encoded-Word) 格式(目前不支持 _Q-encoding_);

* `mime.unew`: 用于解码 Encoded-Word 格式的字符串(未实现);

安装 ------------

    make install

    luarocks install --local rockspec/resty.smtp-0.0.3-1.rockspec

示例 -------

    local config = require("config")
    local smtp = require("resty.smtp")
    local mime = require("resty.smtp.mime")
    local ltn12 = require("resty.smtp.ltn12")

    -- ...
    -- Suppose your mail data in table `args` and default settings
    -- in table `config.mail`
    -- ...

    local mesgt = {
        headers= {
            subject= mime.ew(args.subject or config.mail.SUBJECT, nil,
                             { charset= "utf-8" }),
            ["content-transfer-encoding"]= "BASE64",
            ["content-type"]= "text/plain; charset='utf-8'",
        },

        body= mime.b64(args.body)
    }

    local ret, err = smtp.send {
        from= args.from or config.mail.FROM,
        rcpt= rcpts,
        user= args.user or config.mail.USER,
        password= args.password or config.mail.PASSWORD,
        server= args.server or config.mail.SERVER,
        domain= args.domain or config.mail.DOMAIN,
        source= smtp.message(mesgt),
    }

注意事项

* `ngx.tcp.socket` 使用 Nginx 内置的非阻塞 DNS 解析器来解析域名,前提是你使用主机名而不是 IP 地址配置了 `server` 字段。有关更多信息,请参阅 Nginx 指令 `resolver` 的 [文档](https://nginx.ac.cn/en/docs/http/ngx_http_core_module.html#resolver)。

待办事项 ----

* 当多个收件人中的一个无效时,不要中止整个 SMTP 请求;* 是否使用 FFI 重新实现 MIME 相关的纯 lua 版本的底层过滤器?* 实现过滤器 `mime.unew`;* 通过 `module()` 减少命名空间污染;

性能 -----------

你的 SMTP 服务器是瓶颈。 :)

已知问题 ------------

* 目前仅适用于 LuaJIT 2.x,因为代码库大量依赖于 `pcall`,并且 lua-nginx-module 在这种情况下与标准 Lua 5.1 VM 的配合效果不佳。请参阅 [已知问题](http://wiki.nginx.org/HttpLuaModule#Lua_Coroutine_Yielding.2FResuming)

enable - 布尔值 - 是否使用 SSL 连接到 SMTP 服务器,默认为 false

        C<verify_cert> - boolean - whether or not to perform SSL verification,
default C<false>. When set to C<true>, the server certificate will be verified
according to the CA certificate specified by the
L<`lua_ssl_trusted_cerfificate`|http://wiki.nginx.org/HttpLuaModule#lua_ssl_trusted_certificate>
directive.

额外过滤器

除了 LuaSocket 提供的底层过滤器外,还提供了两个过滤器

  • mime.ew: 用于将非 ASCII 字符串编码为 Encoded-Word 格式(目前不支持 Q-encoding);

  • mime.unew: 用于解码 Encoded-Word 格式的字符串(未实现);

安装

    make install

    luarocks install --local rockspec/resty.smtp-0.0.3-1.rockspec

示例

    local config = require("config")
    local smtp = require("resty.smtp")
    local mime = require("resty.smtp.mime")
    local ltn12 = require("resty.smtp.ltn12")

    -- ...
    -- Suppose your mail data in table `args` and default settings
    -- in table `config.mail`
    -- ...

    local mesgt = {
        headers= {
            subject= mime.ew(args.subject or config.mail.SUBJECT, nil,
                             { charset= "utf-8" }),
            ["content-transfer-encoding"]= "BASE64",
            ["content-type"]= "text/plain; charset='utf-8'",
        },

        body= mime.b64(args.body)
    }

    local ret, err = smtp.send {
        from= args.from or config.mail.FROM,
        rcpt= rcpts,
        user= args.user or config.mail.USER,
        password= args.password or config.mail.PASSWORD,
        server= args.server or config.mail.SERVER,
        domain= args.domain or config.mail.DOMAIN,
        source= smtp.message(mesgt),
    }

注意事项

  • ngx.tcp.socket 使用 Nginx 内置的非阻塞 DNS 解析器来解析域名,前提是你使用主机名而不是 IP 地址配置了 `server` 字段。有关更多信息,请参阅 Nginx 指令 `resolver` 的 文档

待办事项

  • 当多个收件人中的一个无效时,不要中止整个 SMTP 请求;

  • 是否使用 FFI 重新实现 MIME 相关的纯 lua 版本的底层过滤器?

  • 实现过滤器 mime.unew

  • 通过 module() 减少命名空间污染;

性能

你的 SMTP 服务器是瓶颈。 :)

已知问题

  • 目前仅适用于 LuaJIT 2.x,因为代码库大量依赖于 pcall,并且 lua-nginx-module 在这种情况下与标准 Lua 5.1 VM 的配合效果不佳。请参阅 已知问题

作者

杜洪浦 (duhoobo)

许可证

2bsd

依赖

luajit

版本