Skip to content

(Developer) Run the Backend from Source

The backend is the engine of all of MailAgent: it syncs email in the background, runs AI classification, and maintains the local database. When running from source, the whole process is five steps and takes about 15 minutes if you follow along.

Step 1: Clone the repo and create a virtual environment

Section titled “Step 1: Clone the repo and create a virtual environment”

Open a terminal (Terminal or iTerm2) and run:

Terminal window
git clone https://github.com/ChenyqThu/MailAgent.git ~/Documents/MailAgent
cd ~/Documents/MailAgent
python3 -m venv venv
source venv/bin/activate
pip install -e ".[cli,dev]"
cp .env.example .env

The last line, pip install -e ".[cli,dev]", installs the mailagent command into the virtual environment. The -e (editable install) flag makes code changes you pull via git pull take effect immediately, with no reinstall needed.

Verify the install:

Terminal window
which mailagent # should point to venv/bin/mailagent
mailagent --version # expected output 3.0.0

Step 2: Optional — build a Notion mirror

Section titled “Step 2: Optional — build a Notion mirror”

Notion is optional: MailAgent stores email bodies and attachments in a local SQLite database (the authoritative copy); Notion is only an optional extra archive mirror. Skip this step if you want a purely local SQLite setup—go straight to Step 3.

If you do want a Notion mirror, MailAgent needs two Notion databases: one for email, one for the calendar. You must create these two databases in Notion first and set up their fields per the tables below—the field names and types must match exactly, or sync will fail.

2a. Create the Integration and get the Token

Section titled “2a. Create the Integration and get the Token”
  1. Open www.notion.so/my-integrations in your browser.
  2. Click New integration, give it a name (e.g. MailAgent), and associate it with your workspace.
  3. After creating it, copy the Internal Integration Token (starts with ntn_)—this is the NOTION_TOKEN in .env.

Create a new Notion database (type /database on a page → Table - Full page) and add the fields per the table below. Field names must correspond exactly:

Field nameTypeDescription
SubjectTitleEmail subject (just rename the built-in title column of the database)
Message IDTextUnique email identifier, used for deduplication
Thread IDTextThread identifier, shared by emails on the same topic
FromEmailSender address
From NameTextSender display name
ToTextRecipient
CCTextCarbon copy
DateDateEmail date
Parent ItemRelation (pointing to this database itself)Thread-head relation, stringing one topic together
MailboxSelectInbox / Sent / Archive, etc.
Is ReadCheckboxWhether read
Is FlaggedCheckboxWhether flagged
Has AttachmentsCheckboxWhether it has attachments
AI ActionSelectAI-suggested action (Reply needed / For reference only / …)
AI PrioritySelectOptions: Critical / Urgent / Important / Normal / Low
AI Review StatusSelectOptions: Pending / Reviewed

Parent Item is a Relation that points to itself: when creating the field, choose this database itself as the data source. It lets replies on the same topic hang under the thread head.

Once it is set up, open the database’s top-right ⋯ → Connections → and add the MailAgent Integration you just created, otherwise it has no write permission. The 32-character hexadecimal segment in the database URL is the EMAIL_DATABASE_ID:

https://www.notion.so/<workspace>/<this segment is the DATABASE_ID>?v=...

2c. Create the calendar database (6 fields)

Section titled “2c. Create the calendar database (6 fields)”

Likewise create a new database and set up:

Field nameTypeDescription
TitleTitleEvent title
Event IDTextUnique event identifier, used for deduplication
TimeDate (with start/end)Event start and end time
URLURLTeams / meeting link
LocationTextLocation
OrganizerTextOrganizer

Remember to add the Integration connection here too; the ID in the URL is the CALENDAR_DATABASE_ID.

Step 3: Fill in the five required values in .env

Section titled “Step 3: Fill in the five required values in .env”

Open ~/Documents/MailAgent/.env in any editor and fill in at least these five values:

Terminal window
NOTION_TOKEN=ntn_xxxxxxxx # the Integration Token from step 2a
EMAIL_DATABASE_ID=xxxxxxxx # the ID of the email database from step 2b
CALENDAR_DATABASE_ID=xxxxxxxx # the ID of the calendar database from step 2c
USER_EMAIL=[email protected] # your email address
MAIL_ACCOUNT_NAME=Exchange # the name of this account in Mail.app (used by the AppleScript backend)

Not sure what your account is named in Mail.app? Run:

Terminal window
mailagent debug mail-structure

It will list all accounts and mailboxes in Mail.app; put your account name into MAIL_ACCOUNT_NAME.

The full set of optional configuration (Feishu, Redis, AI gateway, individual feature toggles) is documented with comments in .env.example; use what you need.

MailAgent switches between two mailbox-access paths with a single line of config:

Terminal window
MAILAGENT_BACKEND=applescript # code default; corporate Exchange users should change to davmail
BackendHow it connects to the mailboxWho it’s forSpeed
davmail (recommended)Bridges corporate Exchange via DavMail (IMAP / SMTP / CalDAV)Corporate Exchange / Microsoft 365 users who want it faster and more stable, with rich-text replies + multi-folder + direct calendar reads~236 ms per email
applescriptDrives the built-in macOS Mail.app directlyA zero-extra-component, ready-to-go fallback~1 second per email

Corporate Exchange / Microsoft 365 users should use DavMail—faster and more stable, and it genuinely unlocks rich-text Reply All, multi-folder sync, and direct CalDAV calendar reads. The full steps for installation, authentication (including impersonating the Outlook client_id), confirming it runs, and daemonizing it are on the dedicated page Connect Your Corporate Mailbox via DavMail.

Just want the fastest start, with your mailbox already signed in within Mail.app? Keep the applescript default—no extra components needed, and it’s always available as a fallback.

Step 5: Grant macOS permissions and start the service

Section titled “Step 5: Grant macOS permissions and start the service”

The terminal App that runs MailAgent (Terminal / iTerm2) needs the permissions below. Open System Settings → Privacy & Security and grant each one:

PermissionLocationPurpose
Full Disk AccessPrivacy & Security → Full Disk AccessRead Mail.app’s local database (the SQLite radar)
Automation → MailPrivacy & Security → AutomationOperate Mail.app via AppleScript (mark read / flag / draft)
Automation → System EventsPrivacy & Security → AutomationSimulate keystrokes to paste content when creating drafts
AccessibilityPrivacy & Security → AccessibilitySystem Events sends keystrokes
Screen RecordingPrivacy & Security → Screen RecordingOnly needed when screenshotting a draft with --screenshot

If the system doesn’t pop up a permission request automatically, run mailagent debug mail-structure once to trigger it, then go to the locations above and check the boxes. Note: a process started by PM2 inherits the permissions of the terminal it was started in; switching terminals requires re-authorization.

For development / testing, run in the foreground:

Terminal window
python3 main.py

For production / long-running use, daemonize it in the background with PM2 (note that you must specify the Python interpreter inside the venv):

Terminal window
npm install -g pm2
pm2 start main.py --name mail-sync --interpreter ./venv/bin/python3
pm2 save && pm2 startup

Common PM2 commands:

Terminal window
pm2 status # check whether the process is online
pm2 logs mail-sync # tail the logs
pm2 restart mail-sync # restart
Terminal window
mailagent admin health -o json | jq .data.healthy # expect true
tail -f logs/sync.log # there should be no ERROR lines in the logs

When you see the SQLite radar running every 5 seconds and healthy is true, the backend is installed.

Once the backend is ready, the next step is to load your historical email: Initial Sync (CLI). If you also want the graphical interface, go to Install the Desktop App.


Learn more: README Quick Start · Full CLI Command Reference · DavMail and the Architecture Core