├── .editorconfig
├── .github
├── release.yml
└── workflows
│ └── deploy.yml
├── .gitignore
├── .prettierrc
├── README.md
├── package-lock.json
├── package.json
├── src
├── bindings.d.ts
├── email.ts
├── index.ts
└── template.ts
├── tsconfig.json
└── wrangler.toml
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = tab
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.yml]
12 | indent_style = space
13 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | # .github/release.yml
2 |
3 | changelog:
4 |
5 | categories:
6 |
7 | - title: New Features
8 | labels:
9 | - enhancement
10 |
11 | - title: Bugs Fixed
12 | labels:
13 | - bug
14 |
15 | - title: Other Changes
16 | labels:
17 | - "*"
18 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Worker
2 | on:
3 | push:
4 | tags:
5 | - "v*"
6 | jobs:
7 | deploy:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v4
11 | - name: Build & Deploy Worker
12 | uses: cloudflare/wrangler-action@v3
13 | with:
14 | apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
15 | accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
16 | secrets: |
17 | ACCESS_TOKEN
18 | RESEND_APIKEY
19 | SENDER_NAME
20 | SENDER_EMAIL
21 | env:
22 | ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
23 | RESEND_APIKEY: ${{ secrets.RESEND_APIKEY }}
24 | SENDER_NAME: ${{ secrets.SENDER_NAME }}
25 | SENDER_EMAIL: ${{ secrets.SENDER_EMAIL }}
26 |
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 |
3 | logs
4 | _.log
5 | npm-debug.log_
6 | yarn-debug.log*
7 | yarn-error.log*
8 | lerna-debug.log*
9 | .pnpm-debug.log*
10 |
11 | # Diagnostic reports (https://nodejs.org/api/report.html)
12 |
13 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
14 |
15 | # Runtime data
16 |
17 | pids
18 | _.pid
19 | _.seed
20 | \*.pid.lock
21 |
22 | # Directory for instrumented libs generated by jscoverage/JSCover
23 |
24 | lib-cov
25 |
26 | # Coverage directory used by tools like istanbul
27 |
28 | coverage
29 | \*.lcov
30 |
31 | # nyc test coverage
32 |
33 | .nyc_output
34 |
35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
36 |
37 | .grunt
38 |
39 | # Bower dependency directory (https://bower.io/)
40 |
41 | bower_components
42 |
43 | # node-waf configuration
44 |
45 | .lock-wscript
46 |
47 | # Compiled binary addons (https://nodejs.org/api/addons.html)
48 |
49 | build/Release
50 |
51 | # Dependency directories
52 |
53 | node_modules/
54 | jspm_packages/
55 |
56 | # Snowpack dependency directory (https://snowpack.dev/)
57 |
58 | web_modules/
59 |
60 | # TypeScript cache
61 |
62 | \*.tsbuildinfo
63 |
64 | # Optional npm cache directory
65 |
66 | .npm
67 |
68 | # Optional eslint cache
69 |
70 | .eslintcache
71 |
72 | # Optional stylelint cache
73 |
74 | .stylelintcache
75 |
76 | # Microbundle cache
77 |
78 | .rpt2_cache/
79 | .rts2_cache_cjs/
80 | .rts2_cache_es/
81 | .rts2_cache_umd/
82 |
83 | # Optional REPL history
84 |
85 | .node_repl_history
86 |
87 | # Output of 'npm pack'
88 |
89 | \*.tgz
90 |
91 | # Yarn Integrity file
92 |
93 | .yarn-integrity
94 |
95 | # dotenv environment variable files
96 |
97 | .env
98 | .env.development.local
99 | .env.test.local
100 | .env.production.local
101 | .env.local
102 |
103 | # parcel-bundler cache (https://parceljs.org/)
104 |
105 | .cache
106 | .parcel-cache
107 |
108 | # Next.js build output
109 |
110 | .next
111 | out
112 |
113 | # Nuxt.js build / generate output
114 |
115 | .nuxt
116 | dist
117 |
118 | # Gatsby files
119 |
120 | .cache/
121 |
122 | # Comment in the public line in if your project uses Gatsby and not Next.js
123 |
124 | # https://nextjs.org/blog/next-9-1#public-directory-support
125 |
126 | # public
127 |
128 | # vuepress build output
129 |
130 | .vuepress/dist
131 |
132 | # vuepress v2.x temp and cache directory
133 |
134 | .temp
135 | .cache
136 |
137 | # Docusaurus cache and generated files
138 |
139 | .docusaurus
140 |
141 | # Serverless directories
142 |
143 | .serverless/
144 |
145 | # FuseBox cache
146 |
147 | .fusebox/
148 |
149 | # DynamoDB Local files
150 |
151 | .dynamodb/
152 |
153 | # TernJS port file
154 |
155 | .tern-port
156 |
157 | # Stores VSCode versions used for testing VSCode extensions
158 |
159 | .vscode-test
160 |
161 | # yarn v2
162 |
163 | .yarn/cache
164 | .yarn/unplugged
165 | .yarn/build-state.yml
166 | .yarn/install-state.gz
167 | .pnp.\*
168 |
169 | # wrangler project
170 |
171 | .dev.vars
172 | .wrangler/
173 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "singleQuote": true,
4 | "semi": true,
5 | "useTabs": true
6 | }
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cloudflare-email-sender
2 |
3 |
4 | > 自 2024 年 8 月 31 日起,MailChannels 不再为 Cloudflare Workers 用户提供免费电子邮件发送服务 [MailChannels原文](https://support.mailchannels.com/hc/en-us/articles/26814255454093-End-of-Life-Notice-Cloudflare-Workers)
5 | > 由于mailchannels不再免费 且申请免费账户需信用卡成本较高,因此放弃继续使用,转为Resend发信服务
6 | > 如仍需要mailchannels发信, 请查看 `old/mailchannels` 分支
7 |
8 | 使用 cloudflare 免费发送邮件
9 |
10 | ## 前置条件
11 |
12 | - 一个 Cloudflare 帐户
13 | - 一个 Resend 账户
14 | - 一个可以被 Cloudflare 管理的域名
15 | - npm 软件包 create-cloudflare、resend
16 | - git
17 | - openssl(可选)
18 |
19 | ## Resend 相关
20 |
21 | 如果您还没有 Resend 帐户,可以注册一个 [Resend 免费帐户](https://resend.com/signup) 。注册后,前往 Domains 菜单项,然后点击`Add Domain`,输入要添加的域,然后选择一个区域。
22 |
23 | 随后在 Cloudflare 中的 DNS 中配置 Resend 中需要的 DNS 记录
24 |
25 | 
26 |
27 | 配置并校验完成后,在 Resend 菜单中找到 `API Keys` 创建一个 key 记下这个 key 随后项目中会用到。
28 |
29 | > 注意 Resend免费计划用户 每天有100封的发信限制 每月有3000封的发信限制。
30 | > 如果需要发送更多邮件请升级 Resend 的计划
31 |
32 | ## 创建邮件发送服务
33 |
34 | 1. 克隆项目到本地
35 |
36 | ```
37 | git clone https://github.com/devcxl/cloudflare-email-sender
38 | ```
39 |
40 | 2. 编辑 `wrangler.toml` 中的变量
41 | ```
42 | # 自定义域名的发信邮件地址
43 | SENDER_EMAIL = "do-not-replay@example.com"
44 | # 发信人简称/名字
45 | SENDER_NAME = "Example"
46 | ```
47 | 3. 运行 `openssl rand -base64 32` 生成一个随机密钥(可选,可以自己设置密钥)
48 |
49 | 
50 |
51 | 4. 运行 `npx wrangler secret put ACCESS_TOKEN` 设置上一步生成的随机密钥
52 |
53 | 
54 |
55 | 5. 运行 `npx wrangler secret put RESEND_APIKEY` 设置 Resend 中得到的 key
56 | 
57 |
58 | 6. 部署项目
59 | ```
60 | npm run deploy
61 | ```
62 |
63 | ## 使用示例
64 |
65 | ### 发送HTML邮件
66 |
67 | ```shell
68 | curl -X POST -L https://custom.yourdomain.com/v1/send \
69 | -H 'Content-Type: application/json' \
70 | -H 'Authorization: Bearer {ACCESS_TOKEN}' \
71 | -d '{
72 | "to": "you@example.com",
73 | "title": "Just Test Message",
74 | "content": "
86 |
87 | |
88 |
89 |
90 |
91 |
92 | 激活{siteTitle}账户 |
93 |
94 |
95 |
96 |
98 |
99 |
100 | 亲爱的{userName}:
101 | |
102 |
103 |
104 | 感谢您注册{siteTitle},请点击下方按钮完成账户激活。 |
107 |
108 |
109 | 激活账户
113 | |
114 |
115 |
116 | 感谢您选择{siteTitle}。 |
119 |
120 |
121 | |
122 |
123 |
124 |
131 |
132 | |
133 | |
134 |
135 |
136 |
137 | `;
138 |
139 | export const activation = (siteTitle:string, userName:string, activationUrl:string) => {
140 | return activation_template
141 | .replace(/\{siteTitle\}/g, siteTitle)
142 | .replace(/\{userName\}/g, userName)
143 | .replace(/\{activationUrl\}/g, activationUrl);
144 | };
145 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "moduleResolution": "Bundler",
6 | "strict": true,
7 | "lib": ["ESNext"],
8 | "types": ["@cloudflare/workers-types"],
9 | "jsx": "react-jsx",
10 | "jsxImportSource": "hono/jsx"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/wrangler.toml:
--------------------------------------------------------------------------------
1 | #:schema node_modules/wrangler/config-schema.json
2 | name = "email-sender"
3 | main = "src/index.ts"
4 | compatibility_date = "2024-04-05"
5 |
6 | dev.host = "127.0.0.1"
7 | dev.port = 8787
8 |
9 | [vars]
10 | # 自定义域名的发信邮件地址
11 | # SENDER_EMAIL = "do-not-replay@example.com"
12 | # 发信人简称/名字
13 | # SENDER_NAME = "Example"
14 |
--------------------------------------------------------------------------------