Compare commits
4 Commits
893fac1ff2
...
limit-mail
| Author | SHA1 | Date | |
|---|---|---|---|
| c109abc6f5 | |||
| d57037781e | |||
| e936fbc140 | |||
| a96aa6e073 |
@@ -1,12 +1,13 @@
|
||||
FROM node:20-alpine
|
||||
|
||||
# Set timezone to Asia/Shanghai FIRST
|
||||
# This ensures that any native modules compiled during npm install are linked correctly.
|
||||
RUN apk add --no-cache tzdata
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package*.json ./
|
||||
│
|
||||
# Set timezone to Asia/Shanghai │
|
||||
RUN apk add --no-cache tzdata │
|
||||
ENV TZ=Asia/Shanghai │
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
|
||||
@@ -30,7 +30,7 @@ app.get('/api/messages', async (req, res) => {
|
||||
|
||||
try {
|
||||
const [rows] = await db.execute(
|
||||
'SELECT id, sender, recipient, subject, body, received_at FROM emails WHERE recipient LIKE ? ORDER BY received_at DESC',
|
||||
'SELECT id, sender, recipient, subject, body, CAST(received_at AS CHAR) as received_at FROM emails WHERE recipient LIKE ? ORDER BY received_at DESC',
|
||||
[`%${recipient}%`]
|
||||
);
|
||||
res.json(rows);
|
||||
|
||||
@@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS emails (
|
||||
sender VARCHAR(255) NOT NULL,
|
||||
subject VARCHAR(512),
|
||||
body TEXT,
|
||||
received_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
received_at DATETIME,
|
||||
raw MEDIUMBLOB
|
||||
);
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ const logger = winston.createLogger({
|
||||
level: 'info',
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({
|
||||
format: 'YYYY-MM-DD HH:mm:ss'
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
tz: 'Asia/Shanghai'
|
||||
}),
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.splat(),
|
||||
@@ -17,10 +18,16 @@ const logger = winston.createLogger({
|
||||
]
|
||||
});
|
||||
|
||||
// 在非生产环境下,添加一个带有着色的控制台输出
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
logger.add(new winston.transports.Console({
|
||||
format: winston.format.combine(
|
||||
winston.format.colorize(),
|
||||
// 确保控制台日志也有正确格式和时区的时间戳
|
||||
winston.format.timestamp({
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
tz: 'Asia/Shanghai'
|
||||
}),
|
||||
winston.format.printf(({ level, message, timestamp, stack }) => {
|
||||
if (stack) {
|
||||
// 打印错误堆栈
|
||||
@@ -32,14 +39,4 @@ if (process.env.NODE_ENV !== 'production') {
|
||||
}));
|
||||
}
|
||||
|
||||
// 在文件日志中也使用更清晰的格式
|
||||
logger.transports.forEach(t => {
|
||||
if (t.name === 'file') {
|
||||
t.format = winston.format.combine(
|
||||
winston.format.timestamp(),
|
||||
winston.format.json()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = logger;
|
||||
|
||||
@@ -42,9 +42,14 @@ async function saveEmail(stream) {
|
||||
const subject = parsed.subject || 'No Subject';
|
||||
const body = parsed.text || (parsed.html || '');
|
||||
|
||||
// Manually create a timestamp for 'Asia/Shanghai' timezone
|
||||
const received_at = new Date().toLocaleString('sv-SE', {
|
||||
timeZone: 'Asia/Shanghai'
|
||||
});
|
||||
|
||||
const [result] = await db.execute(
|
||||
'INSERT INTO emails (recipient, sender, subject, body) VALUES (?, ?, ?, ?)',
|
||||
[recipient, sender, subject, body]
|
||||
'INSERT INTO emails (recipient, sender, subject, body, received_at) VALUES (?, ?, ?, ?, ?)',
|
||||
[recipient, sender, subject, body, received_at]
|
||||
);
|
||||
// const [result] = await db.execute(
|
||||
// 'INSERT INTO emails (recipient, sender, subject, body, raw) VALUES (?, ?, ?, ?, ?)',
|
||||
|
||||
@@ -17,6 +17,8 @@ services:
|
||||
image: mysql:8.0
|
||||
container_name: email-mysql
|
||||
restart: always
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
env_file:
|
||||
- compose.env
|
||||
volumes:
|
||||
|
||||
@@ -17,6 +17,8 @@ services:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/pull-image/mysql:8.0
|
||||
container_name: email-mysql
|
||||
restart: always
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
env_file:
|
||||
- compose.full.env
|
||||
volumes:
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
services:
|
||||
backend:
|
||||
build: ./backend
|
||||
build:
|
||||
context: ./backend
|
||||
args:
|
||||
HTTP_PROXY: "http://127.0.0.1:7899"
|
||||
HTTPS_PROXY: "http://127.0.0.1:7899"
|
||||
container_name: email-backend
|
||||
restart: always
|
||||
ports:
|
||||
|
||||
@@ -17,6 +17,8 @@ services:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/pull-image/mysql:8.0 # mysql:8.0
|
||||
container_name: email-mysql
|
||||
restart: always
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
env_file:
|
||||
- compose.env
|
||||
volumes:
|
||||
|
||||
@@ -24,6 +24,7 @@ const messages = {
|
||||
selectMail: '请从选择一封邮件查看',
|
||||
from: '发件人',
|
||||
to: '收件人',
|
||||
received_at: '收件时间',
|
||||
attachments: '附件',
|
||||
delete: '删除',
|
||||
clearInbox: '清空收件箱',
|
||||
@@ -68,6 +69,7 @@ const messages = {
|
||||
selectMail: 'Please select an email to view',
|
||||
from: 'From',
|
||||
to: 'To',
|
||||
received_at: 'Received At',
|
||||
attachments: 'Attachments',
|
||||
delete: 'Delete',
|
||||
clearInbox: 'Clear Inbox',
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<h3>{{ selectedMessage.subject }}</h3>
|
||||
<p class="from-line"><strong>{{ $t('home.from') }}:</strong> {{ selectedMessage.sender }}</p>
|
||||
<p><strong>{{ $t('home.to') }}:</strong> {{ selectedMessage.recipient }}</p>
|
||||
<p><strong>{{ $t('home.received_at') }}:</strong> {{ selectedMessage.received_at }}</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button @click="deleteMessage(selectedMessage.id)" :title="$t('home.delete')">
|
||||
|
||||
BIN
sample.png
BIN
sample.png
Binary file not shown.
|
Before Width: | Height: | Size: 204 KiB After Width: | Height: | Size: 103 KiB |
Reference in New Issue
Block a user