mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-05-11 09:59:46 +08:00
feat: init send mail (#113)
* feat: init send mail * feat: init send mail
This commit is contained in:
@@ -138,6 +138,47 @@ api.get('/admin/mails_unknow', async (c) => {
|
||||
})
|
||||
});
|
||||
|
||||
api.get('/admin/address_sender', async (c) => {
|
||||
const { limit, offset } = c.req.query();
|
||||
if (!limit || limit < 0 || limit > 100) {
|
||||
return c.text("Invalid limit", 400)
|
||||
}
|
||||
if (!offset || offset < 0) {
|
||||
return c.text("Invalid offset", 400)
|
||||
}
|
||||
const { results } = await c.env.DB.prepare(
|
||||
`SELECT * FROM address_sender order by id desc limit ? offset ? `
|
||||
).bind(limit, offset).all();
|
||||
let count = 0;
|
||||
if (offset == 0) {
|
||||
const { count: addressCount } = await c.env.DB.prepare(
|
||||
`SELECT count(*) as count FROM address_sender`
|
||||
).first();
|
||||
count = addressCount;
|
||||
}
|
||||
return c.json({
|
||||
results: results,
|
||||
count: count
|
||||
})
|
||||
})
|
||||
|
||||
api.post('/admin/address_sender', async (c) => {
|
||||
let { address_id, balance, enabled } = await c.req.json();
|
||||
if (!address_id) {
|
||||
return c.text("Invalid address_id", 400)
|
||||
}
|
||||
enabled = enabled ? 1 : 0;
|
||||
const { success } = await c.env.DB.prepare(
|
||||
`UPDATE address_sender SET enabled = ?, balance = ? WHERE id = ? `
|
||||
).bind(enabled, balance, address_id).run();
|
||||
if (!success) {
|
||||
return c.text("Failed to update address sender", 500)
|
||||
}
|
||||
return c.json({
|
||||
success: success
|
||||
})
|
||||
})
|
||||
|
||||
api.get('/admin/statistics', async (c) => {
|
||||
const { count: mailCountV1 } = await c.env.DB.prepare(`
|
||||
SELECT count(*) as count FROM mails`
|
||||
|
||||
@@ -84,10 +84,15 @@ api.get('/api/settings', async (c) => {
|
||||
const { count: mailCountV1 } = await c.env.DB.prepare(
|
||||
`SELECT count(*) as count FROM mails where address = ?`
|
||||
).bind(address).first();
|
||||
const balance = await c.env.DB.prepare(
|
||||
`SELECT balance FROM address_sender
|
||||
where address = ? and enabled = 1`
|
||||
).bind(address).first("balance");
|
||||
return c.json({
|
||||
auto_reply: auto_reply,
|
||||
address: address,
|
||||
has_v1_mails: mailCountV1 > 0
|
||||
has_v1_mails: mailCountV1 && mailCountV1 > 0,
|
||||
send_balance: balance || 0,
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
142
worker/src/send_mail_api.js
Normal file
142
worker/src/send_mail_api.js
Normal file
@@ -0,0 +1,142 @@
|
||||
import { Hono } from 'hono'
|
||||
|
||||
const api = new Hono()
|
||||
|
||||
api.post('/api/requset_send_mail_access', async (c) => {
|
||||
const { address } = c.get("jwtPayload")
|
||||
if (!address) {
|
||||
return c.text("No address", 400)
|
||||
}
|
||||
try {
|
||||
const { success } = await c.env.DB.prepare(
|
||||
`INSERT INTO address_sender (address, enabled) VALUES (?, 0)`
|
||||
).bind(address).run();
|
||||
if (!success) {
|
||||
return c.text("Failed to request send mail access", 500)
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.message && e.message.includes("UNIQUE")) {
|
||||
return c.text("Already requested", 400)
|
||||
}
|
||||
return c.text("Failed to request send mail access", 500)
|
||||
}
|
||||
return c.json({ status: "ok" })
|
||||
})
|
||||
|
||||
|
||||
api.post('/api/send_mail', async (c) => {
|
||||
const { address } = c.get("jwtPayload")
|
||||
// check permission
|
||||
const balance = await c.env.DB.prepare(
|
||||
`SELECT balance FROM address_sender
|
||||
where address = ? and enabled = 1`
|
||||
).bind(address).first("balance");
|
||||
if (!balance || balance <= 0) {
|
||||
return c.text("No balance", 400);
|
||||
}
|
||||
let {
|
||||
from_name, to_mail, to_name,
|
||||
subject, content, is_html
|
||||
} = await c.req.json();
|
||||
if (!address) {
|
||||
return c.text("No address", 400)
|
||||
}
|
||||
if (!to_mail) {
|
||||
return c.text("Invalid to mail", 400)
|
||||
}
|
||||
from_name = from_name || address;
|
||||
to_name = to_name || to_mail;
|
||||
if (!subject) {
|
||||
return c.text("Invalid subject", 400)
|
||||
}
|
||||
if (!content) {
|
||||
return c.text("Invalid content", 400)
|
||||
}
|
||||
const body = JSON.stringify({
|
||||
"personalizations": [
|
||||
{
|
||||
"to": [{
|
||||
"email": to_mail,
|
||||
"name": to_name,
|
||||
}]
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"email": address,
|
||||
"name": from_name,
|
||||
},
|
||||
"subject": subject,
|
||||
"content": [{
|
||||
"type": is_html ? "text/html" : "text/plain",
|
||||
"value": content,
|
||||
}],
|
||||
});
|
||||
let send_request = new Request("https://api.mailchannels.net/tx/v1/send", {
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
"body": body,
|
||||
});
|
||||
const resp = await fetch(send_request);
|
||||
const respText = await resp.text();
|
||||
console.log(resp.status + " " + resp.statusText + ": " + respText);
|
||||
if (resp.status >= 300) {
|
||||
return c.text("Failed to send mail", 500)
|
||||
}
|
||||
// update balance
|
||||
try {
|
||||
const { success } = await c.env.DB.prepare(
|
||||
`UPDATE address_sender SET balance = balance - 1
|
||||
where address = ?`
|
||||
).bind(address).run();
|
||||
if (!success) {
|
||||
console.warn(`Failed to update balance for ${address}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(`Failed to update balance for ${address}`);
|
||||
}
|
||||
// save to sendbox
|
||||
try {
|
||||
const { success: success2 } = await c.env.DB.prepare(
|
||||
`INSERT INTO sendbox (address, raw) VALUES (?, ?)`
|
||||
).bind(address, body).run();
|
||||
if (!success2) {
|
||||
console.warn(`Failed to save to sendbox for ${address}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(`Failed to save to sendbox for ${address}`);
|
||||
}
|
||||
return c.json({ status: "ok" });
|
||||
})
|
||||
|
||||
api.get('/api/sendbox', async (c) => {
|
||||
const { address } = c.get("jwtPayload")
|
||||
if (!address) {
|
||||
return c.json({ "error": "No address" }, 400)
|
||||
}
|
||||
const { limit, offset } = c.req.query();
|
||||
if (!limit || limit < 0 || limit > 100) {
|
||||
return c.text("Invalid limit", 400)
|
||||
}
|
||||
if (!offset || offset < 0) {
|
||||
return c.text("Invalid offset", 400)
|
||||
}
|
||||
const { results } = await c.env.DB.prepare(
|
||||
`SELECT * FROM sendbox where address = ?
|
||||
order by id desc limit ? offset ?`
|
||||
).bind(address, limit, offset).all();
|
||||
let count = 0;
|
||||
if (offset == 0) {
|
||||
const { count: mailCount } = await c.env.DB.prepare(
|
||||
`SELECT count(*) as count FROM sendbox where address = ?`
|
||||
).bind(address).first();
|
||||
count = mailCount;
|
||||
}
|
||||
return c.json({
|
||||
results: results,
|
||||
count: count
|
||||
})
|
||||
})
|
||||
|
||||
export { api }
|
||||
@@ -5,6 +5,7 @@ import { jwt } from 'hono/jwt'
|
||||
import { api } from './router';
|
||||
import { api as adminApi } from './admin_api';
|
||||
import { api as apiV1 } from './api_v1';
|
||||
import { api as apiSendMail } from './send_mail_api'
|
||||
import { email } from './email';
|
||||
|
||||
const app = new Hono()
|
||||
@@ -40,6 +41,7 @@ app.use('/admin/*', async (c, next) => {
|
||||
app.route('/', api)
|
||||
app.route('/', adminApi)
|
||||
app.route('/', apiV1)
|
||||
app.route('/', apiSendMail)
|
||||
|
||||
app.all('/*', async c => c.text("Not Found", 404))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user