一阶段ok
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
{{define "admin_dashboard"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>管理后台 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox">返回邮箱</a>
|
||||
<a href="/admin" class="active">控制面板</a>
|
||||
<a href="/admin/domains">域名管理</a>
|
||||
<a href="/admin/users">用户管理</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h2 style="margin-bottom:24px;">管理后台</h2>
|
||||
<div style="margin-bottom:24px;">
|
||||
<div class="stat-card">
|
||||
<h3>{{.domainCount}}</h3>
|
||||
<p>域名数</p>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<h3>{{.userCount}}</h3>
|
||||
<p>用户数</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>快捷操作</h3>
|
||||
<p style="margin-top:12px;">
|
||||
<a href="/admin/domains/new" class="btn btn-primary">新增域名</a>
|
||||
<a href="/admin/users/new" class="btn btn-primary" style="margin-left:8px;">新增用户</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,46 @@
|
||||
{{define "admin_dns_hint"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>DNS配置 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox">返回邮箱</a>
|
||||
<a href="/admin">控制面板</a>
|
||||
<a href="/admin/domains" class="active">域名管理</a>
|
||||
<a href="/admin/users">用户管理</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<h2 style="margin-bottom:16px;">DNS 配置提示 — {{.domain.Name}}</h2>
|
||||
<p style="margin-bottom:16px;color:#7f8c8d;">请在您的 DNS 服务商处添加以下记录:</p>
|
||||
|
||||
<h4 style="margin-bottom:8px;">MX 记录</h4>
|
||||
<div class="dns-record">@ IN MX 10 mail.{{.domain.Name}}.</div>
|
||||
|
||||
<h4 style="margin-bottom:8px;">SPF 记录 (TXT)</h4>
|
||||
<div class="dns-record">@ IN TXT "v=spf1 mx -all"</div>
|
||||
|
||||
<h4 style="margin-bottom:8px;">DKIM 记录</h4>
|
||||
<div class="dns-record" style="color:#e67e22;">⚠️ 请在域名配置页配置 DKIM 私钥路径后,将自动生成 DKIM 公钥记录。</div>
|
||||
|
||||
<h4 style="margin-bottom:8px;">DMARC 记录</h4>
|
||||
<div class="dns-record">_dmarc.{{.domain.Name}}. IN TXT "v=DMARC1; p=none; rua=mailto:postmaster@{{.domain.Name}}"</div>
|
||||
|
||||
<div style="margin-top:24px;">
|
||||
<a href="/admin/domains" class="btn" style="background:#bdc3c7;color:#fff;">返回域名列表</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,56 @@
|
||||
{{define "admin_domain_form"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{if .isEdit}}编辑域名{{else}}新增域名{{end}} - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox">返回邮箱</a>
|
||||
<a href="/admin">控制面板</a>
|
||||
<a href="/admin/domains" class="active">域名管理</a>
|
||||
<a href="/admin/users">用户管理</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<h2 style="margin-bottom:16px;">{{if .isEdit}}编辑域名{{else}}新增域名{{end}}</h2>
|
||||
{{if .error}}<div class="alert alert-error">{{.error}}</div>{{end}}
|
||||
<form method="POST" action="{{if .isEdit}}/admin/domains/{{.domain.ID}}{{else}}/admin/domains{{end}}">
|
||||
<div class="form-group">
|
||||
<label>域名</label>
|
||||
<input type="text" name="name" required value="{{.domain.Name}}" placeholder="example.com">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>SMTP 端口</label>
|
||||
<input type="number" name="smtp_port" value="{{.domain.SmtpPort}}" placeholder="25">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>IMAP 端口</label>
|
||||
<input type="number" name="imap_port" value="{{.domain.ImapPort}}" placeholder="143">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>POP3 端口</label>
|
||||
<input type="number" name="pop3_port" value="{{.domain.Pop3Port}}" placeholder="110">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="checkbox" name="tls_enabled" {{if .domain.TlsEnabled}}checked{{end}}>
|
||||
启用 TLS
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">{{if .isEdit}}保存更改{{else}}创建域名{{end}}</button>
|
||||
<a href="/admin/domains" class="btn" style="margin-left:8px;background:#bdc3c7;color:#fff;">取消</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,79 @@
|
||||
{{define "admin_domains"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>域名管理 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox">返回邮箱</a>
|
||||
<a href="/admin">控制面板</a>
|
||||
<a href="/admin/domains" class="active">域名管理</a>
|
||||
<a href="/admin/users">用户管理</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;">
|
||||
<h2>域名列表</h2>
|
||||
<a href="/admin/domains/new" class="btn btn-primary">新增域名</a>
|
||||
</div>
|
||||
{{if not .domains}}
|
||||
<p style="color:#7f8c8d;text-align:center;padding:40px 0;">暂无域名</p>
|
||||
{{else}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>域名</th>
|
||||
<th>SMTP</th>
|
||||
<th>IMAP</th>
|
||||
<th>POP3</th>
|
||||
<th>TLS</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .domains}}
|
||||
<tr>
|
||||
<td>{{.ID}}</td>
|
||||
<td>{{.Name}}</td>
|
||||
<td>{{.SmtpPort}}</td>
|
||||
<td>{{.ImapPort}}</td>
|
||||
<td>{{.Pop3Port}}</td>
|
||||
<td>{{if .TlsEnabled}}✅{{else}}❌{{end}}</td>
|
||||
<td>
|
||||
<a href="/admin/domains/{{.ID}}/dns" class="btn btn-primary btn-sm">DNS</a>
|
||||
<form method="POST" action="/admin/domains/{{.ID}}/delete" style="display:inline;"
|
||||
onsubmit="return confirm('确定要删除域名 {{.Name}} 吗?删除域名将导致关联用户无法收发邮件!');">
|
||||
<button type="submit" class="btn btn-danger btn-sm">删除</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .totalPages}}
|
||||
<div class="pagination">
|
||||
{{if gt .page 1}}
|
||||
<a href="/admin/domains?page={{sub .page 1}}">上一页</a>
|
||||
{{end}}
|
||||
<span>第 {{.page}} / {{.totalPages}} 页</span>
|
||||
{{if lt .page .totalPages}}
|
||||
<a href="/admin/domains?page={{add .page 1}}">下一页</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,69 @@
|
||||
{{define "admin_user_form"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{if .isEdit}}编辑用户{{else}}新增用户{{end}} - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox">返回邮箱</a>
|
||||
<a href="/admin">控制面板</a>
|
||||
<a href="/admin/domains">域名管理</a>
|
||||
<a href="/admin/users" class="active">用户管理</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<h2 style="margin-bottom:16px;">{{if .isEdit}}编辑用户{{else}}新增用户{{end}}</h2>
|
||||
{{if .error}}<div class="alert alert-error">{{.error}}</div>{{end}}
|
||||
<form method="POST" action="{{if .isEdit}}/admin/users/{{.user.ID}}{{else}}/admin/users{{end}}">
|
||||
<div class="form-group">
|
||||
<label>用户名</label>
|
||||
<input type="text" name="username" required value="{{.user.Username}}" placeholder="username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{if .isEdit}}新密码(留空则不修改){{else}}密码{{end}}</label>
|
||||
<input type="password" name="password" {{if not .isEdit}}required{{end}} placeholder="请输入密码">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>域名</label>
|
||||
<select name="domain_id" required>
|
||||
<option value="">请选择域名</option>
|
||||
{{range .domains}}
|
||||
<option value="{{.ID}}" {{if eq .ID $.user.DomainID}}selected{{end}}>{{.Name}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>配额 (GB)</label>
|
||||
<input type="number" name="quota_gb" min="1" value="5" placeholder="5">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="checkbox" name="is_admin" {{if .user.IsAdmin}}checked{{end}}>
|
||||
管理员
|
||||
</label>
|
||||
</div>
|
||||
{{if .isEdit}}
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="checkbox" name="is_active" {{if .user.IsActive}}checked{{end}}>
|
||||
启用账户
|
||||
</label>
|
||||
</div>
|
||||
{{end}}
|
||||
<button type="submit" class="btn btn-primary">{{if .isEdit}}保存更改{{else}}创建用户{{end}}</button>
|
||||
<a href="/admin/users" class="btn" style="margin-left:8px;background:#bdc3c7;color:#fff;">取消</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,81 @@
|
||||
{{define "admin_users"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>用户管理 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox">返回邮箱</a>
|
||||
<a href="/admin">控制面板</a>
|
||||
<a href="/admin/domains">域名管理</a>
|
||||
<a href="/admin/users" class="active">用户管理</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;">
|
||||
<h2>用户列表</h2>
|
||||
<a href="/admin/users/new" class="btn btn-primary">新增用户</a>
|
||||
</div>
|
||||
{{if not .users}}
|
||||
<p style="color:#7f8c8d;text-align:center;padding:40px 0;">暂无用户</p>
|
||||
{{else}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>用户名</th>
|
||||
<th>域名ID</th>
|
||||
<th>配额</th>
|
||||
<th>已用</th>
|
||||
<th>状态</th>
|
||||
<th>管理员</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .users}}
|
||||
<tr>
|
||||
<td>{{.ID}}</td>
|
||||
<td>{{.Username}}</td>
|
||||
<td>{{.DomainID}}</td>
|
||||
<td>{{formatBytes .QuotaBytes}}</td>
|
||||
<td>{{formatBytes .UsedBytes}}</td>
|
||||
<td>{{if .IsActive}}✅{{else}}❌{{end}}</td>
|
||||
<td>{{if .IsAdmin}}✅{{else}}—{{end}}</td>
|
||||
<td>
|
||||
<a href="/admin/users/{{.ID}}/edit" class="btn btn-primary btn-sm">编辑</a>
|
||||
<form method="POST" action="/admin/users/{{.ID}}/delete" style="display:inline;"
|
||||
onsubmit="return confirm('确定要删除用户 {{.Username}} 吗?');">
|
||||
<button type="submit" class="btn btn-danger btn-sm">删除</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .totalPages}}
|
||||
<div class="pagination">
|
||||
{{if gt .page 1}}
|
||||
<a href="/admin/users?page={{sub .page 1}}">上一页</a>
|
||||
{{end}}
|
||||
<span>第 {{.page}} / {{.totalPages}} 页</span>
|
||||
{{if lt .page .totalPages}}
|
||||
<a href="/admin/users?page={{add .page 1}}">下一页</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,66 @@
|
||||
{{define "styles"}}
|
||||
<style>
|
||||
* { margin:0; padding:0; box-sizing:border-box; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background:#f5f5f5; color:#333; }
|
||||
.navbar { background:#2c3e50; padding:0 20px; height:50px; display:flex; align-items:center; }
|
||||
.navbar a { color:#ecf0f1; text-decoration:none; margin-right:20px; font-size:14px; }
|
||||
.navbar a:hover { color:#3498db; }
|
||||
.navbar .right { margin-left:auto; }
|
||||
.container { max-width:1200px; margin:20px auto; padding:0 20px; }
|
||||
.card { background:#fff; border-radius:8px; box-shadow:0 2px 4px rgba(0,0,0,0.1); padding:20px; margin-bottom:20px; }
|
||||
table { width:100%; border-collapse:collapse; }
|
||||
th, td { padding:10px 12px; text-align:left; border-bottom:1px solid #eee; }
|
||||
th { background:#f8f9fa; font-weight:600; }
|
||||
.btn { display:inline-block; padding:8px 16px; border-radius:4px; text-decoration:none; font-size:14px; cursor:pointer; border:none; }
|
||||
.btn-primary { background:#3498db; color:#fff; }
|
||||
.btn-primary:hover { background:#2980b9; }
|
||||
.btn-danger { background:#e74c3c; color:#fff; }
|
||||
.btn-danger:hover { background:#c0392b; }
|
||||
.btn-sm { padding:4px 10px; font-size:12px; }
|
||||
.alert { padding:12px 16px; border-radius:4px; margin-bottom:16px; }
|
||||
.alert-error { background:#fde8e8; color:#c0392b; }
|
||||
.alert-success { background:#e8fde8; color:#27ae60; }
|
||||
.form-group { margin-bottom:16px; }
|
||||
.form-group label { display:block; margin-bottom:6px; font-weight:600; }
|
||||
.form-group input, .form-group textarea, .form-group select { width:100%; padding:8px 12px; border:1px solid #ddd; border-radius:4px; font-size:14px; }
|
||||
.form-group input[type="checkbox"] { width:auto; }
|
||||
.unread { font-weight:bold; }
|
||||
.message-subject { color:#2c3e50; text-decoration:none; }
|
||||
.message-subject:hover { color:#3498db; }
|
||||
.sidebar { width:200px; float:left; }
|
||||
.sidebar a { display:block; padding:10px 15px; color:#2c3e50; text-decoration:none; border-radius:4px; margin-bottom:2px; }
|
||||
.sidebar a:hover, .sidebar a.active { background:#3498db; color:#fff; }
|
||||
.content { margin-left:220px; }
|
||||
.pagination { margin-top:16px; text-align:center; }
|
||||
.pagination a, .pagination span { display:inline-block; padding:6px 12px; margin:0 2px; border:1px solid #ddd; border-radius:4px; text-decoration:none; color:#333; }
|
||||
.pagination .current { background:#3498db; color:#fff; border-color:#3498db; }
|
||||
.mail-meta { color:#7f8c8d; font-size:13px; margin-bottom:8px; }
|
||||
.mail-body { line-height:1.6; margin-top:16px; padding-top:16px; border-top:1px solid #eee; }
|
||||
.attachment-list { margin-top:16px; padding-top:16px; border-top:1px solid #eee; }
|
||||
.attachment-item { display:inline-block; margin-right:12px; margin-bottom:8px; padding:6px 12px; background:#ecf0f1; border-radius:4px; font-size:13px; }
|
||||
.attachment-item a { color:#2c3e50; text-decoration:none; }
|
||||
.attachment-item a:hover { color:#3498db; }
|
||||
.badge { display:inline-block; padding:2px 8px; border-radius:10px; font-size:11px; font-weight:bold; }
|
||||
.badge-unread { background:#e74c3c; color:#fff; }
|
||||
.stat-card { display:inline-block; width:200px; padding:20px; margin-right:20px; background:#fff; border-radius:8px; box-shadow:0 2px 4px rgba(0,0,0,0.1); text-align:center; }
|
||||
.stat-card h3 { font-size:32px; color:#2c3e50; margin-bottom:4px; }
|
||||
.stat-card p { color:#7f8c8d; font-size:14px; }
|
||||
.dns-record { background:#f8f9fa; padding:12px 16px; border-radius:4px; margin-bottom:12px; font-family:monospace; font-size:13px; white-space:pre-wrap; }
|
||||
.clearfix::after { content:""; display:table; clear:both; }
|
||||
</style>
|
||||
{{end}}
|
||||
|
||||
{{define "navbar"}}
|
||||
{{if .currentUser}}
|
||||
<nav class="navbar">
|
||||
<a href="/inbox">MailGo</a>
|
||||
{{if .currentUser.IsAdmin}}<a href="/admin">管理后台</a>{{end}}
|
||||
<div class="right">
|
||||
<span style="color:#ecf0f1;font-size:13px;">{{.currentUser.Username}}@{{.currentUser.Domain.Name}}</span>
|
||||
<form method="POST" action="/logout" style="display:inline;">
|
||||
<a href="#" onclick="this.parentElement.submit(); return false;">退出</a>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -0,0 +1,55 @@
|
||||
{{define "compose"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>撰写邮件 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox" class="{{if eq .activeFolder `inbox`}}active{{end}}">收件箱</a>
|
||||
<a href="/drafts" class="{{if eq .activeFolder `drafts`}}active{{end}}">草稿箱</a>
|
||||
<a href="/sent" class="{{if eq .activeFolder `sent`}}active{{end}}">发件箱</a>
|
||||
<a href="/compose" class="{{if eq .activeFolder `compose`}}active{{end}}">撰写邮件</a>
|
||||
<a href="/settings" class="{{if eq .activeFolder `settings`}}active{{end}}">设置</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<h2 style="margin-bottom:16px;">撰写邮件</h2>
|
||||
{{if .error}}<div class="alert alert-error">{{.error}}</div>{{end}}
|
||||
<form method="POST" action="/compose" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label>收件人</label>
|
||||
<input type="email" name="to" required value="{{.to}}" placeholder="user@example.com">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>抄送(可选)</label>
|
||||
<input type="text" name="cc" value="{{.cc}}" placeholder="cc@example.com">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>主题</label>
|
||||
<input type="text" name="subject" value="{{.subject}}" placeholder="邮件主题">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>正文</label>
|
||||
<textarea name="body" rows="12" placeholder="请输入邮件内容..."></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>附件</label>
|
||||
<input type="file" name="attachments" multiple>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">发送邮件</button>
|
||||
<a href="/inbox" class="btn" style="margin-left:8px;">取消</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,74 @@
|
||||
{{define "drafts"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>草稿箱 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox" class="{{if eq .activeFolder `inbox`}}active{{end}}">收件箱</a>
|
||||
<a href="/drafts" class="{{if eq .activeFolder `drafts`}}active{{end}}">草稿箱</a>
|
||||
<a href="/sent" class="{{if eq .activeFolder `sent`}}active{{end}}">发件箱</a>
|
||||
<a href="/compose" class="{{if eq .activeFolder `compose`}}active{{end}}">撰写邮件</a>
|
||||
<a href="/settings" class="{{if eq .activeFolder `settings`}}active{{end}}">设置</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<h2 style="margin-bottom:16px;">草稿箱</h2>
|
||||
{{if not .messages}}
|
||||
<p style="color:#7f8c8d;text-align:center;padding:40px 0;">暂无草稿邮件</p>
|
||||
{{else}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:25%;">发件人/收件人</th>
|
||||
<th style="width:45%;">主题</th>
|
||||
<th style="width:20%;">时间</th>
|
||||
<th style="width:10%;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .messages}}
|
||||
<tr>
|
||||
<td>{{.ToAddr}}</td>
|
||||
<td>
|
||||
<a href="/drafts/{{.ID}}" class="message-subject">
|
||||
{{if .Subject}}{{.Subject}}{{else}}(无主题){{end}}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{.Date.Format "2006-01-02 15:04"}}</td>
|
||||
<td>
|
||||
<form method="POST" action="/mail/delete/{{.ID}}" style="display:inline;"
|
||||
onsubmit="return confirm('确定要删除这封邮件吗?');">
|
||||
<button type="submit" class="btn btn-danger btn-sm">删除</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .totalPages}}
|
||||
<div class="pagination">
|
||||
{{if gt .page 1}}
|
||||
<a href="/drafts?page={{sub .page 1}}">上一页</a>
|
||||
{{end}}
|
||||
<span>第 {{.page}} / {{.totalPages}} 页</span>
|
||||
{{if lt .page .totalPages}}
|
||||
<a href="/drafts?page={{add .page 1}}">下一页</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,75 @@
|
||||
{{define "inbox"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>收件箱 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox" class="{{if eq .activeFolder `inbox`}}active{{end}}">收件箱</a>
|
||||
<a href="/drafts" class="{{if eq .activeFolder `drafts`}}active{{end}}">草稿箱</a>
|
||||
<a href="/sent" class="{{if eq .activeFolder `sent`}}active{{end}}">发件箱</a>
|
||||
<a href="/compose" class="{{if eq .activeFolder `compose`}}active{{end}}">撰写邮件</a>
|
||||
<a href="/settings" class="{{if eq .activeFolder `settings`}}active{{end}}">设置</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<h2 style="margin-bottom:16px;">收件箱</h2>
|
||||
{{if not .messages}}
|
||||
<p style="color:#7f8c8d;text-align:center;padding:40px 0;">暂无邮件</p>
|
||||
{{else}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:25%;">发件人</th>
|
||||
<th style="width:45%;">主题</th>
|
||||
<th style="width:20%;">时间</th>
|
||||
<th style="width:10%;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .messages}}
|
||||
<tr class="{{if not .IsRead}}unread{{end}}">
|
||||
<td>{{.FromAddr}}</td>
|
||||
<td>
|
||||
<a href="/inbox/{{.ID}}" class="message-subject">
|
||||
{{if .Subject}}{{.Subject}}{{else}}(无主题){{end}}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{.Date.Format "2006-01-02 15:04"}}</td>
|
||||
<td>
|
||||
{{if not .IsRead}}
|
||||
<form method="POST" action="/mail/read/{{.ID}}" style="display:inline;">
|
||||
<button type="submit" class="btn btn-primary btn-sm">已读</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .totalPages}}
|
||||
<div class="pagination">
|
||||
{{if gt .page 1}}
|
||||
<a href="/inbox?page={{sub .page 1}}">上一页</a>
|
||||
{{end}}
|
||||
<span>第 {{.page}} / {{.totalPages}} 页</span>
|
||||
{{if lt .page .totalPages}}
|
||||
<a href="/inbox?page={{add .page 1}}">下一页</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,33 @@
|
||||
{{define "login"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>登录 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div style="max-width:400px;margin:80px auto;">
|
||||
<div class="card">
|
||||
<h2 style="text-align:center;margin-bottom:24px;">MailGo 登录</h2>
|
||||
{{if .error}}<div class="alert alert-error">{{.error}}</div>{{end}}
|
||||
<form method="POST" action="/login">
|
||||
<div class="form-group">
|
||||
<label>邮箱地址</label>
|
||||
<input type="email" name="email" required autofocus placeholder="admin@example.com">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>密码</label>
|
||||
<input type="password" name="password" required placeholder="请输入密码">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="width:100%;">登录</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,74 @@
|
||||
{{define "sent"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>发件箱 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox" class="{{if eq .activeFolder `inbox`}}active{{end}}">收件箱</a>
|
||||
<a href="/drafts" class="{{if eq .activeFolder `drafts`}}active{{end}}">草稿箱</a>
|
||||
<a href="/sent" class="{{if eq .activeFolder `sent`}}active{{end}}">发件箱</a>
|
||||
<a href="/compose" class="{{if eq .activeFolder `compose`}}active{{end}}">撰写邮件</a>
|
||||
<a href="/settings" class="{{if eq .activeFolder `settings`}}active{{end}}">设置</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<h2 style="margin-bottom:16px;">发件箱</h2>
|
||||
{{if not .messages}}
|
||||
<p style="color:#7f8c8d;text-align:center;padding:40px 0;">暂无已发送邮件</p>
|
||||
{{else}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:25%;">收件人</th>
|
||||
<th style="width:45%;">主题</th>
|
||||
<th style="width:20%;">时间</th>
|
||||
<th style="width:10%;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .messages}}
|
||||
<tr>
|
||||
<td>{{.ToAddr}}</td>
|
||||
<td>
|
||||
<a href="/sent/{{.ID}}" class="message-subject">
|
||||
{{if .Subject}}{{.Subject}}{{else}}(无主题){{end}}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{.Date.Format "2006-01-02 15:04"}}</td>
|
||||
<td>
|
||||
<form method="POST" action="/mail/delete/{{.ID}}" style="display:inline;"
|
||||
onsubmit="return confirm('确定要删除这封邮件吗?');">
|
||||
<button type="submit" class="btn btn-danger btn-sm">删除</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .totalPages}}
|
||||
<div class="pagination">
|
||||
{{if gt .page 1}}
|
||||
<a href="/sent?page={{sub .page 1}}">上一页</a>
|
||||
{{end}}
|
||||
<span>第 {{.page}} / {{.totalPages}} 页</span>
|
||||
{{if lt .page .totalPages}}
|
||||
<a href="/sent?page={{add .page 1}}">下一页</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,48 @@
|
||||
{{define "settings"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>设置 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox" class="{{if eq .activeFolder `inbox`}}active{{end}}">收件箱</a>
|
||||
<a href="/drafts" class="{{if eq .activeFolder `drafts`}}active{{end}}">草稿箱</a>
|
||||
<a href="/sent" class="{{if eq .activeFolder `sent`}}active{{end}}">发件箱</a>
|
||||
<a href="/compose" class="{{if eq .activeFolder `compose`}}active{{end}}">撰写邮件</a>
|
||||
<a href="/settings" class="{{if eq .activeFolder `settings`}}active{{end}}">设置</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<h2 style="margin-bottom:16px;">设置</h2>
|
||||
{{if .error}}<div class="alert alert-error">{{.error}}</div>{{end}}
|
||||
{{if .success}}<div class="alert alert-success">{{.success}}</div>{{end}}
|
||||
<h3 style="margin-bottom:12px;">修改密码</h3>
|
||||
<form method="POST" action="/settings">
|
||||
<div class="form-group">
|
||||
<label>当前密码</label>
|
||||
<input type="password" name="old_password" required placeholder="请输入当前密码">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>新密码</label>
|
||||
<input type="password" name="new_password" required placeholder="请输入新密码">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>确认新密码</label>
|
||||
<input type="password" name="confirm_password" required placeholder="请再次输入新密码">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">修改密码</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,64 @@
|
||||
{{define "view"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>查看邮件 - MailGo</title>
|
||||
{{template "styles" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "navbar" .}}
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<div class="sidebar">
|
||||
<a href="/inbox" class="{{if eq .activeFolder `inbox`}}active{{end}}">收件箱</a>
|
||||
<a href="/drafts" class="{{if eq .activeFolder `drafts`}}active{{end}}">草稿箱</a>
|
||||
<a href="/sent" class="{{if eq .activeFolder `sent`}}active{{end}}">发件箱</a>
|
||||
<a href="/compose" class="{{if eq .activeFolder `compose`}}active{{end}}">撰写邮件</a>
|
||||
<a href="/settings" class="{{if eq .activeFolder `settings`}}active{{end}}">设置</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div style="margin-bottom:16px;">
|
||||
<a href="javascript:history.back()" class="btn" style="background:#bdc3c7;color:#fff;">返回</a>
|
||||
</div>
|
||||
<h2>{{if .message.Subject}}{{.message.Subject}}{{else}}(无主题){{end}}</h2>
|
||||
<div class="mail-meta" style="margin-top:12px;">
|
||||
<p><strong>发件人:</strong> {{.message.FromAddr}}</p>
|
||||
<p><strong>收件人:</strong> {{.message.ToAddr}}</p>
|
||||
{{if .message.CcAddr}}<p><strong>抄送:</strong> {{.message.CcAddr}}</p>{{end}}
|
||||
<p><strong>时间:</strong> {{.message.Date.Format "2006-01-02 15:04:05"}}</p>
|
||||
</div>
|
||||
<div class="mail-body">
|
||||
{{if .message.HtmlBody}}
|
||||
{{.message.HtmlBody | safeHTML}}
|
||||
{{else}}
|
||||
<pre style="white-space:pre-wrap;font-family:inherit;">{{.message.TextBody}}</pre>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .attachments}}
|
||||
<div class="attachment-list">
|
||||
<h4 style="margin-bottom:8px;">附件</h4>
|
||||
{{range .attachments}}
|
||||
<div class="attachment-item">
|
||||
📎 <a href="/attachment/{{.ID}}">{{.FileName}}</a>
|
||||
<span style="color:#7f8c8d;font-size:12px;">({{formatBytes .FileSize}})</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
<div style="margin-top:20px;padding-top:16px;border-top:1px solid #eee;">
|
||||
<form method="POST" action="/mail/delete/{{.message.ID}}" style="display:inline;"
|
||||
onsubmit="return confirm('确定要删除这封邮件吗?');">
|
||||
<button type="submit" class="btn btn-danger">删除邮件</button>
|
||||
</form>
|
||||
<a href="/compose?to={{.message.FromAddr}}&subject={{if .message.Subject}}Re: {{.message.Subject}}{{end}}" class="btn btn-primary" style="margin-left:8px;">回复</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user