Skip to content

Add qq-mail extension#27293

Open
ariesly15 wants to merge 8 commits intoraycast:mainfrom
ariesly15:ext/qq-mail
Open

Add qq-mail extension#27293
ariesly15 wants to merge 8 commits intoraycast:mainfrom
ariesly15:ext/qq-mail

Conversation

@ariesly15
Copy link
Copy Markdown

@ariesly15 ariesly15 commented Apr 20, 2026

Description

A Raycast extension that brings QQ Mail (腾讯QQ邮箱) directly into your workflow. Read, compose, and manage your QQ Mail emails without leaving Raycast.

Features

  • 📬 Browse emails — View your inbox and other folders with unread/read status indicators
  • 📝 Compose emails — Send new emails with CC support directly from Raycast
  • 📎 Attachment support — View and download email attachments
  • 🔍 Filter emails — Filter by unread, read, or emails with attachments
  • 📁 Folder navigation — Switch between Inbox, Sent, Drafts, Trash, and custom folders
  • Optimistic updates — Read/unread status updates instantly without waiting for server response

Configuration

Field Description
QQ Email Address Your full QQ email address (e.g. 123456@qq.com)
Authorization Code QQ Mail authorization code — not your QQ password. Get it from QQ Mail Settings → Account → POP3/IMAP/SMTP/Exchange/CardDAV

⚠️ You must enable IMAP service in QQ Mail settings before using this extension.

Screencast

qq-mail-2 qq-mail-4

Checklist

@raycastbot
Copy link
Copy Markdown
Collaborator

Congratulations on your new Raycast extension! 🚀

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

Once the PR is approved and merged, the extension will be available on our Store.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR adds a new QQ Mail extension that connects to QQ's IMAP/SMTP servers, providing inbox browsing, email composition, attachment downloads, folder navigation, and optimistic read/unread toggling.

  • Attachment filter pagination is broken: fetchEmails slices a fixed UID window then discards non-attachment emails client-side, so hasMore is set to false after the first batch even when many more attachment emails exist — users will see an incomplete list with no way to load more.
  • CHANGELOG.md copied from another extension: the title reads "Proton Mail Changelog" and uses a hardcoded date (2026-01-23) instead of the required {PR_MERGE_DATE} placeholder.

Confidence Score: 3/5

Not ready to merge — the attachment filter produces a broken pagination experience and the changelog has a copy-paste error that must be fixed.

Two P1 issues are present: a logic bug that causes the 'Has Attachment' filter to stop loading emails after the first UID window, and a changelog that was clearly copied from a different extension. Both should be resolved before merging.

extensions/qq-mail/src/imap-client.ts (attachment pagination logic) and extensions/qq-mail/CHANGELOG.md (wrong title and date placeholder)

Important Files Changed

Filename Overview
extensions/qq-mail/CHANGELOG.md Copy-pasted from another extension: wrong title ("Proton Mail") and hardcoded date instead of {PR_MERGE_DATE} placeholder
extensions/qq-mail/src/imap-client.ts Core IMAP logic; attachment filter pagination is broken — client-side filtering against a fixed UID window causes premature pagination termination
extensions/qq-mail/src/smtp-client.ts SMTP send/reply/forward logic; module-level transporter singleton may serve stale credentials after a preference change
extensions/qq-mail/src/list-emails.tsx Main email list UI with optimistic read/unread updates, pagination, and folder switching; well-structured overall
extensions/qq-mail/src/compose-form.tsx Email compose/reply/forward form; correct markdown-to-HTML conversion and input quoting
extensions/qq-mail/src/attachment-list.tsx Attachment download with sanitized filenames, unique path generation, and proper Downloads directory targeting
extensions/qq-mail/package.json Well-configured extension manifest; all listed dependencies are imported in source files
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/qq-mail/CHANGELOG.md
Line: 1-3

Comment:
**Copy-paste artifact and wrong date placeholder**

The changelog title is `Proton Mail Changelog` (copied from another extension) and the date uses a hardcoded value instead of the required `{PR_MERGE_DATE}` placeholder. Both violate the standard Raycast changelog convention.

```suggestion
# QQ Mail Changelog

## [Initial Release] - {PR_MERGE_DATE}
```

**Rule Used:** What: In Raycast extension changelogs, `{PR_MERGE_... ([source](https://app.greptile.com/review/custom-context?memory=799af734-ebd9-4b40-9ffd-97a70fc71c8a))

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/qq-mail/src/imap-client.ts
Line: 136-158

Comment:
**Attachment filter breaks pagination prematurely**

When `filter === "attachment"`, the function fetches `limit` UIDs by position (`slice(offset, offset + limit)`) and then discards non-attachment emails in-memory. If the first page of 20 emails contains only 3 with attachments, the function returns 3 emails. The caller then does `if (moreEmails.length < pageSize) setHasMore(false)``3 < 20` → pagination stops, even though hundreds of attachment-bearing emails may remain further in the mailbox. Users will see only the handful of attachment emails that happened to land in the first UID window.

A correct approach is to either (a) use a server-side IMAP search for `HEADER Content-Disposition attachment` to get only matching UIDs before slicing, or (b) keep fetching until `limit` matching emails are collected or UIDs are exhausted.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/qq-mail/src/smtp-client.ts
Line: 7-28

Comment:
**Stale transporter when credentials change**

`transporterInstance` is a module-level singleton initialized once with the credentials captured at first call. If the user updates their authorization code in Raycast preferences (without fully quitting the extension process), subsequent `sendEmail` calls will silently use the old credentials and fail with an auth error rather than picking up the new password. Since `imap-client.ts` creates a fresh `ImapFlow` per call and never caches, the SMTP side is inconsistent. Consider removing the singleton and calling `nodemailer.createTransport` inside `sendEmail` directly (or at least clearing `transporterInstance` when a send fails with auth error).

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Add qq-mail extension" | Re-trigger Greptile

Comment thread extensions/qq-mail/CHANGELOG.md Outdated
Comment thread extensions/qq-mail/src/imap-client.ts Outdated
Comment thread extensions/qq-mail/src/smtp-client.ts Outdated
慕雨 added 7 commits April 20, 2026 14:19
…nsporter caching

- Add star/unstar action in EmailActions and ExpandedEmailView with optimistic update
- Show star badge (yellow star icon) in email list item accessories
- Fix attachment filter pagination: scan UIDs in batches until limit matched emails collected
- Fix SMTP transporter singleton caching stale credentials: create fresh transporter per send
- Fix CHANGELOG title and date placeholder per Raycast convention
@raycastbot
Copy link
Copy Markdown
Collaborator

This pull request has been automatically marked as stale because it did not have any recent activity.

It will be closed if no further activity occurs in the next 7 days to keep our backlog clean 😊

@raycastbot raycastbot added the status: stalled Stalled due inactivity label May 4, 2026
@ariesly15
Copy link
Copy Markdown
Author

This PR is still actively maintained. I've been refining the implementation based on code review feedback — fixed attachment filter pagination, removed the SMTP transporter singleton to always pick up fresh credentials, and added star/unstar support with optimistic UI updates. Happy to address any further review comments!

@raycastbot raycastbot removed the status: stalled Stalled due inactivity label May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants