From 0ec0fa2cfda427cd4eff9c6da8df2705c7ed0903 Mon Sep 17 00:00:00 2001
From: okxlin <61420215+okxlin@users.noreply.github.com>
Date: Sun, 28 Jun 2026 15:05:17 +0800
Subject: [PATCH] feat: add Roundcube app (#4365)
---
apps/roundcube/README.md | 64 ++++++++
apps/roundcube/data.yml | 31 ++++
apps/roundcube/latest/.env.sample | 11 ++
apps/roundcube/latest/data.yml | 167 +++++++++++++++++++++
apps/roundcube/latest/docker-compose.yml | 37 +++++
apps/roundcube/latest/scripts/init.sh | 7 +
apps/roundcube/latest/scripts/uninstall.sh | 2 +
apps/roundcube/latest/scripts/upgrade.sh | 3 +
apps/roundcube/logo.png | Bin 0 -> 3090 bytes
apps/roundcube/source-evidence.json | 14 ++
10 files changed, 336 insertions(+)
create mode 100644 apps/roundcube/README.md
create mode 100644 apps/roundcube/data.yml
create mode 100644 apps/roundcube/latest/.env.sample
create mode 100644 apps/roundcube/latest/data.yml
create mode 100644 apps/roundcube/latest/docker-compose.yml
create mode 100755 apps/roundcube/latest/scripts/init.sh
create mode 100755 apps/roundcube/latest/scripts/uninstall.sh
create mode 100755 apps/roundcube/latest/scripts/upgrade.sh
create mode 100644 apps/roundcube/logo.png
create mode 100644 apps/roundcube/source-evidence.json
diff --git a/apps/roundcube/README.md b/apps/roundcube/README.md
new file mode 100644
index 000000000..6e330809b
--- /dev/null
+++ b/apps/roundcube/README.md
@@ -0,0 +1,64 @@
+# Roundcube
+
+## 产品介绍
+Roundcube 是一个开源 Webmail 客户端,可通过浏览器连接已有的 IMAP/SMTP 邮件服务器收发邮件。
+
+## 主要功能
+- 通过浏览器访问 IMAP 邮箱
+- 使用外部 SMTP 服务器发送邮件
+- 支持内置插件、主题和自定义配置
+- 使用本地 SQLite 保存 Webmail 元数据
+
+## 访问说明
+安装后通过 `http://<服务器 IP>:18090` 访问,实际端口以安装表单中的 `PANEL_APP_PORT_HTTP` 为准。
+
+## Introduction
+Roundcube is an open source Webmail client for accessing an existing IMAP and SMTP mail server from a browser.
+
+## Features
+- Browser-based IMAP mail access
+- Send mail through an external SMTP server
+- Built-in plugins, themes and custom configuration support
+- Local SQLite metadata storage
+
+## 部署说明
+- 本应用使用官方 Docker 镜像 `roundcube/roundcubemail:1.7.1-apache-nonroot`。
+- 应用分类:邮件服务。
+- 支持架构:amd64、arm64。
+- Roundcube 只是 Webmail 客户端,不包含邮件服务器。请先准备可用的 IMAP/SMTP 服务,例如已有邮箱服务或应用商店中的 Maddy Mail Server。
+
+## 端口
+| 变量 | 说明 | 默认值 | 必填 |
+| --- | --- | --- | --- |
+| PANEL_APP_PORT_HTTP | Web 访问端口 | 18090 | 是 |
+
+## 数据持久化
+| 变量 | 说明 | 默认值 | 必填 |
+| --- | --- | --- | --- |
+| APP_DATA_DIR | SQLite 数据库、自定义配置和 Enigma 插件数据目录 | ./data | 是 |
+
+升级或迁移前,请先在 1Panel 中备份上述数据目录。
+
+## 参数说明
+| 变量 | 说明 | 默认值 | 必填 |
+| --- | --- | --- | --- |
+| ROUNDCUBEMAIL_DEFAULT_HOST | IMAP 主机,可使用 `tls://` 或 `ssl://` 前缀 | ssl://mail.example.com | 是 |
+| ROUNDCUBEMAIL_DEFAULT_PORT | IMAP 端口 | 993 | 是 |
+| ROUNDCUBEMAIL_SMTP_SERVER | SMTP 主机,可使用 `tls://` 或 `ssl://` 前缀 | tls://mail.example.com | 是 |
+| ROUNDCUBEMAIL_SMTP_PORT | SMTP 端口 | 587 | 是 |
+| ROUNDCUBEMAIL_USERNAME_DOMAIN | 登录用户名自动补全域名,留空表示不补全 | 空 | 否 |
+| ROUNDCUBEMAIL_REQUEST_PATH | 反向代理子路径 | / | 是 |
+| ROUNDCUBEMAIL_PLUGINS | 启用的内置插件列表 | archive,zipdownload | 是 |
+| ROUNDCUBEMAIL_DES_KEY | Roundcube 加密密钥,安装后不要随意修改 | 随机生成 | 是 |
+
+## 使用说明
+- 如果 IMAP/SMTP 使用隐式 TLS,主机通常写成 `ssl://mail.example.com`,端口使用 `993` 或 `465`。
+- 如果 IMAP/SMTP 使用 STARTTLS,主机通常写成 `tls://mail.example.com`,端口使用 `143` 或 `587`。
+- `ROUNDCUBEMAIL_DES_KEY` 会影响 Roundcube 保存的加密数据,迁移或重建容器时应保持不变。
+- 自定义 Roundcube 配置可放入数据目录的 `config` 子目录,文件名需以 `.php` 结尾。
+
+## 参考资料
+- 官网:
+- 项目仓库:
+- 官方 Docker 镜像文档:
+- 官方镜像:
diff --git a/apps/roundcube/data.yml b/apps/roundcube/data.yml
new file mode 100644
index 000000000..c6d2d8b5d
--- /dev/null
+++ b/apps/roundcube/data.yml
@@ -0,0 +1,31 @@
+name: Roundcube
+tags:
+ - 邮件服务
+title: 现代 Webmail 客户端
+description: 现代 Webmail 客户端
+additionalProperties:
+ key: roundcube
+ name: Roundcube
+ tags:
+ - Email
+ shortDescZh: 现代 Webmail 客户端
+ shortDescEn: Modern Webmail client
+ description:
+ en: A browser-based IMAP Webmail client for existing mail servers.
+ zh: 面向已有邮件服务器的浏览器 IMAP Webmail 客户端。
+ zh-Hant: 面向既有郵件伺服器的瀏覽器 IMAP Webmail 用戶端。
+ ja: 既存のメールサーバー向けのブラウザベース IMAP Webmail クライアントです。
+ ko: 기존 메일 서버용 브라우저 기반 IMAP Webmail 클라이언트입니다.
+ ru: Браузерный IMAP Webmail-клиент для существующих почтовых серверов.
+ ms: Klien Webmail IMAP berasaskan pelayar untuk pelayan mel sedia ada.
+ pt-br: Cliente Webmail IMAP baseado em navegador para servidores de e-mail existentes.
+ type: website
+ crossVersionUpdate: false
+ limit: 0
+ recommend: 0
+ website: https://roundcube.net/
+ github: https://github.com/roundcube/roundcubemail
+ document: https://github.com/roundcube/roundcubemail-docker
+ architectures:
+ - amd64
+ - arm64
diff --git a/apps/roundcube/latest/.env.sample b/apps/roundcube/latest/.env.sample
new file mode 100644
index 000000000..aa77398f2
--- /dev/null
+++ b/apps/roundcube/latest/.env.sample
@@ -0,0 +1,11 @@
+PANEL_APP_PORT_HTTP=18090
+APP_DATA_DIR=./data
+ROUNDCUBEMAIL_DEFAULT_HOST=ssl://mail.example.com
+ROUNDCUBEMAIL_DEFAULT_PORT=993
+ROUNDCUBEMAIL_SMTP_SERVER=tls://mail.example.com
+ROUNDCUBEMAIL_SMTP_PORT=587
+ROUNDCUBEMAIL_USERNAME_DOMAIN=
+ROUNDCUBEMAIL_REQUEST_PATH=/
+ROUNDCUBEMAIL_PLUGINS=archive,zipdownload
+ROUNDCUBEMAIL_DES_KEY=roundcube_des_key_change
+CONTAINER_NAME=roundcube
diff --git a/apps/roundcube/latest/data.yml b/apps/roundcube/latest/data.yml
new file mode 100644
index 000000000..468ea82ea
--- /dev/null
+++ b/apps/roundcube/latest/data.yml
@@ -0,0 +1,167 @@
+additionalProperties:
+ formFields:
+ - default: 18090
+ edit: true
+ envKey: PANEL_APP_PORT_HTTP
+ labelEn: Web Port
+ labelZh: Web 端口
+ label:
+ en: Web Port
+ zh: Web 端口
+ zh-Hant: Web 埠
+ ja: Web ポート
+ ko: Web 포트
+ ru: Web-порт
+ ms: Port Web
+ pt-br: Porta Web
+ required: true
+ rule: paramPort
+ type: number
+ - default: ./data
+ edit: true
+ envKey: APP_DATA_DIR
+ labelEn: Data Directory
+ labelZh: 数据目录
+ label:
+ en: Data Directory
+ zh: 数据目录
+ zh-Hant: 資料目錄
+ ja: データディレクトリ
+ ko: 데이터 디렉터리
+ ru: Каталог данных
+ ms: Direktori data
+ pt-br: Diretorio de dados
+ required: true
+ type: text
+ - default: ssl://mail.example.com
+ edit: true
+ envKey: ROUNDCUBEMAIL_DEFAULT_HOST
+ labelEn: IMAP Host
+ labelZh: IMAP 主机
+ label:
+ en: IMAP Host
+ zh: IMAP 主机
+ zh-Hant: IMAP 主機
+ ja: IMAP ホスト
+ ko: IMAP 호스트
+ ru: IMAP-хост
+ ms: Hos IMAP
+ pt-br: Host IMAP
+ required: true
+ type: text
+ - default: 993
+ edit: true
+ envKey: ROUNDCUBEMAIL_DEFAULT_PORT
+ labelEn: IMAP Port
+ labelZh: IMAP 端口
+ label:
+ en: IMAP Port
+ zh: IMAP 端口
+ zh-Hant: IMAP 埠
+ ja: IMAP ポート
+ ko: IMAP 포트
+ ru: IMAP-порт
+ ms: Port IMAP
+ pt-br: Porta IMAP
+ required: true
+ rule: paramPort
+ type: number
+ - default: tls://mail.example.com
+ edit: true
+ envKey: ROUNDCUBEMAIL_SMTP_SERVER
+ labelEn: SMTP Host
+ labelZh: SMTP 主机
+ label:
+ en: SMTP Host
+ zh: SMTP 主机
+ zh-Hant: SMTP 主機
+ ja: SMTP ホスト
+ ko: SMTP 호스트
+ ru: SMTP-хост
+ ms: Hos SMTP
+ pt-br: Host SMTP
+ required: true
+ type: text
+ - default: 587
+ edit: true
+ envKey: ROUNDCUBEMAIL_SMTP_PORT
+ labelEn: SMTP Port
+ labelZh: SMTP 端口
+ label:
+ en: SMTP Port
+ zh: SMTP 端口
+ zh-Hant: SMTP 埠
+ ja: SMTP ポート
+ ko: SMTP 포트
+ ru: SMTP-порт
+ ms: Port SMTP
+ pt-br: Porta SMTP
+ required: true
+ rule: paramPort
+ type: number
+ - default: ""
+ edit: true
+ envKey: ROUNDCUBEMAIL_USERNAME_DOMAIN
+ labelEn: Login Domain
+ labelZh: 登录域名
+ label:
+ en: Login Domain
+ zh: 登录域名
+ zh-Hant: 登入網域
+ ja: ログインドメイン
+ ko: 로그인 도메인
+ ru: Домен входа
+ ms: Domain log masuk
+ pt-br: Dominio de login
+ required: false
+ type: text
+ - default: /
+ edit: true
+ envKey: ROUNDCUBEMAIL_REQUEST_PATH
+ labelEn: Request Path
+ labelZh: 请求路径
+ label:
+ en: Request Path
+ zh: 请求路径
+ zh-Hant: 請求路徑
+ ja: リクエストパス
+ ko: 요청 경로
+ ru: Путь запроса
+ ms: Laluan permintaan
+ pt-br: Caminho de requisicao
+ required: true
+ type: text
+ - default: archive,zipdownload
+ edit: true
+ envKey: ROUNDCUBEMAIL_PLUGINS
+ labelEn: Built-in Plugins
+ labelZh: 内置插件
+ label:
+ en: Built-in Plugins
+ zh: 内置插件
+ zh-Hant: 內建外掛
+ ja: 組み込みプラグイン
+ ko: 기본 제공 플러그인
+ ru: Встроенные плагины
+ ms: Pemalam terbina dalam
+ pt-br: Plugins integrados
+ required: true
+ type: text
+ - default: roundcube_des_key_change
+ edit: true
+ envKey: ROUNDCUBEMAIL_DES_KEY
+ labelEn: Encryption Key
+ labelZh: 加密密钥
+ label:
+ en: Encryption Key
+ zh: 加密密钥
+ zh-Hant: 加密金鑰
+ ja: 暗号化キー
+ ko: 암호화 키
+ ru: Ключ шифрования
+ ms: Kunci penyulitan
+ pt-br: Chave de criptografia
+ random: true
+ required: true
+ rule: paramComplexity
+ type: password
diff --git a/apps/roundcube/latest/docker-compose.yml b/apps/roundcube/latest/docker-compose.yml
new file mode 100644
index 000000000..684953d0c
--- /dev/null
+++ b/apps/roundcube/latest/docker-compose.yml
@@ -0,0 +1,37 @@
+services:
+ roundcube:
+ image: "roundcube/roundcubemail:1.7.1-apache-nonroot"
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:8000"
+ environment:
+ - ROUNDCUBEMAIL_DB_TYPE=sqlite
+ - ROUNDCUBEMAIL_DB_DIR=/var/roundcube/db
+ - ROUNDCUBEMAIL_DB_NAME=roundcube
+ - ROUNDCUBEMAIL_DEFAULT_HOST=${ROUNDCUBEMAIL_DEFAULT_HOST}
+ - ROUNDCUBEMAIL_DEFAULT_PORT=${ROUNDCUBEMAIL_DEFAULT_PORT}
+ - ROUNDCUBEMAIL_SMTP_SERVER=${ROUNDCUBEMAIL_SMTP_SERVER}
+ - ROUNDCUBEMAIL_SMTP_PORT=${ROUNDCUBEMAIL_SMTP_PORT}
+ - ROUNDCUBEMAIL_USERNAME_DOMAIN=${ROUNDCUBEMAIL_USERNAME_DOMAIN}
+ - ROUNDCUBEMAIL_REQUEST_PATH=${ROUNDCUBEMAIL_REQUEST_PATH}
+ - ROUNDCUBEMAIL_PLUGINS=${ROUNDCUBEMAIL_PLUGINS}
+ - ROUNDCUBEMAIL_SKIN=elastic
+ - ROUNDCUBEMAIL_DES_KEY=${ROUNDCUBEMAIL_DES_KEY}
+ volumes:
+ - "${APP_DATA_DIR}/db:/var/roundcube/db"
+ - "${APP_DATA_DIR}/config:/var/roundcube/config:ro"
+ - "${APP_DATA_DIR}/enigma:/var/roundcube/enigma"
+ healthcheck:
+ test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8000/ >/dev/null || exit 1"]
+ interval: 10s
+ timeout: 5s
+ retries: 10
+ labels:
+ createdBy: "Apps"
+
+networks:
+ 1panel-network:
+ external: true
diff --git a/apps/roundcube/latest/scripts/init.sh b/apps/roundcube/latest/scripts/init.sh
new file mode 100755
index 000000000..0baabc162
--- /dev/null
+++ b/apps/roundcube/latest/scripts/init.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+DATA_DIR="${APP_DATA_DIR:-./data}"
+mkdir -p "${DATA_DIR}/db" "${DATA_DIR}/config" "${DATA_DIR}/enigma"
+chown -R 33:33 "${DATA_DIR}/db" "${DATA_DIR}/enigma" 2>/dev/null || true
+chmod 755 "${DATA_DIR}/config" 2>/dev/null || true
diff --git a/apps/roundcube/latest/scripts/uninstall.sh b/apps/roundcube/latest/scripts/uninstall.sh
new file mode 100755
index 000000000..ab8a8d674
--- /dev/null
+++ b/apps/roundcube/latest/scripts/uninstall.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+docker-compose down --volumes
diff --git a/apps/roundcube/latest/scripts/upgrade.sh b/apps/roundcube/latest/scripts/upgrade.sh
new file mode 100755
index 000000000..9879df4c3
--- /dev/null
+++ b/apps/roundcube/latest/scripts/upgrade.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+set -euo pipefail
+exit 0
diff --git a/apps/roundcube/logo.png b/apps/roundcube/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..b37854589b8df9649ebc8e28c64d191380f8f9af
GIT binary patch
literal 3090
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