برای عاملهای هوش مصنوعی
`openemail` را از Claude Code، Codex یا یک کار CI به کار بگیرید: ورود بدون حضور کسی، راهنما بهصورت داده، اجرای آزمایشی، دامنههای مجوزِ ناموجود و کدهای تأیید هویت.
راهنمای داخلی
openemail agents یک راهنمای کوتاه بهصورت Markdown برای عاملی مانند Claude Code یا Codex، یا برای یک اسکریپت در CI، چاپ میکند: چگونه بدون یک انسان وارد شود، خروجی را بخواند، فرمانها را پیدا کند، چیزها را با اطمینان تغییر دهد و صفحهبهصفحه در فهرستها پیش برود، وقتی کد تأیید هویت یا دامنهٔ مجوزی کم است چه کند، و پنج دستورالعمل آماده برای رونوشت. openemail agent همان فرمان است.
openemail agentsopenemail agents --json | jq -r '.recipes[].commands[]'با --json راهنما یک سند است با schemaVersion، title، intro، sections از { id, title, points }، exitCodes و recipes از { id, title, commands }. بهجای چسباندن این قاعدهها در هر پرامپت، یک بار در همان فایل دستورالعملی که پروژهٔ شما از قبل به عامل میدهد، به او بگویید پیش از به کار بردن CLI فرمان openemail agents را اجرا کند.
ورود بدون یک انسان
- از یک کلید API استفاده کنید.
OPENEMAIL_API_KEYرا تنظیم کنید، یا--api-keyرا به یک فرمان بدهید. آن را در تنظیمات ← کلیدهای API (openemail open api-keys) فقط با دامنههای مجوزی که عامل نیاز دارد بسازید. کلید هرگز مرورگری باز نمیکند و هرگز به کد تأیید هویت نیاز ندارد. - یا ورود با مرورگری را که یک انسان یک بار روی همین دستگاه با
openemail loginانجام داده دوباره به کار بگیرید و آن را با--profile <name>برگزینید. CLI توکنهایش را خودش نو میکند. - بدون ترمینال چیزی پرسیده نمیشود. زیر
--json،--no-inputیاCI، یا وقتی ترمینالی وصل نیست، مقداری که CLI میپرسید با کد خروج2متوقف میشود و نام پرچمی را که باید داد میگوید. - ورود با مرورگر به انسانی نیاز دارد که آن را تأیید کند، پس
openemail loginبدون حضور کسی پیش از ثبت هر چیزی با کد خروج2و کدunattendedمتوقف میشود و بهopenemail login --with-tokenاشاره میکند. openemail whoami --jsonفضای کاری، نوع ورود وscopesآن را نشان میدهد.
خواندن خروجی
به هر فرمان --json بدهید. آنگاه stdout دقیقاً یک سند JSON، یا با --ndjson در هر خط یک شیء، دارد و پیشرفت روی stderr میماند. شکست یک خط {"error":{...}} روی stderr چاپ میکند: بر پایهٔ کد خروج و code آن تصمیم بگیرید، next را به یک انسان نشان دهید و هرگز message را تجزیه نکنید، چون عبارتش ممکن است تغییر کند. صفحهٔ «اسکریپتنویسی» همهٔ فیلدها و همهٔ کدهای خروج را فهرست میکند.
فرمانها بهصورت داده
--help --json راهنما را بهصورت یک سند JSON چاپ میکند که از همان فهرست ثبت فرمانهایی ساخته شده که CLI با آن تجزیه میکند، پس همیشه با نسخهٔ نصبشده جور است. روی ریشه، یک گروه یا یک فرمان کار میکند و openemail help <command> --json همان را چاپ میکند.
openemail send --help --jsonopenemail domains delete --help --json | jq '.commands[0] | {scopes, destructive}'openemail help domains --json | jq -r '.commands[0].subcommands[].command'openemail --help --json | jq -r '.commands[].command'سند
schemaVersionnumber- وقتی معنای یک فیلد تغییر کند، تغییر میکند
cli, versionstring- همیشه `openemail`، و نسخهای که آن را چاپ کرد
pathstring[]- فرمانی که پرسیده شده، برای ریشه خالی
commandsobject[]- برای ریشه همهٔ فرمانهای سطح بالا، وگرنه همان فرمان پرسیدهشده، هر کدام با زیرفرمانهایش
globalFlagsobject[]- پرچمهایی که هر فرمان میپذیرد، به همان شکل پرچمهای یک فرمان
subcommandAliasesobject- هر نام مستعار مشترک، مانند `ls` یا `rm`، و فعلهایی که بهجایشان مینشیند
exitCodesobject[]- همهٔ کدهای خروج بهصورت `{ code, name, meaning }`
یک فرمان
namestring- آخرین واژهٔ فرمان
commandstring- کل فرمان، مانند `openemail domains delete`
path, aliasesstring[]- واژههای پس از `openemail` که به آن میرسند، و نامهای دیگرش
summary, descriptionstring- کاری که میکند، در یک خط و به تفصیل
usagestring[]- شیوهٔ فراخوانیاش
categorystring | null- بخش آن در `openemail --help` برای فرمان سطح بالا، وگرنه `null`
group, runnable, hiddenboolean- اینکه زیرفرمان دارد، بهتنهایی اجرا میشود و راهنما آن را پنهان میکند یا نه
authstring- ورودی که لازم دارد: `required`، `browser` فقط برای ورود با مرورگر، `optional` یا `none`
scopesstring[]- دامنههای مجوز API که هر اجرای آن لازم دارد
destructiveboolean- اینکه نخست تأیید میخواهد یا نه، تأییدی که `--yes` به آن پاسخ میدهد
argumentsobject[]- `name`، `description`، `required` و `variadic` هر آرگومان
flagsobject[]- `name`، `short`، `kind`، `required`، `repeatable`، `choices`، `placeholder`، `description` و `hidden` هر پرچم
notes, examplesobject[]- بلوکهای اضافی راهنما بهصورت `{ title, lines }`، و نمونهها بهصورت `{ command, note }`
resourceobject | null- برای فرمان منبع، متد SDK و فراخوانی REST پشت آن، وگرنه `null`
subcommandsobject[]- فرمانهای زیر یک گروه، به همان شکل
یک منبع
namespacestring- فضای نام SDK، مانند `domains`
sdkMethodstring- متد SDK، مانند `openemail.domains.delete`
sdkMethodAllstring | null- برای فهرست، متد `listAll` که `--all --json` آن را میپیماید
httpMethod, httpPathstring- فراخوانی REST، مانند `DELETE` و `/domains/{id}`
scopesstring[]- دامنههای مجوزی که متد لازم دارد
authstring- `apiKey`، یا `none` و `inboxToken` برای متدی که کلید API نمیفرستد
returnsobject- `{ shape, type }`: شکل پاسخ، مانند `object` یا `page`، و نوع آن در SDK
paginatesboolean- اینکه یک صفحه از فهرستی را برمیگرداند یا نه
کل درخت حدود یک مگابایت است و تقریباً همهاش 198 فرمان منبع است، پس فرمانی را که لازم دارید بخواهید یا درخت را با jq پالایش کنید. متن بکتیکهایش را نگه میدارد و کد رنگ ندارد، و فرمانهای پنهان مانند security با hidden برابر true در آن هستند.
اجرای آزمایشی
--dry-run روی همهٔ فرمانها جز mcp serve کار میکند. خواندنها مثل همیشه اجرا میشوند، سپس نخستین درخواستی که چیزی را تغییر میداد بهجای فرستاده شدن چاپ میشود و فرمان بیآنکه کار دیگری کند با کد 0 خارج میشود. تأییدها رد میشوند، چون چیزی فرستاده نمیشود، پس عامل میتواند ببیند یک فرمان ویرانگر چه میکرد، بیآنکه --yes بدهد.
openemail domains delete <domain-id> --dry-runopenemail send --from [email protected] --to [email protected] --subject "Hi" --text "Hello" --dry-run --json{ "dryRun": true, "request": { "method": "POST", "url": "https://api.openemail.uk/emails", "headers": { "accept": "application/json", "authorization": "Bearer [redacted]", "content-type": "application/json", "idempotency-key": "58e6fb61-ad2e-401e-b141-7a0546c7c749", "user-agent": "openemail-cli/0.0.1 openemail-sdk/0.0.5" }, "body": { "from": "[email protected]", "to": [ "[email protected]" ], "subject": "Hi", "text": "Hello" }, "raw": null }}- تغییر یعنی هر درخواستی جز
GETوHEAD، فراخوانی یک ابزار MCP، و درخواستهای ورود و خروجloginوlogout. نوسازی توکن وdocs askهمچنان اجرا میشوند. - طرح، متد، URL کامل، سرآیندها با مقدار
Authorizationکوتاهشده بهBearer [redacted]، و بدنهٔ JSON را با فیلدهای محرمانه، مانند کلید Resend، پوشیده نشان میدهد. بارگذاری فقط اندازه و نوع محتوایش را نشان میدهد. - تغییری که روی همین دستگاه میماند، مانند
profile use،login --with-tokenیا فراموش کردن یک کلید API ذخیرهشده،{"dryRun":true,"local":{"action","profile"}}را چاپ میکند و چیزی ذخیره نمیکند. - فرمانی که پیش از نخستین تغییرش آنچه را خوانده چاپ میکند، آن را اول نشان میدهد:
readرشته را چاپ میکند، سپس درخواستی را که آن را خواندهشده علامت میزد. برای کنار گذاشتن دومی--no-mark-readرا بدهید. mcp serveگزینهٔ--dry-runرا با کد خروج2رد میکند، چون کلاینتش تصمیم میگیرد چه بفرستد. بهجای آن یک فراخوانی ابزار را باopenemail mcp call <tool> --dry-runپیشنمایش کنید.
دامنههای مجوزِ ناموجود
هر فرمان دامنههای مجوز API را که همیشه لازم دارد میشناسد و راهنمایش آنها را فهرست میکند. وقتی ورود ذخیرهشده یکی از آنها را ندارد، فرمان یک بار فهرست کنونی را از API میپرسد، پس دسترسیای که پس از ورود در وبسایت داده شده بیدرنگ به حساب میآید. اگر دامنهٔ مجوز هنوز نباشد، پیش از پرسیدن هر چیزی یا فرستادن درخواستی، با کد خروج 4 و کد insufficient_scope متوقف میشود:
{"error":{"type":"cli_error","code":"insufficient_scope","message":"This sign-in does not have the emails:send permission, which openemail send needs.","hint":null,"next":"Give this app more access in Account settings, Connected apps (openemail open apps, then Edit access), or run openemail login --force and choose more access.","status":null,"requestId":null,"param":null,"docUrl":null,"exitCode":4}}- برای ورود با مرورگر،
nextمیگوید در حساب ← خط فرمان به برنامه دسترسی بیشتری بدهید (openemail open cli، سپس «ویرایش دسترسی»)، یاopenemail login --forceرا اجرا کنید و دسترسی بیشتری برگزینید. به ورود با مرورگر هرگزkeys:writeیاkeys:manageداده نمیشود، پس برای آنها به کلید API اشاره میکند. - برای کلید API،
nextمیگوید از کلیدی استفاده کنید که آن دامنهٔ مجوز را دارد. - کلیدی که از
--api-keyیاOPENEMAIL_API_KEYمیآید از پیش بررسی نمیشود و API تصمیم میگیرد. وقتی API فراخوانیای را به خاطر دامنهٔ مجوزِ ناموجود رد کند، خطا همانnextرا دارد.
کدهای تأیید هویت
کلید API هرگز به کد تأیید هویت نیاز ندارد. ورود با مرورگر پیش از تغییری حساس، مانند افزودن یک وبهوک، ساختن یک قاعده، تغییر یک عضو یا حذف یک دامنه، به کد نیاز دارد و عامل نمیتواند آن را تایپ کند. پس پیش از اجرای عامل، یک انسان یا openemail verify را در ترمینالی با همان نمایه اجرا میکند، یا در حساب ← خط فرمان برای آن ورود «اجازهٔ تغییرات برای 60 دقیقه» را برمیگزیند. هر کدام 60 دقیقهٔ بعد را پوشش میدهد.
openemail verifyopenemail verify --status --jsonverify --status --json به عامل میگوید آیا نمایه تأییدشده است، در elevated، و تا کی، در elevatedUntil. بدون تأیید، تغییر با کد خروج 4 و کد step_up_required متوقف میشود و چیزی تغییر نمیکند:
{"error":{"type":"cli_error","code":"step_up_required","message":"This action needs a verification code, and there is no interactive terminal to ask for one.","hint":null,"next":"Run openemail verify in an interactive terminal first, then run this again within 60 minutes. An API key never needs a code.","status":403,"requestId":"req_9Qm4tV","param":null,"docUrl":"https://openemail.uk/docs/api/errors#step_up_required","exitCode":4}}از راه MCP
عاملی که MCP بلد است میتواند بهجای آن از سرور MCP مربوط به OpenEmail استفاده کند. openemail mcp config --client claude-code، یا codex، cursor و دیگر کلاینتهایی که فهرست میکند، راهاندازی را چاپ میکند، و openemail mcp serve یک پل محلی است که ورود با مرورگرِ همین CLI را دوباره به کار میگیرد. کلیدهای API به سرور MCP نمیرسند. جزئیات در صفحهٔ «هوش مصنوعی و MCP» است.
دستورالعملها
openemail inbox --unread --limit 20 --jsonopenemail inbox --unread --json | jq -r '.items[].id'openemail read CAHk7pQ2x9LmZ4 --no-mark-read --jsonopenemail send --from [email protected] --to [email protected] --subject "Weekly report" --body-file report.md --idempotency-key weekly-report-39 --jsonopenemail domains create --domain example.com --dry-run --jsonopenemail domains create --domain example.com --jsonopenemail whoami --json | jq '.scopes'