# Overview

URL: https://zerodev.ca/docs/oasis/developer-documentation

> How Oasis is split into core and optional modules.



Oasis is one product, so everything it needs to host mail lives in the `core` module and cannot be turned off. Separate modules are only for optional extras.

| Module | Requires | What it does                                                                                                                                     |
| ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `core` |          | Members, roles, dashboard access, domains, mailboxes, aliases, message storage, DKIM, the outgoing queue, the SMTP and IMAP servers and webmail. |
| `demo` | `core`   | Locks the dashboard down for the public demo.                                                                                                    |

Each module lives on its own orphan `module/<name>` branch, checked out as a worktree in `modules/<name>`.

## Inside core

| Part                   | Handlers                                                      | Config group | Lang package     |
| ---------------------- | ------------------------------------------------------------- | ------------ | ---------------- |
| Mail data and delivery | `domains`, `mailboxes`, `store`, `storage`, `outbound`, `tls` | `mail`       | `mail`           |
| SMTP server            | `smtp`                                                        | `smtp`       | `smtp`           |
| IMAP server            | `imap`, `mime`                                                | `imap`       |                  |
| Webmail                | `session`, `message`                                          |              | `webmail`, `app` |

Admin routes are served under `/api/modules/core/...` and the dashboard pages under `/m/core/...`.

```js
const smtp = this.oasis.modules.handlers.get("core", "smtp");
const port = this.oasis.modules.config.value("core", "smtp", "inbound_port");
```

## Search

Core's `search(query, actor)` returns members, domains, mailboxes and aliases the signed in staff member can view, as `[{ type, label, hint, href }]`. Other modules can add their own.

The search palette (Ctrl+K) lists matching dashboard pages first, then the results from every module's `search`. The `type` badge is translated with `search.type.<type>` from the module's lang package. Opening a result goes to `href` with `?search=<label>` added, so a resource page opens already filtered to that row.

## Ports

| Port | Config group | Use                                 |
| ---- | ------------ | ----------------------------------- |
| 25   | `smtp`       | Mail from other servers.            |
| 587  | `smtp`       | Mailbox sign in and send, STARTTLS. |
| 465  | `smtp`       | Mailbox sign in and send, TLS.      |
| 993  | `imap`       | IMAP over TLS.                      |
| 143  | `imap`       | IMAP with STARTTLS.                 |

Every port can be turned off or moved in the core config. Saving the `mail`, `smtp` or `imap` group restarts the listeners.

## Demo restrictions

The servers and outbound delivery check `hooks.restricted(...)` before they run, so a demo or any other policy module can switch them off.

| Action     | Effect when restricted                       |
| ---------- | -------------------------------------------- |
| `smtp`     | SMTP listeners do not start.                 |
| `imap`     | IMAP listeners do not start.                 |
| `outbound` | The queue is not delivered to other servers. |
