An OpenCloud web extension that integrates Roundcube webmail into OpenCloud via iframe with HMAC-signed autologin.
Users can configure one or more mail accounts in their OpenCloud account settings and access their mailbox directly from the OpenCloud web interface. Authentication to Roundcube is handled transparently through a signed autologin URL, so users only need to enter their IMAP credentials once.
- Roundcube webmail embedded as an iframe inside OpenCloud
- HMAC-SHA256 signed autologin URLs with expiring tokens (60s TTL)
- Support for multiple Roundcube instances (configured by the administrator)
- Users can manage multiple mail accounts per instance
- IMAP passwords are encrypted in the browser using AES-256-GCM before being stored in localStorage
- OpenCloud instance with web extension support
- One or more Roundcube instances with the
autologin.phpendpoint deployed - A shared secret configured on both the OpenCloud plugin and the Roundcube side
- Node.js and pnpm
pnpm install
pnpm buildThis produces the dist/ directory containing:
dist/
manifest.json
js/
web-app-webmail.js
chunks/
index.mjs
WebmailView.mjs
Copy the contents of the dist/ directory to your OpenCloud web assets directory:
<opencloud-data>/web/assets/apps/webmail/
For example, if OpenCloud stores its data at /var/lib/opencloud:
mkdir -p /var/lib/opencloud/web/assets/apps/webmail
cp -r dist/* /var/lib/opencloud/web/assets/apps/webmail/Restart OpenCloud after installing or updating the plugin.
The plugin is configured through the manifest.json file in the plugin directory. To add Roundcube instances, add a config section with an instances array:
{
"entrypoint": "js/web-app-webmail.js",
"config": {
"instances": [
{
"id": "main-mailserver",
"label": "Company Mail",
"roundcubeUrl": "https://mail.example.com",
"sharedSecret": "your-shared-secret-here"
}
]
}
}| Property | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Unique identifier for this instance |
label |
string | yes | Display name shown to users in the account settings |
roundcubeUrl |
string (URL) | yes | Base URL of the Roundcube installation |
sharedSecret |
string | yes | Shared secret used for HMAC signing (must match the Roundcube autologin.php configuration) |
You can configure multiple Roundcube instances. Users will be able to select which instance to use when adding a mail account:
{
"entrypoint": "js/web-app-webmail.js",
"config": {
"instances": [
{
"id": "internal",
"label": "Internal Mail",
"roundcubeUrl": "https://mail-internal.example.com",
"sharedSecret": "secret-for-internal"
},
{
"id": "external",
"label": "External Mail",
"roundcubeUrl": "https://mail-external.example.com",
"sharedSecret": "secret-for-external"
}
]
}
}- The user adds a mail account in their OpenCloud account settings (label, IMAP username, IMAP password, Roundcube instance).
- When the user opens the webmail view, the plugin builds a signed autologin URL:
- A JSON payload containing the user ID, account ID, IMAP credentials, and an expiration timestamp is base64url-encoded.
- The payload is signed with HMAC-SHA256 using the shared secret.
- The resulting URL points to
<roundcubeUrl>/autologin.php?data=...&sig=...&ts=....
- The Roundcube
autologin.phpendpoint verifies the signature and timestamp, then logs the user in.
IMAP passwords are never stored in plain text in the browser. Before being written to localStorage, each password is encrypted using:
- AES-256-GCM for authenticated encryption
- PBKDF2 with SHA-256 and 100,000 iterations for key derivation
- A random 16-byte salt (generated once per OpenCloud user, stored in localStorage keyed by user ID)
- A random 12-byte IV per encryption operation
The encryption key is derived from the OpenCloud user ID and the salt. This means the encrypted passwords are bound to the specific user session and browser.
Note: This encryption protects credentials at rest in the browser storage (e.g. against casual inspection or data exports). It does not protect against JavaScript running in the same origin (e.g. XSS attacks or malicious browser extensions), since the key material is also accessible in the browser context.
roundcube-opencloud-plugin — Roundcube plugin that lets each user connect their personal OpenCloud Space directly from within Roundcube: save email attachments to the cloud or attach files from it.
Article: From Seafile to OpenCloud: Building a Self-Hosted Webmail & Cloud Integration on Kubernetes — background, motivation, and full setup walkthrough.
This extension requires an autologin.php endpoint on the Roundcube side. The file is included in this repository at dev/docker/roundcube/autologin.php.
Installation:
-
Copy
autologin.phpinto the Roundcube public web root (the directory containingindex.php):cp dev/docker/roundcube/autologin.php /var/www/roundcube/public_html/autologin.php
The exact path depends on your Roundcube installation. Common locations are
/var/www/roundcube/public_html/,/var/www/html/, or/usr/share/roundcube/. -
Edit
autologin.phpand setSHARED_SECRETto a strong random value:define('SHARED_SECRET', 'your-strong-random-secret');
This secret must match the
sharedSecretconfigured in the OpenCloudmanifest.jsonfor the corresponding instance. -
Verify that the endpoint is reachable at
https://your-roundcube-url/autologin.php.
By default, Roundcube's session_lifetime is set to 10 minutes. Since Roundcube runs inside an iframe, an expired session will show the Roundcube login page within the iframe instead of the expected mailbox view.
To avoid this, increase the session_lifetime in your Roundcube config/config.inc.php:
// Session lifetime in minutes (default: 10)
// Set to a high value since session management is handled by OpenCloud
$config['session_lifetime'] = 600; // 10 hourspnpm build:wThis starts Vite in watch mode for development.
pnpm lint
pnpm format:check
pnpm format:writepnpm check:typespnpm test:unitApache-2.0