Access Yahoo Mail over IMAP and SMTP with an app password. Read, send, and manage messages, drafts, threads, and folders.
Reference
Yahoo Mail has no REST API. The maton yahoo-mail commands speak IMAP and SMTP, handling quoting, folder-name encoding, threading headers and the Sent copy, and checking that a write lands on the right message. Connect a mailbox with maton connection create yahoo-mail, your Yahoo address (@yahoo.com, a regional Yahoo domain such as @yahoo.co.uk, @ymail.com or @rocketmail.com) and an app password from Yahoo's Account Security settings.
Message ID
- A message ID is Yahoo's
EMAILID, from the ID column ofmessage list. It stays the same when the message is moved, trashed or its folder is renamed. A copy gets a new ID. - Commands look in one folder only:
--folder, which defaults to INBOX (Trash formessage untrash, Draft for thedraftcommands). If the message is in another folder, the command fails and asks for--folder. Searching every folder takes Yahoo 10+ seconds so the CLI doesn't do it. - Keep the folder with the ID.
message listshows a FOLDER column, andtrash,untrashandmodify --move-toprint the message's new folder. - A thread ID is Yahoo's numeric
THREADID, from the THREAD column ofmessage listorthread_idinmessage get --json.thread getrefuses message IDs. - The output has no
Message-IDheader. The sending software sets it, it isn't unique, and no command accepts it.
Get Mailbox
maton yahoo-mail whoamiList Folders
maton yahoo-mail folder list--folder takes NAME (eg. INBOX, Sent, Draft, Trash, Bulk, Archive, Work/Clients).
Create Folder
maton yahoo-mail folder create Receipts
maton yahoo-mail folder create Work/ClientsRename Folder
maton yahoo-mail folder rename Receipts "Receipts 2026"INBOX and the special folders can't be renamed.
Delete Folder
maton yahoo-mail folder delete "Receipts 2026"Permanently deletes the folder and all its messages. Messages skip Trash and can't be recovered. INBOX and special folders can't be deleted.
List Messages
maton yahoo-mail message listReturns up to 20 unread INBOX messages, newest first. Listing never marks anything read.
All messages:
maton yahoo-mail message list --all -L 50Another folder:
maton yahoo-mail message list --folder Sent --allWith filters (all must match):
maton yahoo-mail message list --all --from boss@example.com --since 2026-10-01
maton yahoo-mail message list --all --subject invoice --before 2026-10-15
maton yahoo-mail message list --all --text "quarterly report"--from, --to, --subject and --text match text anywhere in the field (--text covers headers and body); --since and --before take YYYY-MM-DD. There is no next-page cursor: -L/--max caps the results so narrow with filters instead of paging. Yahoo does not index Bulk (spam) for text searches so --subject and --text find nothing there.
Get Message
maton yahoo-mail message get {messageId}
maton yahoo-mail message get {messageId} --headers
maton yahoo-mail message get {messageId} --folder Sent --rawPrints the plaintext body without marking the message as read. --headers adds From/To/Cc/Subject/Date, --html prints the HTML part, and --raw prints the original source. --json adds the folder, flags, and thread_id.
Send Message
maton yahoo-mail message send --to alice@example.com --subject "Hello" --body "Hi there!"
maton yahoo-mail message send --to alice@example.com --cc bob@example.com --subject "Report" --body "Attached." -a report.pdfYahoo files its own copy in Sent, usually within seconds but sometimes up to 30 seconds later (forwards especially). The output contains no message ID (--json prints {}), so to act on the sent message, find it with message list --folder Sent --all --subject "…", and retry shortly if it isn't there yet. --html sends --body as HTML. reply, reply-all, forward and draft send work the same way.
Reply to Message
maton yahoo-mail message reply {messageId} --body "Thanks!"
maton yahoo-mail message reply {messageId} --body "Draft reply" --draftThe reply goes to the original sender (or their Reply-To address, if set) and includes the threading headers and quoted original so mail apps keep the conversation together. --draft saves the reply to Draft instead of sending it and prints the draft ID.
Reply All to Message
maton yahoo-mail message reply-all {messageId} --body "Sounds good"
maton yahoo-mail message reply-all {messageId} --body "Updated" --remove bob@example.comThe reply goes to everyone in To and Cc, except your own address and any address passed with --remove. When replying to a message you sent, it goes to that message's original recipients.
Forward Message
maton yahoo-mail message forward {messageId} --to dave@example.com --body "FYI"The original's header block and body are included. Its attachments are not re-attached; attach files with -a.
Modify Message
maton yahoo-mail message modify {messageId} --read
maton yahoo-mail message modify {messageId} --unread --flag
maton yahoo-mail message modify {messageId} --move-to ArchiveIMAP uses flags and folders rather than labels. The message keeps its ID; the output names the folder it is now in, which later commands need as --folder.
Trash / Untrash Message
maton yahoo-mail message trash {messageId}
maton yahoo-mail message untrash {messageId}
maton yahoo-mail message untrash {messageId} --to Archivetrash moves the message to Trash where it stays until the provider empties it. untrash moves it back to INBOX or to --to if given.
Create Draft
maton yahoo-mail draft create --to alice@example.com --subject "Hello" --body "Draft body"List Drafts
maton yahoo-mail draft listGet Draft
maton yahoo-mail draft get {draftId}Send Draft
maton yahoo-mail draft send {draftId}Sends the draft as saved, then deletes it from Draft. BCC recipients receive it but aren't shown in the delivered message's headers. Yahoo files its own copy in Sent, usually within seconds but sometimes up to 30 seconds later (forwards especially). The output has no ID (--json prints {}): to act on the sent message, find it with message list --folder Sent --all --subject "…", and retry shortly if it isn't there yet.
Delete Draft
maton yahoo-mail draft delete {draftId}Permanently deletes the draft; it doesn't go to Trash.
Get Thread
maton yahoo-mail thread get {threadId}
maton yahoo-mail thread get {threadId} --jsonLists every message in the conversation across all folders including Sent and Trash, oldest first, as summaries; use message get for bodies.
Raw IMAP / SMTP
POST /yahoo-mail/commands
Content-Type: application/json
{"commands": "<base64 of the IMAP or SMTP stream>"}stream=$(printf 'M1 EXAMINE INBOX\r\nM2 UID SEARCH UNSEEN\r\n' | base64)
maton api -X POST '/yahoo-mail/commands' -f commands="$stream" -q '.data' | base64 --decodeThe request body is exactly {"commands": "<base64 of the stream>"} (any other field is refused), and the response is {"data": "<base64 of the server's reply>"}. A stream whose first word is an SMTP verb (EHLO, MAIL, …) goes to SMTP; anything else goes to IMAP. None of the commands' safeguards apply:
- You own the protocol. Every IMAP command needs a unique tag; strings need quoting or literals (use
{n+}); non-ASCII folder names must be in modified UTF-7 (CaféisCaf&AOk-); every line ends with CRLF, and a bare CR or LF is refused. Mistakes come back asBADreplies, each costing about 4 seconds (includingUNSELECTwith no folder selected), or, worse, as a valid command that does something else. - No folder is selected when a stream starts. Run
SELECTorEXAMINEfirst, in the same stream. - Writes to a missing UID succeed silently.
STORE,MOVE,COPYandEXPUNGEon a UID that no longer exists report success. Check withUID FETCH <uid> (UID)in the same stream, and useUID EXPUNGE <uid>, never plainEXPUNGE, which removes every message marked deleted in the folder. - Fetching with
BODY[]marks a message read. UseBODY.PEEK[]. UID SEARCH EMAILID xon its own ignores the selected folder and can return the UID from another folder. Add any other criterion, e.g.UID SEARCH ALL EMAILID x, to keep it in the selected folder.- No search-and-fetch in one step.
SEARCHRES(RETURN (SAVE)),MULTISEARCHand fetching by EMAILID are refused: search first, then fetch the UIDs it returned. - Threads:
SEARCH THREADID nworks per folder, and the ID must be a number (anything else getsNO [SERVERBUG]).HEADER Referencessearches getBAD [CANNOT]and make anORreturn nothing. - Some commands make Maton discard the session, so the next request logs in again:
LOGIN,AUTHENTICATE,LOGOUT,ENABLE,IDLE,NOTIFY,COMPRESS, CONDSTORE/QRESYNC options, synchronizing literals{n}, andSEARCH … RETURNoptions other thanMIN,MAX,COUNTandALL. - SMTP is all yours: the
MAIL FROM/RCPT TO/DATAsequence (BDATis refused), dot-stuffing, theMessage-IDandDateheaders, strippingBccfrom the message, and threading headers on replies.
Notes
- Removal actions require review.
folder deleteanddraft deleteare permanent; list or get the target first so you can verify it. - Reading never marks mail read.
message list,message getandthread getleave flags alone; mark a message withmessage modify --read. --sinceand--beforework by day, on the date the server received the message; the time of day is ignored.- "Not found" means another folder, or gone. An EMAILID never changes, so
message … not found in INBOXmeans the message is in a different folder or was deleted. - Replies can land in Bulk. Yahoo's spam filter sometimes files replies there, and Bulk isn't indexed for
--subjector--text; list it withmessage list --folder Bulk --all, or find the reply withthread get. - Folder names: non-ASCII names (
Café) are converted to and from IMAP's encoding, and names with control characters are refused. CreatingWork/Clientsalso lists a parentWorkthat can't hold messages; Yahoo removes it with its last child. - Yahoo decides what is in a thread. It groups by its own
THREADID, which also pulls in a forward with the same subject, and ignores aMessage-IDcopied from another message. - A copy is a separate message. Mail sent to yourself is stored twice, in INBOX and in Sent, each with its own EMAILID;
thread getlists both. - Forwards stay in the thread:
forwardsetsReferences(but notIn-Reply-To) to the original. - Only Yahoo addresses can be connected. A Yahoo account that signs in with another provider's address, such as Gmail, has no Yahoo address to send from: Yahoo refuses its sends, so the connect form refuses it. Yahoo Japan (
@yahoo.co.jp) is a separate service and isn't supported. - Retry reads, check writes. After a 500, 502 or 504, a send or change may already have happened: check the folder (and Sent) before repeating it. 429 and 503 changed nothing; retry after
Retry-After.
Rate Limits
- Requests: 10 per second per Maton account, with bursts up to 50.
- Mail requests in progress: at most 4 at a time per Maton account, across all of its mailboxes; more get 429 for a second.
- One session per mailbox: Maton keeps a single IMAP session per mailbox, shared by every connection to that address. Yahoo answers on it one command at a time: about 0.6 s each, 2–3 s for a command that takes a message ID, longer for
thread get. So at most 2 requests are in flight per mailbox, one on the session and one waiting up to 10 s for it; a third is refused at once with 429. Send requests one after another, under one per second. - Logins per mailbox: 4 IMAP logins per 8 s and 10 SMTP logins per 20 s; each send logs in to SMTP. Maton reuses IMAP sessions, so this is only reached by reconnect-heavy raw streams or rapid sends.
- Failed logins: a refused app password is retried only after a pause (5 minutes, doubling up to 6 hours), and two refusals in a row mark the connection
FAILED(login_revoked). - Sending: 500 messages and 500 recipients per mailbox per day, across all its connections, reset at 00:00 UTC. A send over the allowance gets 429 before anything goes out. Leave a minute between sends: each is a separate SMTP login, and about ten within a few minutes have made Yahoo refuse the app password.
- Throttling: bursts of failing requests or reconnects can make Yahoo refuse the mailbox with
[SERVERBUG] … try again lateror[UNAVAILABLE] LOGIN Server error. Maton returns 503 withRetry-After: 60and holds off logging in for 60 s; Yahoo itself has kept a mailbox locked for 45 minutes to 2 hours. Back off rather than retrying in a loop.