Skip to content

Add Mail tools to move, flag and tag messages - #61

Open
oleksandr-nc wants to merge 2 commits into
mainfrom
feature/mail-move-flag-tag
Open

oleksandr-nc wants to merge 2 commits into
mainfrom
feature/mail-move-flag-tag

Conversation

@oleksandr-nc

Copy link
Copy Markdown
Contributor

Closes #59.

Adds five Mail tools so an inbox can be triaged through the MCP server, and adds tags to the message output.

Tools

Tool Permission Annotation Mail route (/index.php/apps/mail)
move_mail_message(message_id, destination_mailbox_id) write ADDITIVE POST /api/messages/{id}/move
set_mail_message_flags(message_id, seen, flagged, answered) write ADDITIVE_IDEMPOTENT PUT /api/messages/{id}/flags
create_mail_tag(display_name, color) write ADDITIVE_IDEMPOTENT POST /api/tags
add_mail_message_tag(message_id, imap_label) write ADDITIVE_IDEMPOTENT PUT /api/messages/{id}/tags/{imapLabel}
remove_mail_message_tag(message_id, imap_label) write ADDITIVE_IDEMPOTENT DELETE /api/messages/{id}/tags/{imapLabel}
  • list_mail_messages and get_mail_message return tags (display name and IMAP label). The OCS message endpoint has no tags, so get_mail_message reads them from GET /api/messages/{id}.
  • set_mail_message_flags sends only the flags that were passed and rejects a call with none.
  • create_mail_tag checks the name (at most 128 characters) and requires a hex color, because Mail stores any string as a color (it accepted "red"). Creating an existing tag returns it unchanged, color included.
  • For a message ID that does not exist or belongs to someone else, and for an unknown tag label, Mail answers 403 with an empty body. The tools turn that into a message saying what was not found.
  • move_mail_message says the old ID is no longer valid. The new ID only exists once Nextcloud syncs the destination mailbox, which happens automatically for the inbox and background-synced folders and otherwise when the folder is opened in Mail, so the tool doesn't return it.

Client

NextcloudClient.app_request_json() calls /index.php/apps/{path} through _do_request with OCS-APIRequest: true, which is what lets these CSRF-protected routes accept Basic auth with an app password (200 with the header, 412 without). It returns the plain JSON body, or None when the body is empty, and _raise_for_app_status surfaces Mail's data.message and message errors.

Mail integration tests read from Dovecot

smtp4dev's IMAP server can't back these tools: it advertises no MOVE, refuses to create folders, and doesn't keep \Flagged or keywords. GreenMail was tried next, but 2.0.1, 2.1.8 and 2.1.13 all fail FETCH BODY[1.MIME] on single-part messages with a ClassCastException, which makes Mail's message view return "Could not connect to IMAP server".

The integration job now runs dovecot/dovecot:2.4.5 for IMAP and keeps smtp4dev for SMTP, so the send_mail delivery checks are unchanged. Dovecot refuses plaintext logins, so the account uses STARTTLS with the image's self-signed certificate and app.mail.verify-tls-peer=false. Test messages are put into the INBOX with IMAP APPEND instead of being sent over SMTP.

Docs

The README Mail tables list the new tools, the Mail row says OCS + REST, and the tool count is corrected to 161 (162 with NEXTCLOUD_MCP_UPLOAD_ROOT); the heading said 140.

Verification

  • ruff check, ruff format --check, isort and pyright are clean; unit tests: 142 passed, 38 of them new (16 for the client helper, 22 for the tools).
  • tests/integration/test_mail.py: 48 passed against a local Nextcloud 36 dev instance with Mail 5.12.0-rc.1, Dovecot 2.4.5 and smtp4dev. The routes used are the same in Mail 5.11.5, which CI installs on Nextcloud 34.

Five write tools call the Mail app's JSON routes through a new app_request_json client helper, and list/get output now includes tags. The Mail integration tests read from Dovecot instead of smtp4dev, whose IMAP server has no MOVE, folders or keywords. Closes #59.

Signed-off-by: Oleksandr Piskun <oleksandr2088@icloud.com>
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 6c8d3ee1-0afd-40d1-8182-db218079af58


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

test_server.py pins the registered tool names and count, so the five new Mail tools failed it with 161 == 156.

Signed-off-by: Oleksandr Piskun <oleksandr2088@icloud.com>
@codecov

codecov Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.43%. Comparing base (bde9f8a) to head (11ff522).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #61      +/-   ##
==========================================
+ Coverage   96.22%   96.43%   +0.21%     
==========================================
  Files          31       31              
  Lines        3363     3478     +115     
==========================================
+ Hits         3236     3354     +118     
+ Misses        127      124       -3     
Flag Coverage Δ
integration 95.11% <94.11%> (+0.04%) ⬆️
nc34 95.11% <94.11%> (+0.04%) ⬆️
py3.12 14.63% <100.00%> (+5.14%) ⬆️
py3.13 14.63% <100.00%> (+5.14%) ⬆️
py3.14 14.63% <100.00%> (+5.14%) ⬆️
session-cache 19.75% <15.96%> (-0.20%) ⬇️
unit 14.63% <100.00%> (+5.14%) ⬆️
user-permissions 40.10% <30.25%> (-0.40%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mail: add tools to move, flag and tag messages

1 participant