النطاقات والعناوين
أضف النطاقات وتحقّق منها، واقرأ سجلات DNS التي تحتاجها، وأدِر العناوين عليها، وافحص ما يمكنك الإرسال باسمه.
نظرة عامة
مساحتا أسماء تغطيان نطاقاتك. يدير openemail domains النطاقات المرتبطة بمساحة العمل: إضافتها وإزالتها، وسجلات DNS التي يحتاجها كل منها، وما إذا كان يستطيع الاستقبال والإرسال، وcatch-all الخاص به، ونطاقَي التتبع والملفات، والعناوين عليه. ويجيب openemail addresses عن سؤال أضيق: ما العناوين التي يجوز للمفتاح أو تسجيل الدخول الذي تستخدمه الإرسال باسمها.
- يأخذ أمر النطاق معرّف النطاق، وهو UUID من
domains listأوdomains create. ولا يُقبل اسم المضيف بدلًا منه، لذا فإنopenemail domains get acme.comيعطي 404 ويخرج بالرمز5. - يأخذ أمر العنوان معرّف النطاق ثم معرّف العنوان، وهو UUID من
domains list-addressesأوdomains create-address. - يعمل
domainوaddressكأسماء لمساحات الأسماء أيضًا. وتستجيب أفعال النطاقات للأسماء البديلة المعتادة، مثلlsوshowوnewوeditوrm، وكذلكaddresses list. أما الأفعال الخمسة لعناوين النطاق، مثلcreate-address، فلا أسماء بديلة لها. - يسرد
openemail <command> --helpكل وسيط وخيار بنوعه، والنطاق الذي يحتاجه الاستدعاء، وطريقته ومساره، وما يعود. أضف--jsonلتحصل على الصفحة نفسها في صورة بيانات.
كل الأوامر
| الأمر | ما تفعله |
|---|---|
| openemail domains list | اسرد نطاقات مساحة العمل، أبجديًا، مع حالة الاستقبال والإرسال والتتبع والملفات |
| openemail domains get <id> | اقرأ نطاقًا واحدًا مع عناوينه، وكل سجل DNS يستخدمه وما إذا عُثر على كل منها، وقراءة DMARC الخاصة به |
| openemail domains create --domain <value> | أضف نطاقًا. يضم الجواب كل سجل DNS يجب نشره، وقد فُحص مرة بالفعل |
| openemail domains verify <id> | افحص DNS النطاق فورًا وأعِد النطاق كما تركه الفحص |
| openemail domains update <id> | شغّل catch-all أو أوقفه، واضبط نطاق التتبع ونطاق الملفات أو أزلهما |
| openemail domains delete <id> | أزل النطاق وكل عنوان عليه. يطلب منك التأكيد |
| openemail domains list-addresses <id> | اسرد العناوين على نطاق مع معرّفاتها وتسمياتها وحالة تفعيلها ومتى استقبل كل منها بريدًا آخر مرة |
| openemail domains create-address <id> --local-part <value> | أنشئ عنوانًا على النطاق، مفعّلًا، مع --label اختياري |
| openemail domains get-address <id> <address-id> | قراءة عنوان واحد على نطاق |
| openemail domains update-address <id> <address-id> | أعِد تسمية عنوان بـ --label، أو أوقفه وشغّله بـ --no-enabled و--enabled |
| openemail domains delete-address <id> <address-id> | أزل عنوانًا من نطاقه. يطلب منك التأكيد |
| openemail addresses list | اسرد العناوين التي يجوز لك الإرسال باسمها بهذا المفتاح أو تسجيل الدخول، وحالة الاستقبال والإرسال لكل نطاق |
كل خيار موجود في مساعدة أمره، مثل openemail domains update --help أو openemail domains create-address --help.
الاستقبال والإرسال
يبلّغ النطاق عن حقيقتين مستقلتين. تصبح receiving.verified صحيحة حين يجيب DNS العام بسجلات MX وسجل TXT _openemail-challenge الخاصة به، ومن ثم يستقبل البريد. وsending.status هي حالة التوقيع كما رآها الفحص الأخير: verified أو pending أو failed أو no_identity أو unknown. وتبيّن sending.canSend ما إذا كان إرسال من النطاق سيُقبل الآن، والحكم السلبي الأقدم من يوم يُعدّ مجهولًا، لذا ينبغي للسكربت أن يتفرع على canSend لا على status. وما دامت خاطئة، يُرفض الإرسال من النطاق بـ 409 domain_not_sendable.
- يجري
domains createأول فحص DNS أثناء الاستدعاء، لذا تحمل كل مدخلة فيrecordsبالفعلstatus:foundأوmissingأو null حين لم تُفحص بعد. انشر كل سجل كما هو بالضبط، لأن القيم خاصة بالنطاق. - يفحص
domains verifyفورًا. وخلال 10 ثوانٍ من الفحص الأخير لا يفحص شيئًا جديدًا ويعيد النطاق كما هو. وفي النطاق المتحقَّق منه يفحص سجلات التوقيع من جديد، فتكونsendingمحدَّثة. - يفحص
domains getعلى نطاق غير متحقَّق منه من جديد حين يكون عمر الفحص الأخير أكثر من 20 ثانية، لذا يعمل استطلاعgetأيضًا ولا يحتاج إلا إلىdomains:read، حيث يحتاجverifyإلىdomains:write. - قد يستغرق السجل المنشور قبل لحظات بضع دقائق ليظهر في DNS العام.
في الطرفية، تطبع get وcreate وverify حقلًا واحدًا في كل سطر، مع الكتل المتداخلة مثل receiving وsending وrecords بصيغة JSON مضغوطة. أضف --json واقرأها بأداة مثل jq، كما تفعل الأمثلة أدناه.
نطاقات catch-all والتتبع والملفات
يغيّر domains update ثلاثة إعدادات لا يعتمد أحدها على الآخر. والخيار الذي تُغفله يُترك كما هو، ودون أي خيارات يعود النطاق دون تغيير.
| الخيار | ما يغيّره |
|---|---|
| --catch-all, --no-catch-all | التشغيل يقبل البريد إلى أي عنوان على النطاق لم ينشئه أحد، ويظهر العنوان في list-addresses منذ رسالته الأولى. والإيقاف يرفض البريد إلى كل عنوان لم يُنشأ يدويًا، بما فيها العناوين التي التقطها catch-all من قبل. ويبدأ النطاق الجديد وهو مفعّل |
| --tracking-host <value> | نطاق فرعي مثل links.acme.com للروابط المتتبَّعة وبكسل الفتح. وnull يزيله |
| --storage-host <value> | نطاق فرعي مثل files.acme.com لروابط تنزيل الملفات المرسلة من النطاق. وnull يزيله |
- يُحفظ المضيف الجديد ويُفحص في الاستدعاء نفسه. انشر سجل CNAME باسم
record.nameوالقيمةrecord.valueمن كتلةtrackingأوstorageفي الجواب، مع إيقاف أي وكالة. وإعداد مضيف من جديد قد يعطيه قيمة مختلفة، لذا انشر القيمة التي يبلّغ عنها أحدث جواب. - إلى أن ينجح فحص، يظهر المضيف بالحالة
pendingويبقى البريد الجديد على مضيف OpenEmail الافتراضي. وبمجرد نجاح فحص يظهر بالحالةactive. ويواصل OpenEmail الفحص من تلقاء نفسه، والمضيف النشط الذي يفشل في ثلاثة فحوص متتالية، أو الذي مضت ساعتان على آخر فحص ناجح له، يظهر بالحالةfailedبينما يعود البريد الجديد إلى المضيف الافتراضي. - أزل مضيفًا بـ
null، كما في--tracking-host null. والقيمة الفارغة مثل--tracking-host=خطأ استخدام في CLI وتخرج بالرمز2. - يحتاج المضيف الجديد إلى نطاق متحقَّق منه، أو على الأقل إلى نشر سجل TXT
_openemail-challengeالخاص به. وإلا رُفض الاستدعاء بـ 409domain_not_verified. - تُطبَّق الخيارات بالترتيب: catch-all، ثم نطاق التتبع، ثم نطاق الملفات. والخيار اللاحق الذي يُرفض قد يترك تغييرًا سابقًا محفوظًا، لذا أرسلها في استدعاءات منفصلة حين يجب أن يقوم كل منها بذاته.
العناوين على النطاق
يضم النطاق العناوين المنشأة يدويًا أو عبر API، وتلك التي التقطها catch-all حين وصلها البريد أول مرة. ويعرض list-addresses النوعين، بما فيها المعطّلة. أما catch-all نفسه فليس صفًا: إنه receiving.catchAll على النطاق.
- يأخذ
create-addressالخيار--local-part، أي الجزء الذي يسبق @، و--labelاختياريًا. ولا يلزم أن يكون النطاق متحقَّقًا منه بعد، لكن العنوان لا يستقبل شيئًا حتى يصبح كذلك. ويُرفض*وحده، لأن هذه هي كتابة catch-all. - إنشاء عنوان موجود بالفعل، أو عنوان أُزيل، ليس خطأ. يعود مفعّلًا، بالتسمية التي أرسلتها أو دونها، ويحتفظ بمعرّفه. والعنوان الذي التقطه catch-all يصبح عنوانًا منشأً يدويًا، فيبقى يستقبل بعد إيقاف catch-all.
- مع تشغيل catch-all، يبدأ العنوان الجديد بإعدادات catch-all الخاصة بكل عنوان، مثل توقيعه وتتبعه، عدا إعدادات الخصوصية. تُنسخ مرة واحدة ولا تُبقى متزامنة.
- يوقف
update-address --no-enabledاستقبال العنوان للبريد، فيتلقى المرسلون ارتدادًا، ولا يمكن الإرسال منه. ويحتفظ ببريده وإعداداته والأشخاص الذين يصلون إليه، ويكمل--enabledمن حيث توقف. ويعيد--labelتسميته، ويزيل--label nullالاسم. - يذهب
delete-addressأبعد من ذلك. يُرفض البريد إلى العنوان حتى مع تشغيل catch-all، وتتوقف إعادة توجيهه، وتُحذف إعداداته، ويفقد من مُنحوا الوصول إليه ذلك الوصول، ويُبطَل تسجيل الدخول إليه بكلمة المرور. ويبقى البريد الذي استقبله بالفعل في صندوق البريد. وإنشاؤه من جديد يعيد المعرّف نفسه، دون الإعدادات أو الصلاحيات القديمة.
ما يمكنك الإرسال باسمه
يجيب openemail addresses list عن السؤال الكامن وراء 403 from_address_forbidden: ما العناوين التي يجوز للمفتاح أو تسجيل الدخول الذي تستدعي به وضعها في From. ويحتاج إلى emails:send لا إلى نطاق قراءة، لأنه يصف ما سيقبله الإرسال.
- في الطرفية يطبع جدولين: العناوين، مع ما إذا كان كل منها مفعّلًا وما إذا كنت تستطيع الإرسال منه، ثم النطاقات، مع ما إذا كان كل منها متحقَّقًا منه للاستقبال وللإرسال، وcatch-all الخاص به.
- تكون
unrestrictedصحيحة حين لا يقيّد بيانات الاعتماد شيء. عندها يمكن الإرسال من أي جزء محلي على نطاقات مساحة العمل، بما فيها تلك التي لم ينشئها أحد. وإلا فلا تكونcanSendصحيحة إلا لعنوان مفعّل تغطيه بيانات الاعتماد، عبر نطاق كامل تحمله أو عبر قائمة عناوينها الخاصة. - تكون
canSendخاطئة للعنوان المعطّل، وللعنوان الذي لا تغطيه بيانات الاعتماد، وللعنوان الذي لا يستطيع نطاقه التوقيع بعد. - لا تُسرد إلا العناوين المنشأة. وبيانات الاعتماد التي تحمل نطاقًا كاملًا تستطيع الإرسال باسم أي جزء محلي عليه، والعنوان الموجود في قائمتها دون صندوق بريد خلفه يمكن الإرسال منه دون أن يظهر هنا.
- مع
--jsonيطبع{ unrestricted, addresses, domains, hasMore, nextCursor }لصفحة واحدة، و{ unrestricted, addresses, domains }مع--all، بدلًا من مستند{ items, hasMore, nextCursor }الذي تطبعه القوائم الأخرى. ومع--allفي أنبوب، أو مع--ndjson، يطبع عنوانًا واحدًا في كل سطر.
status وopen ومزوّدو DNS
يقرأ openemail status تسجيل دخولك وaddresses list وdomains list في الوقت نفسه ويطبعها معًا. يعرض جدول عناوين المرسل كل عنوان مع ما إذا كان يستطيع الإرسال وما إذا كان مفعّلًا. ويعرض جدول النطاقات كل نطاق بالحالة verified أو not verified للاستقبال، وحالة إرساله، وcatch-all الخاص به. ويعرض أول 100 من كل منهما ويذكر أمر --all للبقية.
- الجزء الذي لا يجوز لبيانات اعتمادك قراءته، مثل النطاقات دون
domains:readأو العناوين دونemails:send، يقول «غير متاح» مع السبب، ويُطبع الباقي على أي حال. - حين لا توجد عناوين بعد، يقترح
openemail domains create --domain example.com. - يطبع
openemail status --jsonكائنًا واحدًا فيهaccountوaddressesوdomainsوunavailable، حيث تعطيunavailableالسبب لكل جزء تعذرت قراءته.
ربط مزوّد DNS، كي تُكتب سجلات النطاق الجديد نيابةً عنك، لا يجري إلا في تطبيق الويب في 0.0.2. يفتح openemail open providers، أو open dns، تلك الصفحة. ويفتح open domains النطاقات وسجلات DNS الخاصة بها، وopen addresses العناوين. وإعادة التوجيه في تطبيق الويب أيضًا، ويفتحها open forwarding <address> لعنوان واحد. ويطبع --print الرابط بدلًا من فتح متصفح.
حيث كتب OpenEmail سجلات DNS للنطاق بنفسه، يستعيد domains delete تلك السجلات ويسرد في leftBehind ما تعذّر عليه استعادته، لتزيله أنت لدى مزوّد DNS. أما السجلات التي نشرتها بنفسك فلا تُمَس أبدًا، لذا أزلها أيضًا بعد ذهاب النطاق.
أمثلة
openemail domains create --domain acme.com --json > acme.jsonjq -r '.records[] | [.type, .name, .value, (.priority // "")] | @tsv' acme.jsonopenemail domains verify "$(jq -r .id acme.json)"id=b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6funtil openemail domains get "$id" --json | jq -e .receiving.verified > /dev/null; do sleep 30doneopenemail domains get "$id" --json | jq '.sending | {status, canSend, error}'openemail domains list-addresses "$id" --allopenemail domains create-address "$id" --local-part invoices --label Invoicesopenemail domains update "$id" --no-catch-all --dry-runopenemail domains update "$id" --no-catch-allإنشاء invoices يدويًا يُبقيه مستقبِلًا بعد إيقاف catch-all، بينما يُرفض البريد إلى كل عنوان آخر التقطه catch-all. ويطبع التشغيل التجريبي PATCH وجسمه دون إرساله.
openemail domains update "$id" --tracking-host links.acme.com --json | jq '.tracking | {status, record, error}'openemail domains update "$id" --tracking-host nulladdress_id=$(openemail domains list-addresses "$id" --all | jq -r 'select(.address == "[email protected]") | .id')openemail domains update-address "$id" "$address_id" --no-enabledopenemail domains delete-address "$id" "$address_id" --yesإيقاف العنوان أولًا يمكن التراجع عنه بـ --enabled. أما الحذف فلا، ويحتاج في السكربت إلى --yes. ومع تسجيل الدخول عبر المتصفح يطلب أيضًا رمز تحقق، لا يتخطاه --yes أبدًا.
openemail domains list --all | jq -r 'select(.sending.canSend | not) | [.domain, .sending.status] | @tsv'openemail addresses list --all --json | jq -r '.addresses[] | select(.canSend) | .address'النطاقات والتأكيدات والأخطاء
| النطاق | الأوامر |
|---|---|
| domains:read | domains list, get, list-addresses, get-address |
| domains:write | domains create, verify, update, delete, create-address, update-address, delete-address |
| emails:send | addresses list |
- تسجيل الدخول أو المفتاح الذي لا يملك النطاق يتوقف برمز الخروج
4، ويسمّي النطاق الناقص ويقول كيف تحصل عليه. - يطلب
domains deleteوdomains delete-addressمنك التأكيد. والإجابة بلا تخرج بالرمز10ولا تغيّر شيئًا. ومن دون إشراف ودون--yesيتوقفان برمز الخروج2قبل إرسال أي شيء. - مع تسجيل الدخول عبر المتصفح، يطلب هذان الحذفان أيضًا رمز تحقق، كما يفعل تطبيق الويب. ومن دون إشراف لا أحد يستطيع كتابته، فيتوقف الأمر برمز الخروج
4. شغّلopenemail verifyأولًا فلا تحتاج الدقائق الـ 60 التالية إلى رمز. ولا يُطلب من مفتاح API أبدًا. - يطبع
--dry-runالطلب الذي كان التغيير سيرسله، مع جسمه، ويخرج بالرمز0دون إرساله أو طلب التأكيد منك. - تقرأ القائمة صفحة واحدة: يأخذ
--limitمن 1 إلى 100 ويرسل الخادم 25 حين يُغفل، ويأخذ--cursorقيمةnextCursorمن الصفحة السابقة. ويقرأ--allكل صفحة، ويتوقف--max <n>بعد هذا العدد من العناصر، ويطبع--ndjson، أو--allفي أنبوب، كائن JSON واحدًا في كل سطر. ومع--jsonيطبعdomains listوlist-addressesمستند{ items, hasMore, nextCursor }واحدًا. - المفتاح أو تسجيل الدخول المقيّد بنطاقات أو عناوين معيّنة يظل يرى كل نطاق وعنوان. لكنه لا يستطيع إضافة نطاق، وكل تغيير آخر يحتاج إلى أن يكون النطاق كاملًا بين النطاقات التي يحملها، وإلا رُفض الاستدعاء بـ 422
capability_unsupported. - يخرج الرفض برمز حالته:
4لـ 403، مثلdomain_allowance_reachedحين لا تسمح الخطة بمزيد من النطاقات، و5لـ 404، و6لـ 409، مثلdomain_already_addedأوdomain_claimed، و7لـ 422، مثلinvalid_tracking_hostأوworkspace_limit_reached. - لا يمكن إزالة آخر نطاق في مساحة العمل من CLI. ذلك 409
last_domain، لأن إزالته تحذف صندوق البريد كله، وهو ما يطلب تطبيق الويب تأكيده أولًا. والنطاق الذي يضم عناوين حساب محجوزة يعطي 409domain_holds_reserved_addresses. - لا يُعاد
domains createوالحذفان أبدًا بعد فشل في الشبكة. و409domain_already_added، أو 404 في محاولتك الثانية بعد ضياع الجواب، يعني أن الأولى نجحت. أماverifyوupdateوcreate-addressوupdate-addressفتُعاد تلقائيًا، لأن إرسال أحدها مرتين يترك النتيجة نفسها.