Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: init send mail #113

Merged
merged 2 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# CHANGE LOG

## 2024-04-12 v0.0.2

- support send email

DB changes:

- `db/2024-04-12-patch.sql`

## 2024-04-10 v0.0.1

Breaking changes:
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
- [Cloudflare Workers 后端](#cloudflare-workers-后端-1)
- [Cloudflare Email Routing](#cloudflare-email-routing)
- [Cloudflare Pages 前端](#cloudflare-pages-前端)
- [配置发送邮件](#配置发送邮件)
- [参考资料](#参考资料)


Expand All @@ -60,6 +61,7 @@
- [x] 增加自动回复功能
- [x] 增加查看附件功能
- [x] 使用 rust wasm 解析邮件
- [x] 支持发送邮件

---

Expand Down Expand Up @@ -201,6 +203,19 @@ pnpm run deploy

![pages](readme_assets/pages.png)

## 配置发送邮件

找到域名 `DNS` 记录的 `TXT` 的 `SPF` 记录, 增加 `include:relay.mailchannels.net`

```bash
v=spf1 include:_spf.mx.cloudflare.net include:relay.mailchannels.net ~all
```

新建 `_mailchannels` 记录, 类型为 `TXT`, 内容为 `v=mc1 cfid=你的worker域名`

- 此处 worker 域名为后端 api 的域名,比如我部署在 `https://temp-email-api.awsl.uk/`,则填写 `v=mc1 cfid=awsl.uk`
- 如果你的域名是 `https://temp-email-api.xxx.workers.dev`,则填写 `v=mc1 cfid=xxx.workers.dev`

## 参考资料

- https://developers.cloudflare.com/d1/
Expand Down
14 changes: 14 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This is a temporary email service that uses Cloudflare Workers to create a tempo
- [x] Add auto reply feature
- [x] Add attachment viewing function
- [x] use rust wasm to parse email
- [x] support send email

![demo](readme_assets/demo.png)

Expand Down Expand Up @@ -92,3 +93,16 @@ pnpm run deploy
```

![pages](readme_assets/pages.png)

## Configure sending emails

Find the `SPF` record of `TXT` in the domain name `DNS` record, and add `include:relay.mailchannels.net`

```bash
v=spf1 include:_spf.mx.cloudflare.net include:relay.mailchannels.net ~all
```

Create a new `_mailchannels` record, the type is `TXT`, the content is `v=mc1 cfid=your worker domain name`

- The worker domain name here is the domain name of the back-end api. For example, if I deploy it at `https://temp-email-api.awsl.uk/`, fill in `v=mc1 cfid=awsl.uk`
- If your domain name is `https://temp-email-api.xxx.workers.dev`, fill in `v=mc1 cfid=xxx.workers.dev`
14 changes: 14 additions & 0 deletions db/2024-04-12-patch.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS address_sender (
id INTEGER PRIMARY KEY,
address TEXT UNIQUE,
balance INTEGER DEFAULT 0,
enabled INTEGER DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS sendbox (
id INTEGER PRIMARY KEY,
address TEXT,
raw TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
27 changes: 27 additions & 0 deletions db/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ CREATE TABLE IF NOT EXISTS mails (
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_mails_address ON mails(address);

CREATE TABLE IF NOT EXISTS raw_mails (
id INTEGER PRIMARY KEY,
message_id TEXT,
Expand All @@ -17,13 +19,17 @@ CREATE TABLE IF NOT EXISTS raw_mails (
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_raw_mails_address ON raw_mails(address);

CREATE TABLE IF NOT EXISTS address (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_address_name ON address(name);

CREATE TABLE IF NOT EXISTS auto_reply_mails (
id INTEGER PRIMARY KEY,
source_prefix TEXT,
Expand All @@ -35,6 +41,8 @@ CREATE TABLE IF NOT EXISTS auto_reply_mails (
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_auto_reply_mails_address ON auto_reply_mails(address);

CREATE TABLE IF NOT EXISTS attachments (
id INTEGER PRIMARY KEY,
source TEXT,
Expand All @@ -43,3 +51,22 @@ CREATE TABLE IF NOT EXISTS attachments (
data TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS address_sender (
id INTEGER PRIMARY KEY,
address TEXT UNIQUE,
balance INTEGER DEFAULT 0,
enabled INTEGER DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_address_sender_address ON address_sender(address);

CREATE TABLE IF NOT EXISTS sendbox (
id INTEGER PRIMARY KEY,
address TEXT,
raw TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_sendbox_address ON sendbox(address);
1 change: 1 addition & 0 deletions frontend/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const getSettings = async () => {
address: res["address"],
auto_reply: res["auto_reply"],
has_v1_mails: res["has_v1_mails"],
send_balance: res["send_balance"],
};
} finally {
settings.value.fetched = true;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const i18n = createI18n({
'en': {
messages: {}
},
'zhCN': {
'zh': {
messages: {}
}
})
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/router/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { createRouter, createWebHistory } from 'vue-router'
import Index from '../views/Index.vue'
import Settings from '../views/Settings.vue'
import SendMail from '../views/send/SendMail.vue'
import Admin from '../views/Admin.vue'
import SendBox from '../views/send/SendBox.vue'

const router = createRouter({
history: createWebHistory(),
Expand All @@ -14,6 +16,14 @@ const router = createRouter({
path: '/settings',
component: Settings
},
{
path: '/send',
component: SendMail
},
{
path: '/sendbox',
component: SendBox
},
{
path: '/admin',
component: Admin
Expand Down
1 change: 1 addition & 0 deletions frontend/src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const useGlobalState = createGlobalState(
const settings = ref({
fetched: false,
has_v1_mails: false,
send_balance: 0,
address: '',
auto_reply: {
subject: '',
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/views/Admin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { User, UserCheck, MailBulk } from '@vicons/fa'

import { useGlobalState } from '../store'
import { api } from '../api'
import { processItem, getDownloadEmlUrl } from '../utils/email-parser'
import { processItem } from '../utils/email-parser'
import SenderAccess from './admin/SenderAccess.vue'

const { localeCache, adminAuth, showAdminAuth } = useGlobalState()
const router = useRouter()
Expand Down Expand Up @@ -49,6 +50,7 @@ const { t } = useI18n({
account: 'Account',
unknow: 'Unknow',
addressQueryTip: 'Leave blank to query all addresses',
senderAccess: 'Sender Access Control',
},
zh: {
title: '临时邮件 Admin',
Expand All @@ -72,6 +74,7 @@ const { t } = useI18n({
account: '账号',
unknow: '未知',
addressQueryTip: '留空查询所有地址',
senderAccess: '发件权限控制',
}
}
});
Expand Down Expand Up @@ -396,6 +399,9 @@ const fetchMailUnknowData = async () => {
</n-list-item>
</n-list>
</n-tab-pane>
<n-tab-pane name="senderAccess" :tab="t('senderAccess')">
<SenderAccess />
</n-tab-pane>
</n-tabs>
</div>
</template>
Expand Down
24 changes: 23 additions & 1 deletion frontend/src/views/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ref, h, computed, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router'
import { useIsMobile } from '../utils/composables'
import { DarkModeFilled, LightModeFilled, MenuFilled, AdminPanelSettingsFilled } from '@vicons/material'
import { DarkModeFilled, LightModeFilled, MenuFilled, AdminPanelSettingsFilled, SendFilled } from '@vicons/material'
import { GithubAlt, Language, User, Home, Copy } from '@vicons/fa'

import { useGlobalState } from '../store'
Expand Down Expand Up @@ -73,6 +73,8 @@ const { t } = useI18n({
home: 'Home',
menu: 'Menu',
user: 'User',
sendbox: 'Send Box',
sendMail: 'Send Mail',
pleaseGetNewEmail: 'Please login or click "Get New Email" button to get a new email address',
getNewEmail: 'Get New Email',
getNewEmailTip1: 'Please input the email you want to use. only allow ., a-z, A-Z and 0-9',
Expand Down Expand Up @@ -104,6 +106,8 @@ const { t } = useI18n({
home: '主页',
menu: '菜单',
user: '用户',
sendbox: '发件箱',
sendMail: '发送邮件',
pleaseGetNewEmail: '请"登录"或点击 "获取新邮箱" 按钮来获取一个新的邮箱地址',
getNewEmail: '获取新邮箱',
getNewEmailTip1: '请输入你想要使用的邮箱地址, 只允许 ., a-z, A-Z, 0-9',
Expand Down Expand Up @@ -176,6 +180,19 @@ const menuOptions = computed(() => [
show: showUserMenu.value,
key: "user",
children: [
{
label: () => h(
NButton,
{
tertiary: true,
ghost: true,
size: "small",
onClick: () => router.push('/sendbox')
},
{ default: () => t('sendbox') }
),
key: "sendbox"
},
{
label: () => h(
NButton,
Expand Down Expand Up @@ -358,6 +375,7 @@ const deleteAccount = async () => {
onMounted(async () => {
await api.getOpenSettings(message);
emailDomain.value = openSettings.value.domains ? openSettings.value.domains[0].value : "";
await api.getSettings();
});
</script>

Expand Down Expand Up @@ -386,6 +404,10 @@ onMounted(async () => {
<n-alert type="info" show-icon>
<span>
<b>{{ t('yourAddress') }} <b>{{ settings.address }}</b></b>
<n-button style="margin-left: 10px" @click="router.push('/send')" size="small" tertiary round
type="primary">
<n-icon :component="SendFilled" /> {{ t('sendMail') }}
</n-button>
<n-button style="margin-left: 10px" @click="copy" size="small" tertiary round type="primary">
<n-icon :component="Copy" /> {{ t('copy') }}
</n-button>
Expand Down
Loading