{"id":28690576,"url":"https://github.com/thunderbird/thunderbird-accounts","last_synced_at":"2026-05-01T01:03:14.749Z","repository":{"id":262698098,"uuid":"885573924","full_name":"thunderbird/thunderbird-accounts","owner":"thunderbird","description":"Thunderbird Accounts","archived":false,"fork":false,"pushed_at":"2025-06-12T19:19:06.000Z","size":5578,"stargazers_count":6,"open_issues_count":26,"forks_count":1,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-06-12T20:48:48.138Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thunderbird.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-11-08T21:23:12.000Z","updated_at":"2025-06-12T17:59:44.000Z","dependencies_parsed_at":"2024-12-05T20:18:52.820Z","dependency_job_id":"23548267-9771-43af-b8ea-b6864fe99db7","html_url":"https://github.com/thunderbird/thunderbird-accounts","commit_stats":null,"previous_names":["thunderbird/thunderbird-accounts","thunderbird/thunderbird-pro-services"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thunderbird/thunderbird-accounts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thunderbird%2Fthunderbird-accounts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thunderbird%2Fthunderbird-accounts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thunderbird%2Fthunderbird-accounts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thunderbird%2Fthunderbird-accounts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thunderbird","download_url":"https://codeload.github.com/thunderbird/thunderbird-accounts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thunderbird%2Fthunderbird-accounts/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259768605,"owners_count":22908229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-14T06:05:28.132Z","updated_at":"2026-05-01T01:03:14.732Z","avatar_url":"https://github.com/thunderbird.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Thunderbird Accounts\n\n\u003e [!IMPORTANT]\n\u003e Thunderbird Accounts is still in active development and is not ready for any active use.\n\n[![Documentation Status](https://readthedocs.com/projects/thunderbird-thunderbird-pro-services/badge/?version=latest)](https://pro-services-docs.thunderbird.net/en/latest/?badge=latest)\n\nThere is codebase documentation available at [https://pro-services-docs.thunderbird.net/en/latest](https://pro-services-docs.thunderbird.net/en/latest).\n\nThis project uses [uv](https://github.com/astral-sh/uv).\n\nThunderbird Accounts is a Django 5.2 application. Please read up on Django before diving in.\n\nDocker is the recommended way to run the server.\n\n## Services \u0026 Ports used\n\nDuring development it's great to have these handy!\n\n| Service    | Exposed Port | Remarks                                       |\n|------------|--------------|-----------------------------------------------|\n| postgres   | 5433         | Accounts DB                                   |\n| kcpostgres | 5434         | Keycloak DB                                   |\n| redis      | 6380         | Redis                                         |\n| redis      | 8071         | Redis Insights                                |\n| accounts   | 8087         | Accounts Web                                  |\n| flower     | 5555         | Celery task monitoring                        |\n| vite-dev   | 5173         | Used on Account's frontend for hot-reloading. |\n| mailpit    | 8025         | Mailpit Web                                   |\n| mailpit    | 1025         | Mailpit SMTP                                  |\n| stalwart   | 443          | Stalwart Admin                                |\n| stawart    | 8080         | Stalwart Admin                                |\n| stalwart   | 8081         | Stalwart JMAP                                 |\n| stalwart   | 143          | Stalwart IMAP                                 |\n| stalwart   | 993          | Stalwart IMAP TLS                             |\n| stalwart   | 25           | Stalwart SMTP                                 |\n| stalwart   | 465          | Stalwart SMTP TLS                             |\n\n## Before you begin\n\nMake sure you have [uv](https://github.com/astral-sh/uv) up and running.\n\n\n## Getting Started\n\nEnsure you have uv setup and the project bootstrapped by running:\n\n```bash\nuv sync\nuv run bootstrap.py\n```\n\nThis will create a virtual environment if needed and sync the latest project dependencies to your local environment.\n\nThe project comes with some optional dependencies such as cli tools, tools for building the docs, and tools for working\nwith our Subscription app powered by Paddle.\n\nThese can be installed be appending `--extra \u003coptional dependency\u003e` like so:\n\n```bash\nuv sync --extra cli --extra docs --extra subscription\n```\n\n## Re-bootstrapping the project\n\nIf you find your environment in a troubled state (it happens) you can add the option `--from-scratch` to bootstrap like\nso:\n\n```bash\nuv run bootstrap.py --from-scratch\n```\n\nThis will overwrite your local `.env` with the contents of `.env.example`, copy over a fresh copy of the stalwart config\nfrom `config.toml.example` to `mail/etc/config.toml` and delete your stalwart's internal db `mail/data`.\n\nAdditionally, you'll want to remove the volumes for both postgres and kcpostgres to clear accounts and keycloak's\ndatabase.\n\n## OIDC / Authentication\n\nAccounts integrates [mozilla-django-oidc](https://github.com/mozilla/mozilla-django-oidc). Included in this repo is a\nbasic development config for keycloak, and a keycloak environment defined in docker-compose.yml. There's nothing\nstopping you from using a different OIDC provider. Please refer to the package documentation and your local `.env` file\nfor settings you may need to change.\n\n## Running\n\nOnce you have the project bootstrapped you'll want to actually run the project via docker:\n\n```bash\ndocker compose up --build -V\n```\n\n(Note: If you're not attached to the docker group you may need to add sudo before the above command.)\n\nThe first boot may take a while as:\n\n* Keycloak imports realm / user information from `keycloak/data/import`\n* Accounts runs the required database migrations\n* Accounts pulls the latest Paddle product and subscription information (if you have the Paddle setup.)\n\nPlease wait until the containers are fully booted before continuing.\n\n## Logging in\n\nA variety of basic development admin accounts are provided to help folks boot the project and start working.\n\n### Accounts / Thunderbird Pro Dashboard\n\nYou can access the login / dashboard at [http://localhost:8087/](http://localhost:8087/). If you\nare not logged in you will be taken to a keycloak login screen. You can use the following credentials to proceed:\n\n```\nUsername: admin@example.org\nPassword: admin\n```\n\nFrom here you can create an email account.\n\nThe default admin user is also setup you use Django's admin panel available\nat [http://localhost:8087/admin/](http://localhost:8087/admin/).\n\n### Stalwart\n\nStalwart is located at [http://localhost:8080/](http://localhost:8080/). Currently, there is\na [bug](https://github.com/stalwartlabs/webadmin/issues/52) preventing instances connected to an external OIDC directory\nserver from logging into the admin panel.\n\nIf you need to access the admin panel you can modify your `mail/etc/config.toml` and edit `[storage].directory` from\n`kc` to `internal`, and restart the docker container.\n\nFrom there you can login with the following credentials:\n\n```\nUsername: admin\nPassword: accounts\n```\n\nYou generally won't need to connect to Stalwart's admin panel unless you need to verify account status or debug api\ncalls. Make sure to change the `[storage].directory` key back to `kc` and restart the docker container when you're\nfinished.\n\n### Keycloak\n\nKeycloak is the auth/OIDC provider that is setup by default. Two realms are imported the default `master` realm and the\n`tbpro` realm.\n\nIf you like to login to Keycloak's admin interface you can access that at [http://keycloak:8999/admin/master/console/](http://keycloak:8999/admin/master/console/)\nwith the following credentials:\n\n```\nUsername: admin\nPassword: admin\n```\n\nFrom there you can switch to the tbpro realm and access settings that will affect Account's and Stalwart's login.\n\nAdditionally, you can access a simple user management portal under the tbpro realm available\nat [http://keycloak:8999/realms/tbpro/account](http://keycloak:8999/realms/tbpro/account). Since this within the tbpro\nrealm you can login to any account you created for accounts including admin@example.org.\n\n## Legal Documents\n\nLegal documents (Terms of Service, Privacy Policy) are stored as markdown source files under\n`assets/legal/` and served to the frontend as pre-rendered HTML within `src/thunderbird_accounts/legal/templates/`.\n\n### Directory structure\n\n```\nassets/legal/\n├── tos/\n│   └── v1.0/\n│       ├── en.md        # Markdown source (source of truth)\n└── privacy/\n    └── v1.0/\n        ├── en.md\n\nsrc/thunderbird_accounts/legal/templates/\n├── tos/\n│   └── v1.0/\n│       └── en.html      # Pre-rendered HTML (served by the API)\n└── privacy/\n    └── v1.0/\n        └── en.html\n```\n\nEach version directory can contain multiple locale files (e.g. `de.md`, `fr.md`). The API falls\nback to `en.html` when a requested locale is not available.\n\n### Adding a new document version\n\n1. Create a new versioned directory, e.g. `assets/legal/tos/v2.0/`\n2. Write the markdown source file, e.g. `en.md`\n3. Run the conversion command to generate the HTML:\n   ```bash\n   uv run python manage.py convert_legal_docs\n   ```\n4. Commit both the `.md` and `.html` files\n5. In Django admin, create or update the `LegalDocument` record -- set `content_path` (e.g.\n   `tos/v2.0`), `version`, and check `is_current`. Saving will automatically unset `is_current` on\n   the previous version of the same document type.\n6. If adding new locales, update the SUPPORTED_LEGAL_LANGUAGES value in settings.py\n\n### Regenerating HTML from markdown\n\nIf you edit an existing markdown file, re-run the conversion command to update the HTML:\n\n```bash\nuv run python manage.py convert_legal_docs\n```\n\nThis converts all `*.md` files under `assets/legal/` and writes a sibling `.html` for each.\n\n## Creating additional apps\n\nApps are feature of django we can use to create re-usable modules with. We mostly just use them to separate out and\norganize components.\nApps can depend on and/or require other internal apps, there's no hard rule here.\n\nEnsure to nest all internal apps inside `src/thunderbird_accounts` by appending the destination path after the command:\n\n`mkdir -p src/thunderbird_accounts/\u003capp name\u003e \u0026\u0026 ./manage.py startapp \u003capp name\u003e src/thunderbird_accounts/\u003capp name\u003e`\n\nOnce the app is created go to `src/thunderbird_accounts/\u003capp name\u003e/apps.py` and prepend `thunderbird_accounts.` to\nAuthConfig.name so it looks like `thunderbird_accounts.\u003capp name\u003e`.\n\n## Building documentation locally\n\nEnsure you have the requirements in docs installed and run the following command in the project's root folder:\n\n```shell\nsphinx-build docs build\n```\n\n## Feature Flags\n\nFeature flags are stored in `localStorage` and read at runtime to toggle UI behavior.\n\n| Key | Values | Description |\n| --- | ------ | ----------- |\n| `feature.show-connect-now` | `true` | Shows the \"Connect Now\" action card on the desktop panel, which launches Thunderbird Desktop via a custom protocol URL. |\n| `feature.phase` | `2` | Enables phase 2 UI: QR code setup flow on mobile and the \"Connect Now\" card on desktop, replacing the auto-config placeholders. |\n\n## Running tests\n\nMake sure that the containers are already running.\n\nTo run all tests:\n\n```shell\ndocker compose exec backend uv run python manage.py test\n```\n\nTo run tests for a specific module:\n\n```shell\ndocker compose exec backend uv run manage.py test thunderbird_accounts.client.tests\n```\n\n## Running the E2E tests\n\nPlease see the [E2E tests README](./test/e2e/README.md).\n\n\n## Accessing the Flower Web Interface\n\nWe run Flower to surface information about Celery tasks. This service exposes a web interface on\nport 5555. In development, you can access this at `http://localhost:5555` after bringing services\nonline with `docker-compose`. In Thunderbird's live (protected) environments, we have to create an\nSSH proxy through a bastion.\n\nHow to build a bastion is documented in the Pulumi config files themselves. Once you have one that\nallows traffic from your IP, you'll need to gather some info:\n\n- Your bastion's public IP address (`$BASTION_IP`)\n- The DNS address for the Flower load balancer in the environment (`$FLOWER_LB_DBS`)\n- An available local port to forward through, let's say `8443`.\n\nOpen an SSH proxy to the bastion server:\n\n```bash\nssh -L 8443:$FLOWER_LB_DNS:443 ec2-user@$BASTION_IP\n```\n\nOur live environments all use TLS, so you will need to browse to https://localhost:8443/. You will\nhave to push past an SSL certificate hostname mismatch alert, but then you will find yourself at the\nFlower landing page, listing Celery workers on the network.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthunderbird%2Fthunderbird-accounts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthunderbird%2Fthunderbird-accounts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthunderbird%2Fthunderbird-accounts/lists"}