#send-email #automation #cli

bin+lib 鸽子-rs

经济高效的电子邮件自动化命令行工具

9 个版本

0.4.2 2024 年 5 月 2 日
0.4.1 2024 年 4 月 6 日
0.4.0 2023 年 12 月 24 日
0.3.0 2022 年 7 月 8 日
0.1.3 2021 年 11 月 16 日

#259 in 电子邮件

Download history 180/week @ 2024-04-28 7/week @ 2024-05-05 12/week @ 2024-05-19 3/week @ 2024-06-02 1/week @ 2024-06-09 17/week @ 2024-07-07

每月 574 次下载

Apache-2.0

120KB
2.5K SLoC

鸽子

latest version documentation build status codecov dependency status

鸽子是一个用于以经济高效的方式自动化您的电子邮件工作流程的命令行工具。利用您最熟悉的开发工具。

例如,查询您的时事通讯的订阅者,从模板文件创建纯文本和 html 电子邮件,并全部发送给他们

pigeon send-bulk \
    [email protected] \
    --receiver-query "select email from user where newsletter_confirmed = true" \
    --message-file "message.yaml" \
    --display \
    --assume-yes
> Display query result: shape: (4, 1)
+------------------------------+
| email                        |
| ---                          |
| str                          |
+==============================+
| "[email protected]"            |
+------------------------------+
| "[email protected]" |
+------------------------------+
| "[email protected]"           |
+------------------------------+
| "[email protected]"            |
+------------------------------+
> Sending email to 4 receivers ...
[email protected] ... ok
[email protected] ... ok
[email protected] ... ok
[email protected] ... ok

安装 Pigeon

crates.io 安装 Pigeon

# Build and install pigeon binary to ~/.cargo/bin
cargo install pigeon-rs

注意: 再次运行 cargo install pigeon-rs 以更新到最新版本。使用 cargo uninstall pigeon-rs 卸载 pigeon 二进制文件。

github.com 安装 Pigeon

# Clone repository
git clone [email protected]:quambene/pigeon-rs.git
cd pigeon-rs

# Build and install pigeon binary to ~/.cargo/bin
cargo install --path .

注意: 如果缺少,请将 $HOME/.cargo/bin 添加到您的 PATH

export PATH="$HOME/.cargo/bin:$PATH"

获取帮助

要获取帮助,请尝试以下方法之一

# Check version
pigeon --version

# Print help
pigeon --help

# Print help for subcommand
pigeon help send
pigeon help send-bulk
pigeon help connect
pigeon help init
pigeon help query
pigeon help simple-query
pigeon help read

用法

使用 pigeon connect 检查与您的 SMTP 服务器的连接

pigeon connect

正在连接到 SMTP 服务器 'email-smtp.eu-west-1.amazonaws.com' ... ok

请参阅以下支持的 集成连接方法

注意: 您还可以检查连接到第三方 API,而不仅仅是使用 SMTP 协议。例如,使用 AWS Simple Email Service (SES):pigeon connect aws

向单个接收者发送电子邮件

使用主题和内容发送单个电子邮件

pigeon send \
    [email protected] \
    [email protected] \
    --subject "Test subject" \
    --content "This is a test email."

使用单独的模板文件定义的消息发送单个电子邮件

pigeon send \
    [email protected] \
    [email protected] \
    --message-file "message.yaml"

消息模板 message.yaml 是使用子命令 init 创建的

pigeon init

注意: --message-file 的一项优点是您还可以草拟电子邮件的 HTML 版本。相比之下,使用选项 --subject--content,电子邮件将以纯文本格式发送。

如果您更喜欢用于草拟电子邮件的专用 HTML 文件,请使用以下命令

pigeon send \
    [email protected] \
    [email protected] \
    --subject "Test subject" \
    --text-file "./message.txt" \
    --html-file "./message.html"

其中,--text-file 定义纯文本,而 --html-file 定义电子邮件的 HTML 版本。

向多个接收者发送批量电子邮件

例如,查询已确认接收您的时事通讯的相关用户,并向他们所有人发送电子邮件。

让我们首先通过 pigeon query 检查查询

pigeon query --display "select email from user where newsletter_confirmed = true"
> Display query result: shape: (4, 1)
+------------------------------+
| email                        |
| ---                          |
| str                          |
+==============================+
| "[email protected]"            |
+------------------------------+
| "[email protected]" |
+------------------------------+
| "[email protected]"           |
+------------------------------+
| "[email protected]"            |
+------------------------------+

请参阅下面的 如何连接 以连接到您的数据库。

注意: 您还可以将查询保存为 CSV 文件:pigeon query --save <my-query>

现在向查询到的接收者发送时事通讯。如果表列名不同于 "email",请使用 --receiver-column 定义不同的列名。让我们首先尝试一个没有确认的 --dry-run--assume-yes

pigeon send-bulk \
    [email protected] \
    --receiver-query "select email from user where newsletter_confirmed = true" \
    --message-file "message.yaml" \
    --assume-yes \
    --dry-run
> Sending email to 4 receivers ...
[email protected] ... dry run
[email protected] ... dry run
[email protected] ... dry run
[email protected] ... dry run

在双重检查后,您可以提交相同的命令而不使用 --dry-run。还要删除 --assume-yes 以进行明确的确认。

注意: 您还可以向定义在 CSV 文件中的电子邮件地址发送批量电子邮件,而不是查询结果。在这种情况下,请使用选项 --receiver-file 而不是 --receiver-query。您可以通过子命令 read 检查 CSV 文件的内容,例如 pigeon read recipients.csv

个性化您的电子邮件

如果您需要更多个人电子邮件,您可以使用选项 --personalize 来个性化您的电子邮件。让我们首先检查相关的查询

pigeon query --display "select first_name, last_name, email from user where newsletter_confirmed = true"
> Display query result: shape: (4, 3)
+-------------+----------------+------------------------------+
| first_name  | last_name      | email                        |
| ---         | ---            | ---                          |
| str         | str            | str                          |
+=============+================+==============================+
| "Marie"     | "Curie"        | "[email protected]"            |
+-------------+----------------+------------------------------+
| "Alexandre" | "Grothendieck" | "[email protected]" |
+-------------+----------------+------------------------------+
| "Emmy"      | "Noether"      | "[email protected]"           |
+-------------+----------------+------------------------------+
| "Elie"      | "Cartan"       | "[email protected]"            |
+-------------+----------------+------------------------------+

在您的消息模板 message.yaml 中,使用大括号中的变量,例如 {first_name}{last_name}。然后定义个人列作为选项 --personalize 的参数。最后,让我们使用 --display 显示一切。

pigeon send-bulk \
    [email protected] \
    --receiver-query "select first_name, last_name, email from user where newsletter_confirmed = true" \
    --message-file "message.yaml" \
    --personalize "first_name" "last_name" \
    --display
> Display message file: MessageTemplate {
    message: Message {
        subject: "Issue No. 1",
        text: "Dear {first_name} {last_name},
            Welcome to my newsletter. We are doing hard sciences here.
            Sincerely, Albert Einstein",
        html: "Dear {first_name} {last_name},
            Welcome to my newsletter. We are doing hard sciences here.
            Sincerely, Albert Einstein",
    },
}
> Display emails: BulkEmail {
    emails: [
        Email {
            sender: "[email protected]",
            receiver: "[email protected]",
            message: Message {
                subject: "Issue No. 1",
                text: "Dear Marie Curie,
                    Welcome to my newsletter. We are doing hard sciences here.
                    Sincerely, Albert Einstein",
                html: "Dear Marie Curie,
                    Welcome to my newsletter. We are doing hard sciences here.
                    Sincerely, Albert Einstein",
                },
        },
        Email {
            sender: "[email protected]",
            receiver: "[email protected]",
            message: Message {
                subject: "Issue No. 1",
                text: "Dear Alexandre Grothendieck,
                    Welcome to my newsletter. We are doing hard sciences here.
                    Sincerely, Albert Einstein",
                html: "Dear Alexandre Grothendieck,
                    Welcome to my newsletter. We are doing hard sciences here.
                    Sincerely, Albert Einstein",
            },
        },
        Email {
            sender: "[email protected]",
            receiver: "[email protected]",
            message: Message {
                subject: "Issue No. 1",
                text: "Dear Emmy Noether,
                    Welcome to my newsletter. We are doing hard sciences here.
                    Sincerely, Albert Einstein",
                html: "Dear Emmy Noether,
                    Welcome to my newsletter. We are doing hard sciences here.
                    Sincerely, Albert Einstein",
            },
        },
        Email {
            sender: "[email protected]",
            receiver: "[email protected]",
            message: Message {
                subject: "Issue No. 1",
                text: "Dear Elie Cartan,
                    Welcome to my newsletter. We are doing hard sciences here.
                    Sincerely, Albert Einstein",
                html: "Dear Elie Cartan,
                    Welcome to my newsletter. We are doing hard sciences here.
                    Sincerely, Albert Einstein",
            },
        },
    ],
}
> Should an email be sent to 4 recipients? Yes (y) or no (n)
>

如果您准备好出发,请确认 y

如何连接

如何连接到 SMTP 服务器

要连接到 SMTP 服务器,请定义环境变量 SMTP_SERVERSMTP_USERNAMESMTP_PASSWORD。例如,使用 AWS SES

SMTP_SERVER=email-smtp.eu-west-1.amazonaws.com
SMTP_USERNAME=...
SMTP_PASSWORD=...

在您的当前 shell 中源环境 .env

set -a && source .env && set +a

如何连接到电子邮件提供商 API

您还可以通过特定电子邮件提供商的 API 发送电子邮件而不是使用 SMTP。

使用 AWS SES,请定义以下环境变量

AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_REGION=eu-west-1

其中,AWS_REGION 依赖于您的 AWS SES 账户指定的区域。

再次源环境

set -a && source .env && set +a

使用 --connection 发送电子邮件

pigeon send \
    sender@your-domain.com \
    receiver@gmail.com \
    --connection aws \
    --message-file "message.yaml"

如何连接到 postgres 数据库

对于 postgres,数据库 URL 的构造如下:postgresql://db_user:db_password@db_host:db_port/db_name

因此,在您的环境 .env 中设置以下环境变量

  • DB_HOST
  • DB_PORT
  • DB_USER
  • DB_PASSWORD
  • DB_NAME

再次源环境

set -a && source .env && set +a

注意: 目前不支持通过 TLS 连接。请通过 SSH 隧道转发本地端口,例如:

pigeon query "select email from user where newsletter_confirmed = true" --display --ssh-tunnel 5437

除了上述环境变量外,还需要设置 SERVER_USERSERVER_HOST 以进行 SSH 连接(ssh user@host)。

集成

电子邮件协议

  • MIME
  • SMTP

第三方 API

  • AWS SES

数据源

  • PostgreSQL
  • CSV

与 Mailchimp、Sendgrid 和 ConvertKit 的比较

这些数字可能已经过时。请自行进行研究。

以下表格比较了电子邮件提供商每月的价格和每月的电子邮件数量。

  5,000 10,000 100,000
Pigeon+AWS $4.50 $5 $14
Mailchimp 营销 $9.99 $20.99 $78.99
Mailchimp 交易性 - - $80
Sendgrid 营销 $15 $15 $120
Sendgrid API $14.95 $14.95 $29.95
ConvertKit $66 $100 $516

以下表格显示了每个提供商每天发送电子邮件的限制。

提供商 每日限制
Pigeon+AWS 50,000
Mailchimp 等于每月限制
Sendgrid 等于每月限制

测试

某些集成测试需要本地运行的 PostgreSQL 数据库

  1. 指定以下环境变量
    • DB_HOST
    • DB_PORT
    • DB_USER
    • DB_PASSWORD
    • DB_NAME
  2. 设置一个临时的 PostgreSQL 数据库: docker-compose run --rm --service-ports postgres
# Run unit tests and integration tests
cargo test

# Run unit tests
cargo test --lib

# Run integration tests
cargo test --test '*'

依赖项

~54–73MB
~1.5M SLoC