الفصل 14 العملاء والعمل الجماعي وCLI المسؤول: #pApiAuth

المرجع الكامل لحقول API وCLI: جميع أنواع الكائنات الاثني عشر ونقاط نهاية REST وPOST /api/v1/send

يوثّق هذا المرجع كل خاصية JSON ونوع بيانات وقيمة تعداد (enum) وإعداد افتراضي والحد الأدنى لدور RBAC عبر جميع كائنات الإدارة الاثني عشر (/api/admin/cli/objects/{type} & nextxch-cli) بالإضافة إلى تسليم البريد الإلكتروني للمعاملات (POST /api/v1/send). استخدموا مربع التصفية الفوري أعلى الجدول للبحث عن أي خاصية مثل dkimSigningMode أو tlsMode أو allowedCidrs أو warmingEnabled.

نصيحة تشغيلية وملاحظة حول البنية

فحص مباشر في الطرفية أو عبر HTTP: يعرض كل nextxch هذا المخطط الكامل بصيغة JSON قابلة للقراءة آليًا على GET /api/admin/cli/schema (مع ترويسة SHA-256 باسم X-Nextxch-Schema-Version). وفي الطرفية، نفّذوا nextxch-cli describe <Type> (مثل nextxch-cli describe Domain أو nextxch-cli describe SmtpQueue) في أي وقت.

التسليم المعاملاتي

TransactionalSendRequest (POST /api/v1/send)

المفتاح: Idempotency-Key RBAC: User+
13 خاصية

نقطة نهاية HTTP JSON عالية الإنتاجية لتسليم البريد من تطبيقات الويب وأنظمة ERP وCRM ورموز 2FA، مع تحديد الأولوية حسب الفئة وإحماء IP والفحص المسبق لقائمة المنع وIdempotency لمدة 24 ساعة.

POST /api/v1/send يضع البريد الإلكتروني للمعاملات في قائمة الانتظار ويوقّعه (UTF-8 Multipart/Alternative + مرفقات)
POST /api/v1/unsubscribe/{token} نقطة نهاية عامة لإلغاء الاشتراك بنقرة واحدة وفق RFC 8058 (رمز موقّع بـ DKIM)
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ from string اختياري
الافتراضي: Key senderAddress
عنوان المرسل. يأخذ تلقائيًا القيمة الافتراضية senderAddress المرتبطة بالمفتاح لمفاتيح Role=User.
├─ to string[] مطلوب
مصفوفة عناوين البريد الإلكتروني للمستلمين الأساسيين (مطلوب عنوان واحد على الأقل).
├─ cc string[] اختياري
الافتراضي: []
مستلمو النسخة الكربونية الاختياريون.
├─ bcc string[] اختياري
الافتراضي: []
مستلمو النسخة المخفية الاختياريون.
├─ replyTo string اختياري
عنوان Reply-To اختياري.
├─ subject string مطلوب
سطر موضوع البريد الإلكتروني (UTF-8).
├─ textBody string اختياري
نص عادي (text/plain). يلزم وجود textBody أو htmlBody على الأقل.
├─ htmlBody string اختياري
نص HTML ‏(text/html). قدّموه مع textBody للحصول على قابلية تسليم 10/10.
├─ category string اختياري
الافتراضي: transactional
يحدد أولوية قائمة الانتظار وتجاوز تسخين IP ومجموعة حصة مزود المستلم.
Enum:"critical""transactional""notification""marketing"
├─ overflowMode string اختياري
الافتراضي: DeferQueue
السلوك عند بلوغ الحصة الساعية لمزود الوجهة (توزيع سلس عبر قائمة الانتظار مقابل HTTP 429 + Retry-After).
Enum:"DeferQueue""Reject429"
├─ idempotencyKey string اختياري
الافتراضي: Header Idempotency-Key
مفتاح إزالة تكرار حتمي (مثل رقم الفاتورة) يمنع الإرسال المكرر خلال 24 ساعة.
├─ headers Record<string, string> اختياري
الافتراضي: {}
قاموس ترويسات X مخصصة وفق RFC 5322.
├─ attachments SendAttachmentDto[] اختياري
الافتراضي: []
مصفوفة من { fileName: string, contentType: string, base64Content: string }.
{
  "from": "Abrechnung <rechnung@firma.de>",
  "to": ["einkauf@kunde.de"],
  "cc": ["buchhaltung@firma.de"],
  "subject": "Ihre elektronische Rechnung RE-2026-90412",
  "category": "transactional",
  "overflowMode": "DeferQueue",
  "textBody": "Guten Tag,\nanbei erhalten Sie Ihre Rechnung RE-2026-90412.",
  "htmlBody": "<p>Guten Tag,</p><p>anbei erhalten Sie Ihre Rechnung <strong>RE-2026-90412</strong>.</p>",
  "headers": {
    "X-ERP-Document-Id": "RE-2026-90412"
  },
  "attachments": [
    {
      "fileName": "RE-2026-90412.pdf",
      "contentType": "application/pdf",
      "base64Content": "JVBERi0xLjcKJcfs..."
    }
  ]
}
# 1) Kleinstprivilegierten Sende-Key (Role=User) für rechnung@firma.de erstellen:
nextxch-cli create ApiKey \
  --set label="ERP Rechnungsversand" \
  --set role=User \
  --set senderAddress=rechnung@firma.de \
  --set defaultCategory=transactional \
  --set allowedCidrs=10.20.0.0/16

# 2) Risikofreier Trockentest gegen die integrierte Sandbox-Sink-Domain:
# ok@sink.nextxch.local | bounce@sink.nextxch.local | defer@sink.nextxch.local
curl -fsS -X POST "https://mail.firma.de/api/v1/send" \
  -H "Authorization: Bearer smk_01968f2a_..." \
  -H "Idempotency-Key: inv-2026-90412" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "rechnung@firma.de",
    "to": ["einkauf@kunde.de"],
    "subject": "Ihre Rechnung RE-2026-90412",
    "category": "transactional",
    "textBody": "Guten Tag, anbei Ihre Rechnung RE-2026-90412.",
    "htmlBody": "<p>Guten Tag, anbei Ihre Rechnung <b>RE-2026-90412</b>.</p>"
  }'
using System.Net.Http.Headers;
using System.Net.Http.Json;

using var http = new HttpClient { BaseAddress = new Uri("https://mail.firma.de") };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "smk_01968f2a_...");
http.DefaultRequestHeaders.Add("Idempotency-Key", "inv-2026-90412");

var response = await http.PostAsJsonAsync("/api/v1/send", new
{
    from = "rechnung@firma.de",
    to = new[] { "einkauf@kunde.de" },
    subject = "Ihre Rechnung RE-2026-90412",
    category = "transactional",
    textBody = "Guten Tag, anbei Ihre Rechnung RE-2026-90412.",
    htmlBody = "<p>Guten Tag, anbei Ihre Rechnung <strong>RE-2026-90412</strong>.</p>"
});
response.EnsureSuccessStatusCode();
كائن Collection (CRUD)

IntegrationKey (API v1)

المفتاح: id RBAC: TenantAdmin+
9 خصائص

مفتاح تكامل بنطاقات صلاحيات لـ /api/v1. يعمل المفتاح باسم مستخدم واحد، أو كتكامل على مستوى المستأجر باسم المستخدم المذكور في ترويسة X-Nextxch-Act-As. ودون نطاق الصلاحية تجيب API بالرمز 403؛ ويؤدي مستخدم من مستأجر آخر إلى 404. اختياريًا OAuth 2.0 client credentials (الرمز صالح لمدة ساعة واحدة).

POST /api/admin/integrations/keys إنشاء مفتاح (للمسؤول، يُعرض مرة واحدة)
PUT /api/admin/integrations/keys/{id} تغيير النطاقات
DELETE /api/admin/integrations/keys/{id} إلغاء مفتاح (ورموز OAuth الخاصة به)
POST /api/v1/oauth/token OAuth 2.0 client_credentials: معرّف المفتاح + المفتاح للحصول على رمز وصول
GET /api/v1/me المفتاح والنطاقات والمستخدم المنفّذ
GET /api/v1/openapi.json مستند OpenAPI 3.1 الخاص بالتثبيت
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ label string مطلوب
التسمية، مثل CRM أو ERP.
├─ mode string مطلوب
الافتراضي: user
user: يعمل دائمًا باسم userEmail. tenant: يعمل باسم X-Nextxch-Act-As (لمستخدمي المستأجر نفسه فقط).
Enum:"user""tenant"
├─ userEmail string اختياري
المستخدم عند mode=user.
├─ scopes string[] مطلوب
الأذونات؛ .write يشمل .read. أما crypto.read وcrypto.manage (S/MIME وPGP) فمحجوزان.
Enum:"calendar.read""calendar.write""rooms.read""booking.read""booking.write""contacts.read""contacts.write""directory.read""sharing.manage""webhooks.manage""mail.send"
├─ domainId guid اختياري
تكامل المستأجر مقتصر على مستخدمي هذا النطاق.
├─ allowedCidrs string[] اختياري
الافتراضي: []
شبكات IP المسموح بها.
├─ expiresInDays integer اختياري
مدة الصلاحية بالأيام (فارغ: غير محدودة).
├─ senderAddress string اختياري
المرسل لـ mail.send (POST /api/v1/send).
├─ apiKey string للقراءة فقط
smk_<id>_<secret>، فقط في استجابة الإنشاء؛ ولا تُخزَّن سوى قيمة التجزئة.
{
  "label": "CRM",
  "mode": "tenant",
  "scopes": ["calendar.write", "rooms.read", "contacts.write", "webhooks.manage"],
  "allowedCidrs": ["203.0.113.0/24"],
  "expiresInDays": 365
}
# Integrations-Schlüssel: Admin > API & Integrationen > Neuer Schlüssel
# Danach z. B. ein Access-Token per OAuth 2.0 Client Credentials holen:
curl -fsS -X POST "https://mail.firma.de/api/v1/oauth/token" \
  -d grant_type=client_credentials \
  -d client_id=0196c3a2-5f1e-7c11-9a20-1c2d3e4f5a6b \
  -d client_secret=smk_0196c3a25f1e7c119a201c2d3e4f5a6b_... \
  -d scope="calendar.read rooms.read"
curl -fsS "https://mail.firma.de/api/v1/me" \
  -H "Authorization: Bearer smk_0196c3a2..." \
  -H "X-Nextxch-Act-As: anna@firma.de"
using var http = new HttpClient { BaseAddress = new Uri("https://mail.firma.de") };
http.DefaultRequestHeaders.Authorization = new("Bearer", "smk_0196c3a2...");
http.DefaultRequestHeaders.Add("X-Nextxch-Act-As", "anna@firma.de");
var me = await http.GetFromJsonAsync<JsonElement>("/api/v1/me");
كائن Collection (CRUD)

CalendarEvent (API v1)

المفتاح: hrefName RBAC: User+
12 خاصية

مواعيد مع سلاسل واستثناءات، والحضور، والغرف، والدعوات، والردود، ومتوفر/مشغول، والتقويمات المشتركة والعامة، وروابط الدعوة. النطاقات calendar.read وcalendar.write. الأوقات بتوقيت UTC (ISO-8601)، والمناطق الزمنية بأسماء IANA.

GET /api/v1/calendars تقويمات خاصة ومشتركة وعامة وتقويمات الموارد
GET /api/v1/calendar/events?from&to&calendarId&limit&cursor التكرارات ضمن نافذة زمنية (السلسلة موسّعة)
POST /api/v1/calendar/events إنشاء موعد (دعوة أشخاص وغرف)
GET /api/v1/calendar/events/{hrefName} موعد مع سلسلة واستثناءات
PUT /api/v1/calendar/events/{hrefName} تغيير؛ scope=occurrence|following لأجزاء من سلسلة
DELETE /api/v1/calendar/events/{hrefName} حذف، مع إلغاءات اختيارية (notify=true)
POST /api/v1/calendar/events/{hrefName}/respond الرد على دعوة
POST /api/v1/calendar/events/{hrefName}/invite-link رابط دعوة موقّع
GET /api/v1/calendar/events/{hrefName}/ics iCalendar خام
POST /api/v1/calendar/freebusy حالة متوفر/مشغول للأشخاص والغرف
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ title string مطلوب
العنوان.
├─ startUtc datetime مطلوب
البدء بتوقيت UTC.
├─ endUtc datetime مطلوب
النهاية بتوقيت UTC.
├─ timeZone string اختياري
الافتراضي: Europe/Berlin
المنطقة الزمنية IANA للموعد (السلسلة، العرض).
├─ allDay boolean اختياري
الافتراضي: false
طوال اليوم.
├─ attendees Attendee[] اختياري
الافتراضي: []
{ email, name, role }؛ وتقبل الغرف والموارد الدعوات أو ترفضها وفق قواعدها.
├─ sendInvitations boolean اختياري
الافتراضي: false
إرسال دعوات iMIP.
├─ recurrence التكرار اختياري
{ freq, interval, byDay, byMonthDay, count, until }.
├─ showAs string اختياري
الافتراضي: busy
إظهار كـ.
Enum:"free""tentative""busy""oof""workingElsewhere"
├─ isPrivate boolean اختياري
الافتراضي: false
خاص (التفاصيل للمالك فقط).
├─ calendarId string اختياري
التقويم الهدف ownerId:slug مع صلاحيات الكتابة.
├─ teamsMeeting boolean اختياري
إنشاء اجتماع Microsoft Teams.
{
  "title": "Projektstart",
  "startUtc": "2026-12-03T09:00:00Z",
  "endUtc": "2026-12-03T10:00:00Z",
  "timeZone": "Europe/Berlin",
  "attendees": [
    { "email": "bernd@firma.de" },
    { "email": "raum-1@firma.de" }
  ],
  "sendInvitations": true
}
# Benötigte Scopes: calendar.read (lesen), calendar.write (schreiben)
# Einen Raum buchen: Raumadresse als Teilnehmer eintragen
curl -fsS -X POST "https://mail.firma.de/api/v1/calendar/events" \
  -H "Authorization: Bearer smk_0196c3a2..." \
  -H "X-Nextxch-Act-As: anna@firma.de" \
  -H "Content-Type: application/json" \
  -d '{"title":"Projektstart","startUtc":"2026-12-03T09:00:00Z","endUtc":"2026-12-03T10:00:00Z","timeZone":"Europe/Berlin","attendees":[{"email":"raum-1@firma.de"}]}'
var res = await http.PostAsJsonAsync("/api/v1/calendar/events", new
{
    title = "Projektstart",
    startUtc = DateTimeOffset.Parse("2026-12-03T09:00:00Z"),
    endUtc = DateTimeOffset.Parse("2026-12-03T10:00:00Z"),
    timeZone = "Europe/Berlin",
    attendees = new[] { new { email = "raum-1@firma.de" } }
});
string href = (await res.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("data").GetProperty("hrefName").GetString()!;
كائن Collection (CRUD)

Rooms & Booking (API v1)

المفتاح: id RBAC: User+
6 خصائص

الغرف والموارد مع التوفر (rooms.read) وصفحات الحجز على غرار Calendly (booking.read وbooking.write): صفحة الحجز، وأنواع المواعيد، والفترات المتاحة، وقراءة الحجوزات وإلغاؤها. وتُحجز الغرفة عبر موعد تكون فيه الغرفة مشاركًا.

GET /api/v1/rooms?startUtc&endUtc&category الغرف والموارد، مع الأوقات المتاحة في النافذة الزمنية
GET /api/v1/rooms/{email}/availability أوقات انشغال غرفة واحدة
GET /api/v1/booking/profile صفحة الحجز مع ساعات العمل وأنواع المواعيد
GET /api/v1/booking/event-types أنواع الأحداث
POST /api/v1/booking/event-types إنشاء نوع موعد
GET /api/v1/booking/event-types/{id}/slots?from&to أوقات البدء المتاحة (42 يومًا كحد أقصى)
GET /api/v1/booking/bookings?status&from&to الحجوزات
POST /api/v1/booking/bookings/{id}/cancel إلغاء حجز (يُبلَّغ الضيف)
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ slots[].startUtc datetime للقراءة فقط
بداية الوقت المتاح بتوقيت UTC.
├─ slots[].endUtc datetime للقراءة فقط
النهاية (البداية زائد المدة).
├─ slots[].staff object[] للقراءة فقط
الموظفون المتاحون لأنواع مواعيد الفريق.
├─ status string للقراءة فقط
حالة الحجز.
Enum:"confirmed""cancelled"
├─ guest object للقراءة فقط
{ name, email, phone, timeZone }.
├─ free boolean للقراءة فقط
الغرفة متاحة في الفترة الزمنية.
{
  "ok": true,
  "data": {
    "eventTypeId": "beratung-3f2a",
    "durationMinutes": 30,
    "timeZone": "Europe/Berlin",
    "slots": [
      { "startUtc": "2026-12-04T08:00:00Z", "endUtc": "2026-12-04T08:30:00Z", "staff": [] }
    ]
  }
}
# Benötigte Scopes: rooms.read, booking.read, booking.write
curl -fsS "https://mail.firma.de/api/v1/rooms?startUtc=2026-12-03T09:00:00Z&endUtc=2026-12-03T10:00:00Z" \
  -H "Authorization: Bearer smk_0196c3a2..."
var slots = await http.GetFromJsonAsync<JsonElement>("/api/v1/booking/event-types/beratung/slots");
foreach (var s in slots.GetProperty("data").GetProperty("slots").EnumerateArray())
    Console.WriteLine(s.GetProperty("startUtc").GetString());
كائن Collection (CRUD)

Contact, Directory & Sharing (API v1)

المفتاح: hrefName RBAC: User+
9 خصائص

جهات الاتصال الشخصية مع جميع الحقول والصورة (contacts.read وcontacts.write وIf-Match للحماية من التعارض)، وقائمة العناوين العامة (directory.read)، والمشاركات والتفويض (sharing.manage، والتفويض = إذن على صندوق البريد مع sendAs أو sendOnBehalf).

GET /api/v1/contacts?q البحث في جهات الاتصال
POST /api/v1/contacts إنشاء جهة اتصال
PUT /api/v1/contacts/{hrefName} تعديل جهة اتصال (الحقول الفارغة null تبقى كما هي)
DELETE /api/v1/contacts/{hrefName} حذف جهة اتصال
GET /api/v1/directory?q&type قائمة العناوين العامة
GET /api/v1/sharing/grants الأذونات الخاصة
PUT /api/v1/sharing/grants تعيين تفويض أو إزالته
GET /api/v1/sharing/shared-with-me مُشارَك معي
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ givenName string اختياري
الاسم الأول.
├─ familyName string اختياري
اسم العائلة.
├─ organization string اختياري
الشركة.
├─ emails TypedValue[] اختياري
الافتراضي: []
{ type: work|home|other, value }.
├─ phones TypedValue[] اختياري
الافتراضي: []
{ type: cell|work|home|fax, value }.
├─ addresses Address[] اختياري
الافتراضي: []
{ type, street, city, region, postalCode, country }.
├─ birthday string اختياري
yyyy-MM-dd أو --MM-dd.
├─ photo string للكتابة فقط (سري)
data:image/jpeg;base64,... (بحد أقصى 512 KB)، والقيمة الفارغة تحذف الصورة.
├─ permissions string[] اختياري
حقوق المنحة (PUT /sharing/grants).
Enum:"freeBusy""read""write""delete""sendOnBehalf""sendAs""manage"
{
  "givenName": "Clara",
  "familyName": "Kunde",
  "organization": "Kunde AG",
  "emails": [{ "type": "work", "value": "clara@kunde.example" }],
  "phones": [{ "type": "cell", "value": "+49 170 1234567" }]
}
# Benötigte Scopes: contacts.read, contacts.write, directory.read, sharing.manage
curl -fsS -X POST "https://mail.firma.de/api/v1/contacts" \
  -H "Authorization: Bearer smk_0196c3a2..." \
  -H "Content-Type: application/json" \
  -d '{"givenName":"Clara","familyName":"Kunde","emails":[{"type":"work","value":"clara@kunde.example"}]}'
await http.PutAsJsonAsync("/api/v1/sharing/grants", new
{
    kind = "calendar", granteeType = "user", grantee = "bernd@firma.de", permissions = new[] { "read" }
});
كائن Collection (CRUD)

Webhook (API v1)

المفتاح: id RBAC: User+
4 خصائص

الأحداث بوصفها طلب JSON POST موقّعًا: calendar.event.created وcalendar.event.updated وcalendar.event.deleted وcalendar.invitation.replied وbooking.created وbooking.rescheduled وbooking.cancelled. التوقيع X-Nextxch-Signature: v1=hex(HMAC-SHA256(secret, X-Nextxch-Timestamp + "." + body)). إعادة المحاولة بعد 30 ثانية ودقيقتين و10 دقائق وساعة واحدة و6 ساعات.

GET /api/v1/webhooks Webhooks الخاصة بالمستأجر
POST /api/v1/webhooks تسجيل webhook (السر في الاستجابة فقط)
DELETE /api/v1/webhooks/{id} حذف webhook
GET /api/v1/webhooks/{id}/deliveries عمليات التسليم الأخيرة
POST /api/v1/webhooks/{id}/test إرسال حدث تجريبي
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ url string مطلوب
هدف HTTPS (العناوين الداخلية محظورة).
├─ events string[] مطلوب
المواعيد؛ يحتاج المفتاح إلى نطاقات .read المطابقة.
Enum:"calendar.event.created""calendar.event.updated""calendar.event.deleted""calendar.invitation.replied""booking.created""booking.rescheduled""booking.cancelled""*"
├─ secret string للقراءة فقط
whsec_...، عند الإنشاء فقط؛ ويُخزَّن مشفرًا.
├─ id (Ereignis) string للقراءة فقط
evt_... ثابت لكل تغيير، لإزالة التكرار.
{
  "id": "evt_5c1f0e9a2b7d4c3e8f601a2b",
  "type": "calendar.invitation.replied",
  "createdAtUtc": "2026-12-01T10:15:02Z",
  "tenantId": "0196c3a2-0000-7000-8000-000000000001",
  "data": {
    "calendarId": "0196c3a25f1e7c11:default",
    "hrefName": "0196c3a2@nextxch.ics",
    "title": "Projektstart",
    "startUtc": "2026-12-03T09:00:00Z",
    "attendee": { "email": "bernd@firma.de", "partStat": "ACCEPTED" }
  }
}
# Signatur prüfen (Bash):
# expected="v1=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)"
curl -fsS -X POST "https://mail.firma.de/api/v1/webhooks" \
  -H "Authorization: Bearer smk_0196c3a2..." \
  -H "Content-Type: application/json" \
  -d '{"url":"https://crm.firma.de/hooks/nextxch","events":["calendar.event.created","booking.created"]}'
// ASP.NET Core receiver
app.MapPost("/hooks/nextxch", async (HttpRequest req) =>
{
    using var ms = new MemoryStream();
    await req.Body.CopyToAsync(ms);
    string ts = req.Headers["X-Nextxch-Timestamp"]!;
    byte[] mac = HMACSHA256.HashData(Encoding.UTF8.GetBytes(secret), [.. Encoding.ASCII.GetBytes(ts + "."), .. ms.ToArray()]);
    return req.Headers["X-Nextxch-Signature"] == "v1=" + Convert.ToHexStringLower(mac) ? Results.Ok() : Results.Unauthorized();
});
كائن Collection (CRUD)

Tenant

المفتاح: slug RBAC: ServerAdmin+
11 خاصية

حدود مؤسسة متعددة المستأجرين تعزل النطاقات والجهات الأساسية وحصص التخزين (GiB) والاحتفاظ الافتراضي للامتثال وفق GoBD WORM.

GET /api/admin/cli/objects/Tenant يسرد جميع المستأجرين
GET /api/admin/cli/objects/Tenant/{slugOrId} يجلب المستأجر حسب slug أو UUID
POST /api/admin/cli/objects/Tenant ينشئ مستأجرًا جديدًا
PATCH /api/admin/cli/objects/Tenant/{slugOrId} يحدّث حصص المستأجر في مكانها
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ id guid للقراءة فقط
الافتراضي: UUIDv7
معرّف UUIDv7 داخلي ثابت.
├─ slug string PRIMARY KEY
مفتاح فريد آمن للاستخدام في URL للمستأجر (مثل "default" أو "acme").
├─ name string مطلوب
اسم عرض المؤسسة المقروء.
├─ isActive boolean اختياري
الافتراضي: true
تفعيل المستأجر أو تعليقه.
├─ maxDomains integer اختياري
الافتراضي: 100
الحد الأقصى للنطاقات المسموح بها في هذا المستأجر.
├─ maxPrincipals integer اختياري
الافتراضي: 10000
الحد الأقصى للحسابات وقوائم التوزيع.
├─ quotaGb integer اختياري
الافتراضي: 100
الحد الأقصى لتخزين المستأجر بوحدة GiB.
├─ outboundDailyLimit integer اختياري
الافتراضي: 25000
الحد الأقصى لرسائل البريد الصادرة يوميًا على مستوى المستأجر.
├─ defaultLockMode string اختياري
الافتراضي: Normal
وضع قفل GoBD WORM الافتراضي للنطاقات المُنشأة حديثًا.
Enum:"Normal""Governance""Compliance""LegalHold"
├─ defaultRetentionDays integer اختياري
الافتراضي: 0
فترة الاحتفاظ الإلزامية الافتراضية بالأيام (3650 = 10 سنوات وفق GoBD).
├─ createdAtUtc datetime للقراءة فقط
الطابع الزمني للإنشاء بتوقيت UTC.
{
  "slug": "acme",
  "name": "ACME Logistik GmbH",
  "isActive": true,
  "maxDomains": 50,
  "maxPrincipals": 2500,
  "quotaGb": 250,
  "outboundDailyLimit": 25000,
  "defaultLockMode": "Compliance",
  "defaultRetentionDays": 3650
}
# Mandant anlegen:
nextxch-cli create Tenant \
  --set slug=acme \
  --set name="ACME Logistik GmbH" \
  --set quotaGb=250 \
  --set defaultLockMode=Compliance \
  --set defaultRetentionDays=3650

# Mandant abfragen & Kontingent erhöhen:
nextxch-cli get Tenant acme
nextxch-cli update Tenant acme --set quotaGb=500
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/Tenant" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"slug":"acme","name":"ACME Logistik GmbH","quotaGb":250,"defaultLockMode":"Compliance","defaultRetentionDays":3650}'
var payload = new
{
    slug = "acme",
    name = "ACME Logistik GmbH",
    quotaGb = 250,
    defaultLockMode = "Compliance",
    defaultRetentionDays = 3650
};
using var res = await http.PostAsJsonAsync("/api/admin/cli/objects/Tenant", payload);
كائن Collection (CRUD)

Domain

المفتاح: name RBAC: TenantAdmin+
19 خاصية

نطاق بريد مستضاف مع توليد تلقائي متوازٍ لمفاتيح Dual-DKIM ‏(RSA-2048 + Ed25519)، وسياسة احتفاظ GoBD WORM، والعناوين الإضافية (Plus-Addressing)، وحدود المعدل.

GET /api/admin/cli/objects/Domain يسرد جميع النطاقات
GET /api/admin/cli/objects/Domain/{name} يجلب إعدادات النطاق ومحددات DKIM
POST /api/admin/cli/objects/Domain ينشئ النطاق ويولّد مفاتيح DKIM من نوع RSA-2048 + Ed25519
PATCH /api/admin/cli/objects/Domain/{name} يحدّث وضع DKIM أو الحصص أو الاحتفاظ في 0 ms
GET /api/admin/cli/dns/{name}?live=true يتحقق من سجلات DNS المباشرة أو يصدّر منطقة BIND وفق RFC 1035
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ id guid للقراءة فقط
الافتراضي: UUIDv7
معرّف UUIDv7 الداخلي للنطاق.
├─ name string PRIMARY KEY
اسم نطاق DNS (مثل "muster-logistik.de").
├─ tenant string اختياري
الافتراضي: default
المعرّف المختصر (slug) أو GUID للمستأجر المالك.
├─ isActive boolean اختياري
الافتراضي: true
تفعيل النطاق أو إيقافه مؤقتًا.
├─ postmasterAddress string اختياري
الافتراضي: postmaster@<name>
عنوان اتصال postmaster وفق RFC 5321.
├─ dkimSigningMode string اختياري
الافتراضي: Dual
وضع توقيع DKIM النشط (يوقّع Dual بكل من RSA-2048 وEd25519).
Enum:"Rsa2048""Ed25519""Dual"
├─ dkimRsaSelector string اختياري
الافتراضي: s2026
محدد DNS لـ RSA-2048.
├─ dkimRsaDnsName string للقراءة فقط
الافتراضي: s2026._domainkey.<name>
اسم FQDN المحسوب لـ _domainkey الخاص بـ RSA-2048.
├─ dkimEd25519Selector string اختياري
الافتراضي: ed2026
محدِّد DNS لـ Ed25519.
├─ dkimEd25519DnsName string للقراءة فقط
الافتراضي: ed2026._domainkey.<name>
اسم FQDN المحسوب لـ Ed25519 _domainkey.
├─ retentionLockMode string اختياري
الافتراضي: Normal
وضع قفل أرشيف GoBD بنظام WORM لهذا النطاق.
Enum:"Normal""Governance""Compliance""LegalHold"
├─ retentionDays integer اختياري
الافتراضي: 0
مدة الاحتفاظ الإلزامية بالأيام (3650 = 10 سنوات وفق GoBD).
├─ quotaGb integer اختياري
الافتراضي: 50
الحد الأقصى لتخزين النطاق بوحدة GiB.
├─ maxMessageSizeMb integer اختياري
الافتراضي: 50
الحد الأقصى لحجم الرسالة بوحدة MiB.
├─ maxAccounts integer اختياري
الافتراضي: 1000
الحد الأقصى لصناديق البريد في هذا النطاق.
├─ outboundDailyLimit integer اختياري
الافتراضي: 5000
الحد اليومي للإرسال الصادر لهذا النطاق.
├─ outboundHourlyLimit integer اختياري
الافتراضي: 1000
حد الإرسال الصادر في الساعة لهذا النطاق.
├─ usePlusAddressing boolean اختياري
الافتراضي: true
يفعّل العنونة بعلامة الجمع وفق RFC 5233 (user+tag@domain).
├─ createdAtUtc datetime للقراءة فقط
الطابع الزمني للإنشاء بتوقيت UTC.
{
  "name": "muster-logistik.de",
  "tenant": "default",
  "isActive": true,
  "postmasterAddress": "postmaster@muster-logistik.de",
  "dkimSigningMode": "Dual",
  "dkimRsaSelector": "s2026",
  "dkimEd25519Selector": "ed2026",
  "retentionLockMode": "Compliance",
  "retentionDays": 3650,
  "quotaGb": 100,
  "maxMessageSizeMb": 50,
  "maxAccounts": 500,
  "outboundDailyLimit": 10000,
  "outboundHourlyLimit": 2000,
  "usePlusAddressing": true
}
# Domain mit Dual-DKIM und 10 Jahren GoBD-Compliance anlegen:
nextxch-cli create Domain \
  --set name=muster-logistik.de \
  --set dkimSigningMode=Dual \
  --set retentionLockMode=Compliance \
  --set retentionDays=3650

# Fertige RFC-1035 BIND-Zonendatei exportieren & DNS live prüfen:
nextxch-cli dns muster-logistik.de --bind > muster-logistik.de.zone
nextxch-cli dns muster-logistik.de --live
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/Domain/muster-logistik.de" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"dkimSigningMode":"Dual","retentionLockMode":"Compliance","retentionDays":3650}'
using var res = await http.PatchAsJsonAsync(
    "/api/admin/cli/objects/Domain/muster-logistik.de",
    new { dkimSigningMode = "Dual", quotaGb = 200 });
res.EnsureSuccessStatusCode();
كائن Collection (CRUD)

Account (Account/User & Account/List)

المفتاح: email RBAC: TenantAdmin+
18 خاصية

يمثل صندوق بريد مستخدم (@type="User"، مع IMAP/JMAP/CalDAV/CardDAV/ActiveSync) أو قائمة توزيع (@type="List" مع members[]).

GET /api/admin/cli/objects/Account?filter=role=TenantAdmin يسرد/يصفّي الحسابات وقوائم التوزيع
POST /api/admin/cli/objects/Account/User ينشئ صندوق بريد مستخدم جديدًا مع مجلدات RFC 6154
POST /api/admin/cli/objects/Account/List ينشئ قائمة توزيع جديدة
PATCH /api/admin/cli/objects/Account/{email} يحدّث حصة التخزين أو إعادة التوجيه أو الرد التلقائي أو كلمة المرور
DELETE /api/admin/cli/objects/Account/{email} يحذف الحساب حذفًا مبدئيًا (Soft Delete)
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ id guid للقراءة فقط
الافتراضي: UUIDv7
معرّف UUIDv7 الداخلي للكيان.
├─ @type string اختياري
الافتراضي: User
نوع الحساب: صندوق بريد مستخدم (User) أو مجموعة توزيع (List).
Enum:"User""List"
├─ email string PRIMARY KEY
عنوان البريد الإلكتروني الأساسي لصندوق البريد أو القائمة.
├─ displayName string اختياري
الافتراضي: Lokalteil
اسم العرض الظاهر في Webmail وقائمة العناوين العامة (GAL) وترويسات From.
├─ password string للكتابة فقط (سري)
كلمة مرور بنص عادي عند الإنشاء/التحديث (تُجزّأ فورًا بـ Argon2id).
├─ role string اختياري
الافتراضي: User
دور RBAC الإداري.
Enum:"User""ComplianceAuditor""TenantAdmin""ServerAdmin"
├─ isActive boolean اختياري
الافتراضي: true
تفعيل الحساب أو تعليقه.
├─ quotaMb integer اختياري
الافتراضي: 5120
حصة تخزين صندوق البريد بوحدة MiB (5120 = 5 GiB).
├─ usedBytes long للقراءة فقط
الافتراضي: 0
استخدام التخزين الحالي لصندوق البريد بالبايت.
├─ outboundDailyLimit integer اختياري
الافتراضي: 500
حد الرسائل الصادرة يوميًا لهذا الحساب.
├─ forwardAddress string اختياري
عنوان بريد إلكتروني اختياري لوجهة إعادة التوجيه الآمنة وفق SRS.
├─ forwardKeepOriginal boolean اختياري
الافتراضي: true
الاحتفاظ بنسخة محلية في INBOX عند تفعيل إعادة التوجيه.
├─ vacationEnabled boolean اختياري
الافتراضي: false
تفعيل الرد التلقائي على البريد أثناء الغياب.
├─ vacationSubject string اختياري
موضوع الرد التلقائي (خارج المكتب).
├─ vacationBody string للكتابة فقط (سري)
نص الرد التلقائي (خارج المكتب).
├─ twoFactorEnabled boolean للقراءة فقط
الافتراضي: false
يشير إلى ما إذا كان TOTP 2FA نشطًا.
├─ members string[] اختياري
الافتراضي: []
عناوين البريد الإلكتروني للأعضاء (لـ @type="List").
├─ createdAtUtc datetime للقراءة فقط
الطابع الزمني للإنشاء بتوقيت UTC.
{
  "@type": "User",
  "email": "anna.weber@muster-logistik.de",
  "displayName": "Anna Weber (IT-Leitung)",
  "password": "SicheresStartPasswort!2026",
  "role": "TenantAdmin",
  "isActive": true,
  "quotaMb": 15360,
  "outboundDailyLimit": 1000,
  "forwardAddress": null,
  "forwardKeepOriginal": true,
  "vacationEnabled": false,
  "vacationSubject": "Abwesenheitsnotiz: Anna Weber",
  "vacationBody": "Ich bin ab Montag wieder erreichbar."
}
# Benutzerpostfach (15 GiB Quota) anlegen:
nextxch-cli create Account/User \
  --set email=anna.weber@muster-logistik.de \
  --set displayName="Anna Weber" \
  --set password="SicheresStartPasswort!2026" \
  --set quotaMb=15360

# Verteilerliste anlegen:
nextxch-cli create Account/List \
  --set email=team@muster-logistik.de \
  --set displayName="Disposition & Einkauf" \
  --set members=anna.weber@muster-logistik.de,dispo@muster-logistik.de
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/Account/User" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"email":"anna.weber@muster-logistik.de","displayName":"Anna Weber","password":"SicheresStartPasswort!2026","quotaMb":15360}'
await http.PostAsJsonAsync("/api/admin/cli/objects/Account/User", new
{
    email = "anna.weber@muster-logistik.de",
    displayName = "Anna Weber",
    password = "SicheresStartPasswort!2026",
    quotaMb = 15360
});
كائن Collection (CRUD)

Alias

المفتاح: address RBAC: TenantAdmin+
7 خصائص

اسم مستعار ثانوي للبريد الإلكتروني أو اسم مستعار مقنّع مؤقت للخصوصية يُوجَّه إلى صندوق بريد Account أساسي أو قائمة توزيع.

GET /api/admin/cli/objects/Alias يسرد جميع الأسماء المستعارة وعناوين البريد المقنّعة
POST /api/admin/cli/objects/Alias ينشئ اسمًا مستعارًا جديدًا يُوجَّه إلى صندوق بريد هدف
PATCH /api/admin/cli/objects/Alias/{address} يفعّل اسمًا مستعارًا أو يوقفه مؤقتًا أو يحدّث هدفه
DELETE /api/admin/cli/objects/Alias/{address} يحذف الاسم المستعار
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ address string PRIMARY KEY
عنوان البريد الإلكتروني للاسم المستعار.
├─ target string مطلوب
عنوان البريد الإلكتروني للحساب الأساسي المستهدف.
├─ principalId guid للقراءة فقط
UUID للكيان الهدف بعد الحل.
├─ description string اختياري
الافتراضي: ""
ملاحظة الغرض أو تسمية الخدمة الخارجية (تظهر أيضًا في محرر الرسائل في Webmail).
├─ isMasked boolean اختياري
الافتراضي: false
يُعلِّم الاسم المستعار كاسم مستعار مقنّع لحماية الخصوصية.
├─ isEnabled boolean اختياري
الافتراضي: true
عند القيمة false، يُرفض البريد المرسل إلى هذا الاسم المستعار دون تحرير العنوان.
├─ createdAtUtc datetime للقراءة فقط
الطابع الزمني للإنشاء بتوقيت UTC.
{
  "address": "shop-8f2k@muster-logistik.de",
  "target": "anna.weber@muster-logistik.de",
  "description": "Fachbuchhandlung / Online-Bestellung",
  "isMasked": true,
  "isEnabled": true
}
# Masked-Email-Alias anlegen:
nextxch-cli create Alias \
  --set address=shop-8f2k@muster-logistik.de \
  --set target=anna.weber@muster-logistik.de \
  --set description="Fachbuchhandlung" \
  --set isMasked=true

# Alias bei Spam-Aufkommen mit 1 Befehl stummschalten:
nextxch-cli update Alias shop-8f2k@muster-logistik.de --set isEnabled=false
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/Alias" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"address":"vertrieb@muster-logistik.de","target":"anna.weber@muster-logistik.de","description":"Vertrieb & Angebote"}'
await http.PostAsJsonAsync("/api/admin/cli/objects/Alias", new
{
    address = "vertrieb@muster-logistik.de",
    target = "anna.weber@muster-logistik.de",
    description = "Vertrieb & Angebote",
    isEnabled = true
});
كائن Collection (CRUD)

ApiKey

المفتاح: id RBAC: TenantAdmin+
11 خاصية

مفتاح API محصور (Scoped API Key) ثابت ومقيّد بـ RBAC وCIDR (smk_<id>_<secret>) لـ /api/v1/send أو SCIM 2.0 أو nextxch-cli.

GET /api/admin/cli/objects/ApiKey يسرد مفاتيح API النشطة (دون السر)
POST /api/admin/cli/objects/ApiKey ينشئ مفتاح API جديدًا ويعيد apiKey (smk_...) مرة واحدة
DELETE /api/admin/cli/objects/ApiKey/{id} يُبطل مفتاح API فورًا
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ id guid للقراءة فقط
الافتراضي: UUIDv7
UUID مفتاح فريد (يُستخدم للإلغاء عبر DELETE).
├─ apiKey string إنشاء فقط
الافتراضي: smk_<id>_<secret>
يُعاد رمز Bearer الكامل مرة واحدة فقط عند الإنشاء.
├─ label string مطلوب
تسمية مقروءة للبشر (مثل "Ansible GitOps" أو "Shopware 6").
├─ role string اختياري
الافتراضي: TenantAdmin
نطاق الصلاحيات (يقتصر User حصرًا على POST /api/v1/send).
Enum:"User""ComplianceAuditor""TenantAdmin""ServerAdmin"
├─ senderAddress string اختياري
عنوان المرسل المصرّح به (مطلوب عند role="User").
├─ defaultCategory string اختياري
الافتراضي: transactional
فئة الإرسال الافتراضية لهذا المفتاح.
Enum:"critical""transactional""notification""marketing"
├─ allowedCidrs string[] اختياري
الافتراضي: [] (Alle IPs)
شبكات CIDR المصدرية المسموح بها لـ IPv4/IPv6.
├─ expiresInDays integer للكتابة فقط (سري)
الافتراضي: null (Kein Ablauf)
انتهاء صلاحية تلقائي اختياري بالأيام من تاريخ الإنشاء.
├─ expiresAtUtc datetime للقراءة فقط
الطابع الزمني المحسوب لانتهاء الصلاحية بتوقيت UTC.
├─ outboundDailyLimit integer اختياري
الافتراضي: 10000
الحد اليومي للإرسال الصادر لهذا المفتاح.
├─ isActive boolean للقراءة فقط
الافتراضي: true
حالة التفعيل.
{
  "label": "Shopware 6 ERP Rechnungsversand",
  "role": "User",
  "senderAddress": "rechnung@muster-logistik.de",
  "defaultCategory": "transactional",
  "allowedCidrs": ["10.20.10.15/32", "2a01:4f8:120:44aa::/64"],
  "expiresInDays": 180,
  "outboundDailyLimit": 10000
}
# CIDR-geschützten Key für Ansible / nextxch-cli erstellen:
nextxch-cli create ApiKey \
  --set label="GitLab CI / Ansible" \
  --set role=TenantAdmin \
  --set allowedCidrs=10.20.0.0/16 \
  --set expiresInDays=90

# Schlüssel widerrufen:
nextxch-cli delete ApiKey 0195f2a0-8b14-7000-9a10-001122334455
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/ApiKey" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"label":"Shopware 6","role":"User","senderAddress":"rechnung@muster-logistik.de","allowedCidrs":["10.20.10.15/32"],"expiresInDays":180}'
var res = await http.PostAsJsonAsync("/api/admin/cli/objects/ApiKey", new
{
    label = "Shopware 6",
    role = "User",
    senderAddress = "rechnung@muster-logistik.de",
    allowedCidrs = new[] { "10.20.10.15/32" },
    expiresInDays = 180
});
var created = await res.Content.ReadFromJsonAsync<JsonElement>();
string oneTimeSecretKey = created.GetProperty("apiKey").GetString()!;
كائن Collection (CRUD)

Route

المفتاح: domain RBAC: ServerAdmin+
10 خصائص

توجيه SMTP صادر لكل نطاق أو استثناء لشهادة TLS (مثل StartTlsIgnoreCert لمضيفات MX لدى الشركاء ذات الشهادات غير المتطابقة، أو موصل Smart-Host).

GET /api/admin/cli/objects/Route يسرد جميع مسارات البريد الصادر المخصصة
POST /api/admin/cli/objects/Route ينشئ مسار نطاق مخصصًا أو تجاوزًا لإعدادات TLS
PATCH /api/admin/cli/objects/Route/{domain} يحدّث المضيف الهدف أو المنفذ أو وضع TLS
DELETE /api/admin/cli/objects/Route/{domain} يحذف المسار المخصص
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ domain string PRIMARY KEY
نطاق المستلم المستهدف (مثل "neff.me" أو "*.partner-holding.eu").
├─ targetHost string اختياري
الافتراضي: "" (Auto DNS-MX)
اسم مضيف المرحّل أو عنوان IP. اتركوه فارغًا لتحليل MX الوجهة عبر DNS تلقائيًا.
├─ targetPort integer اختياري
الافتراضي: 25
منفذ TCP المستهدف (25 أو 587 أو 465).
├─ tlsMode string اختياري
الافتراضي: StartTlsOptional
وضع TLS والتحقق من X.509 للبريد الصادر لهذا النطاق.
Enum:"StartTlsOptional""StartTlsRequired""StartTlsIgnoreCert""ImplicitTls""ImplicitTlsIgnoreCert""None"
├─ username string اختياري
اسم مستخدم SMTP AUTH اختياري.
├─ password string للكتابة فقط (سري)
كلمة مرور SMTP AUTH اختيارية.
├─ hasPassword boolean للقراءة فقط
الافتراضي: false
يشير إلى ما إذا كانت كلمة مرور مخزنة.
├─ clearPassword boolean للكتابة فقط (سري)
الافتراضي: false
اضبطوا القيمة true لمسح كلمة المرور المخزنة.
├─ description string اختياري
ملاحظة تدقيق المسؤول.
├─ enabled boolean اختياري
الافتراضي: true
تفعيل المسار أو إيقافه مؤقتًا.
{
  "domain": "neff.me",
  "targetHost": "",
  "targetPort": 25,
  "tlsMode": "StartTlsIgnoreCert",
  "username": null,
  "description": "Shared-Hosting-MX mit abweichendem Zertifikatsnamen (Auto DNS-MX)",
  "enabled": true
}
# Partner-Domain mit fehlerhaftem MX-Zertifikat per Auto-DNS-MX freigeben:
nextxch-cli create Route \
  --set domain=neff.me \
  --set tlsMode=StartTlsIgnoreCert \
  --set description="TLS NameMismatch auf Partner-MX erlauben"

# Internes ERP-Subnetz an lokalen Connector routen:
nextxch-cli create Route \
  --set domain=erp.firma.intern \
  --set targetHost=10.40.2.15 \
  --set targetPort=25
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/Route" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"domain":"neff.me","targetHost":"","targetPort":25,"tlsMode":"StartTlsIgnoreCert","enabled":true}'
await http.PostAsJsonAsync("/api/admin/cli/objects/Route", new
{
    domain = "neff.me",
    targetHost = "",
    targetPort = 25,
    tlsMode = "StartTlsIgnoreCert",
    enabled = true
});
سياسة Singleton

TransactionalSend (Singleton)

المفتاح: singleton RBAC: TenantAdmin+
11 خاصية

يتحكم في إحماء IP التدريجي لمدة 28 يومًا، وفئات الرسائل، والحصص الساعية/اليومية لكل مزود مستلم (Google وMicrosoft وYahoo/AOL ومزودو خدمة الإنترنت الألمان وiCloud و*).

GET /api/admin/cli/objects/TransactionalSend/singleton يجلب سياسة إحماء IP النشطة وحصص المزودين
PATCH /api/admin/cli/objects/TransactionalSend/singleton يحدّث يوم التسخين أو الإعداد المسبق أو حصص المزودين
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ enabled boolean اختياري
الافتراضي: true
يُفعّل حوكمة حصص الفئات والمزودين.
├─ warmingEnabled boolean اختياري
الافتراضي: false
يفعّل منحنى إحماء IP يومي تدريجي.
├─ startAtWarmingDay integer للكتابة فقط (سري)
الافتراضي: 1
ينتقل بجدول الإحماء إلى اليوم N أو يعيد ضبطه (1..365).
├─ currentWarmingDay integer للقراءة فقط
اليوم النشط الحالي في جدول الإحماء.
├─ currentWarmingPercent integer للقراءة فقط
النسبة المئوية النشطة حاليًا من حصص المزود المستهدف.
├─ warmingDailyRampPercents integer[] اختياري
الافتراضي: [5,7,10,...,100]
مصفوفة النسب المئوية اليومية لمنحنى الإحماء.
├─ maxDeferHours integer اختياري
الافتراضي: 48
الحد الأقصى لنافذة الاستشراف بالساعات لتنظيم وتيرة DeferQueue.
├─ defaultCategory string اختياري
الافتراضي: transactional
الفئة الاحتياطية عند إغفالها في استدعاءات API.
Enum:"critical""transactional""notification""marketing"
├─ preset string للكتابة فقط (سري)
محدد الإعداد المسبق بخطوة واحدة.
Enum:"warming_28d""warming_14d""production_100"
├─ categories CategoryPolicy[] اختياري
الافتراضي: 4 Kategorien
مصفوفة من كائنات سياسات الفئات.
├─ providers ProviderQuota[] اختياري
الافتراضي: 6 Provider-Gruppen
مصفوفة تعريفات حصص مزودي المستلمين.
{
  "enabled": true,
  "warmingEnabled": true,
  "startAtWarmingDay": 1,
  "maxDeferHours": 48,
  "defaultCategory": "transactional",
  "preset": "warming_28d"
}
# 28-Tage IP-Warming aktivieren:
nextxch-cli update TransactionalSend --set preset=warming_28d

# Direkt auf Warming-Tag 14 vorspringen:
nextxch-cli update TransactionalSend --set startAtWarmingDay=14
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/TransactionalSend/singleton" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"preset":"warming_28d","enabled":true}'
await http.PatchAsJsonAsync(
    "/api/admin/cli/objects/TransactionalSend/singleton",
    new { preset = "warming_28d", enabled = true });
سياسة Singleton

ReputationShield (Singleton)

المفتاح: singleton RBAC: TenantAdmin+
20 خاصية

حماية اختيارية لسمعة البريد الصادر: قائمة إيقاف تلقائية للارتدادات/الشكاوى، وإلغاء الاشتراك بنقرة واحدة وفق RFC 8058، وقاطع دائرة للارتدادات، وتراجع تكيّفي عند 421 من مزودي الإنترنت، وwebhooks بتوقيع HMAC-SHA256.

GET /api/admin/cli/objects/ReputationShield/singleton يجلب إعداد Reputation Shield الحالي
PATCH /api/admin/cli/objects/ReputationShield/singleton يحدّث علامات الحماية أو يطبّق إعدادًا مسبقًا
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ preset string للكتابة فقط (سري)
يطبق ملف حماية كاملًا بخطوة واحدة.
Enum:"off""recommended""strict_bulk"
├─ enableSuppressionPreCheck boolean اختياري
الافتراضي: false
يُصفّي العناوين الموقوفة قبل الإرسال.
├─ enforceSuppressionOnSmtpRelay boolean اختياري
الافتراضي: false
يطبّق قائمة الإيقاف أيضًا على الإرسال عبر SMTP Submission.
├─ allSuppressedBehavior string اختياري
الافتراضي: reject_422
وضع الاستجابة عندما يكون جميع المستلمين في قائمة المنع.
Enum:"reject_422""accept_noop"
├─ autoSuppressHardBounces boolean اختياري
الافتراضي: false
يوقف تلقائيًا العناوين ذات الارتدادات الدائمة 5xx.
├─ hardBounceSuppressionDays integer اختياري
الافتراضي: 180
أيام الاحتفاظ بإيقافات الارتداد الدائم (Hard Bounce).
├─ autoSuppressConsecutiveSoftBounces boolean اختياري
الافتراضي: false
يصعّد حالات الارتداد المؤقت 4xx المتكررة إلى قائمة الإيقاف.
├─ softBounceEscalationThreshold integer اختياري
الافتراضي: 5
عدد الارتدادات المؤقتة المتتالية قبل الإيقاف.
├─ autoSuppressFblComplaints boolean اختياري
الافتراضي: false
يحلّل تلقائيًا تقارير إساءة الاستخدام الواردة بتنسيق ARF وفق RFC 5965.
├─ enableOneClickUnsubscribe boolean اختياري
الافتراضي: false
يُدرج ترويسات List-Unsubscribe وفق RFC 8058 موقّعة بـ DKIM.
├─ oneClickUnsubscribeCategories string[] اختياري
الافتراضي: ["marketing","notification"]
الفئات التي تتلقى ترويسات إلغاء الاشتراك وفق RFC 8058.
├─ enableBounceCircuitBreaker boolean اختياري
الافتراضي: false
يوقف الإرسال غير الحرج مؤقتًا إذا ارتفع معدل الارتداد/الشكاوى خلال 24 ساعة بشكل حاد.
├─ maxHardBouncePercent number اختياري
الافتراضي: 5.0
الحد الأقصى لمعدل الارتداد الدائم خلال 24 ساعة بالنسبة المئوية.
├─ maxComplaintPercent number اختياري
الافتراضي: 0.1
الحد الأقصى لمعدل شكاوى ARF خلال 24 ساعة بالنسبة المئوية.
├─ allowCriticalWhenTripped boolean اختياري
الافتراضي: true
يسمح ببريد 2FA الحرج حتى عند فصل قاطع الدائرة.
├─ enableAdaptiveIspBackoff boolean اختياري
الافتراضي: false
تهدئة تلقائية عندما يعيد خادم MX البعيد خنق 421/451.
├─ ispCooldownMinutes integer اختياري
الافتراضي: 15
مدة التهدئة بالدقائق.
├─ webhookEnabled boolean اختياري
الافتراضي: false
يفعّل webhooks موقّعة بـ HMAC-SHA256.
├─ webhookUrl string اختياري
عنوان URL الوجهة عبر HTTPS لـ Webhooks.
├─ webhookSecret string للكتابة فقط (سري)
سر HMAC-SHA256 لـ X-Nextxch-Signature.
{
  "preset": "recommended",
  "enableSuppressionPreCheck": true,
  "autoSuppressHardBounces": true,
  "hardBounceSuppressionDays": 180,
  "enableOneClickUnsubscribe": true,
  "oneClickUnsubscribeCategories": ["marketing", "notification"],
  "enableBounceCircuitBreaker": true,
  "maxHardBouncePercent": 5.0,
  "maxComplaintPercent": 0.1,
  "allowCriticalWhenTripped": true,
  "enableAdaptiveIspBackoff": true,
  "webhookEnabled": true,
  "webhookUrl": "https://erp.firma.de/webhooks/nextxch"
}
# Empfohlenen Reputationsschutz aktivieren:
nextxch-cli update ReputationShield --set preset=recommended

# Webhook-Ziel konfigurieren:
nextxch-cli update ReputationShield \
  --set webhookEnabled=true \
  --set webhookUrl=https://erp.firma.de/webhooks/nextxch \
  --set webhookSecret=whsec_9f8e7d6c5b4a
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/ReputationShield/singleton" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"preset":"recommended"}'
await http.PatchAsJsonAsync(
    "/api/admin/cli/objects/ReputationShield/singleton",
    new { preset = "recommended" });
سياسة Singleton

SpamGuard (Singleton)

المفتاح: singleton RBAC: ServerAdmin+
15 خاصية

حماية واردة متعددة المراحل: التحقق من SPF/DKIM/DMARC/ARC، وSmart Greylisting ‏(/24 IPv4 & /64 IPv6)، ومصنّف تعلّم آلي عبر الإنترنت (FTRL-Proximal)، ومناطق DNSBL، وقوائم السماح/الحظر، وفحص ClamAV عبر TCP.

GET /api/admin/cli/objects/SpamGuard/singleton يجلب عتبات SpamGuard وعدادات التدريب
PATCH /api/admin/cli/objects/SpamGuard/singleton يحدّث النتائج أو قوائم DNSBL أو قوائم السماح أو ClamAV في مكانها
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ enableEmailAuthChecks boolean اختياري
الافتراضي: true
يتحقق من SPF وDKIM وDMARC وARC للبريد الوارد.
├─ enableGreylisting boolean اختياري
الافتراضي: true
قائمة رمادية ذكية تكيفية للمرسلين المجهولين لأول مرة.
├─ greylistRetryDelaySeconds integer اختياري
الافتراضي: 240
الحد الأدنى لتأخير إعادة المحاولة بالثواني (الافتراضي: 240s).
├─ junkScoreThreshold number اختياري
الافتراضي: 4.5
عتبة الدرجة للنقل إلى مجلد البريد العشوائي.
├─ rejectScoreThreshold number اختياري
الافتراضي: 9.0
عتبة الدرجة للرفض النهائي عبر SMTP 550.
├─ tagSubjectOnJunk boolean اختياري
الافتراضي: false
إضافة بادئة إلى موضوع رسائل البريد العشوائي.
├─ subjectTagPrefix string اختياري
الافتراضي: "[SPAM] "
سلسلة بادئة الموضوع.
├─ enableStructuralHeuristics boolean اختياري
الافتراضي: true
يقيّم الاستدلالات البنيوية لـ MIME/HTML.
├─ dnsblZones string[] اختياري
الافتراضي: ["bl.spamcop.net","ix.dnsbl.manitu.net"]
مناطق DNSBL التي يُستعلم عنها.
├─ dnsblHitScore number اختياري
الافتراضي: 3.5
الدرجة المضافة لكل تطابق في DNSBL.
├─ allowedSendersOrDomains string[] اختياري
الافتراضي: []
قائمة سماح صريحة لعناوين البريد الإلكتروني أو نطاقات المرسلين.
├─ blockedSendersOrDomains string[] اختياري
الافتراضي: []
قائمة حظر صريحة لعناوين البريد الإلكتروني أو نطاقات المرسلين.
├─ clamAvEnabled boolean اختياري
الافتراضي: false
يفعّل فحص TCP INSTREAM عبر خدمة ClamAV.
├─ clamAvHost string اختياري
الافتراضي: "127.0.0.1"
مضيف خدمة ClamAV أو عنوان IP الخاص بها.
├─ clamAvPort integer اختياري
الافتراضي: 3310
منفذ TCP لخدمة ClamAV.
{
  "enableEmailAuthChecks": true,
  "enableGreylisting": true,
  "greylistRetryDelaySeconds": 240,
  "junkScoreThreshold": 4.5,
  "rejectScoreThreshold": 9.0,
  "enableStructuralHeuristics": true,
  "dnsblZones": ["bl.spamcop.net", "ix.dnsbl.manitu.net"],
  "dnsblHitScore": 3.5,
  "allowedSendersOrDomains": ["datev.de", "partner-spedition.de"],
  "blockedSendersOrDomains": [],
  "clamAvEnabled": false,
  "clamAvHost": "127.0.0.1",
  "clamAvPort": 3310
}
# Partner-Domains auf die Allowlist setzen:
nextxch-cli update SpamGuard \
  --set allowedSendersOrDomains=datev.de,partner-spedition.de

# Schwellenwerte anpassen:
nextxch-cli update SpamGuard --set junkScoreThreshold=4.5 --set rejectScoreThreshold=9.0
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/SpamGuard/singleton" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"junkScoreThreshold":4.5,"rejectScoreThreshold":9.0,"allowedSendersOrDomains":["datev.de"]}'
await http.PatchAsJsonAsync(
    "/api/admin/cli/objects/SpamGuard/singleton",
    new { junkScoreThreshold = 4.5, rejectScoreThreshold = 9.0 });
سياسة Singleton

SmtpQueue (Singleton)

المفتاح: singleton RBAC: ServerAdmin+
19 خاصية

يتحكم في قائمة انتظار تسليم MX الصادرة، وتزامن العمّال، وفترات إعادة المحاولة، وتقييد المعدل لدى مزودي الخدمة، والتحقق من TLS الصادر، والمضيف الذكي العام (Smart-Host)، وحدود ESMTP الواردة.

GET /api/admin/cli/objects/SmtpQueue/singleton يجلب جميع إعدادات قائمة الانتظار وTLS وESMTP
PATCH /api/admin/cli/objects/SmtpQueue/singleton يحدّث عمّال قائمة الانتظار أو جدول إعادة المحاولة أو حدود ESMTP خلال 0 ms
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ outboundQueuePaused boolean اختياري
الافتراضي: false
يوقف تسليم البريد الصادر عبر MX مؤقتًا مع الاستمرار في قبول البريد.
├─ outboundWorkerConcurrency integer اختياري
الافتراضي: 8
عدد عمّال التسليم الصادر المتوازيين.
├─ maxDeliveryAttempts integer اختياري
الافتراضي: 10
الحد الأقصى لمحاولات التسليم قبل الارتداد الدائم.
├─ retryScheduleMinutes integer[] اختياري
الافتراضي: [5,15,60,240,720]
جدول التراجع لإعادة المحاولة بالدقائق.
├─ maxConcurrentConnectionsPerMxDomain integer اختياري
الافتراضي: 4
الحد الأقصى للاتصالات المتزامنة لكل نطاق MX وجهة.
├─ strictThrottleDomains string[] اختياري
الافتراضي: ["t-online.de","gmx.de","web.de","yahoo.com"]
نطاقات تخضع لخنق صارم للتزامن.
├─ strictThrottleMaxConcurrency integer اختياري
الافتراضي: 2
الحد الأقصى للاتصالات المتزامنة لـ strictThrottleDomains.
├─ outboundConnectTimeoutSeconds integer اختياري
الافتراضي: 30
مهلة اتصال TCP/TLS الصادر بالثواني.
├─ outboundBindAddress string اختياري
الافتراضي: "" (Auto)
عنوان IP مصدر محلي اختياري للربط.
├─ outboundUseStartTls boolean اختياري
الافتراضي: true
استخدام STARTTLS في اتصالات MX الصادرة.
├─ requireOutboundTls boolean اختياري
الافتراضي: false
إيقاف التسليم إذا لم يوفر خادم MX البعيد TLS.
├─ outboundTlsCertValidation string اختياري
الافتراضي: Opportunistic
وضع التحقق العام من شهادات X.509 للبريد الصادر.
Enum:"Opportunistic""IgnoreErrors""Strict"
├─ outboundSmartHost string اختياري
الافتراضي: ""
مضيف ترحيل علوي عام اختياري.
├─ outboundSmartPort integer اختياري
الافتراضي: 587
منفذ TCP للمضيف الذكي العام (Smart-host).
├─ maxMessageSizeMb long اختياري
الافتراضي: 50
حد ESMTP SIZE العام بوحدة MiB.
├─ maxRecipientsPerTransaction integer اختياري
الافتراضي: 100
الحد الأقصى لأوامر RCPT TO في المعاملة الواحدة.
├─ maxConnectionsPerIp integer اختياري
الافتراضي: 20
الحد الأقصى للاتصالات الواردة المتزامنة لكل عنوان IP.
├─ tarpitDelayMs integer اختياري
الافتراضي: 1500
تأخير Tarpit بالمللي ثانية عند أخطاء المصادقة/الأوامر.
├─ requireTlsForAuth boolean اختياري
الافتراضي: true
يشترط تشفير TLS قبل السماح بـ SMTP AUTH.
{
  "outboundQueuePaused": false,
  "outboundWorkerConcurrency": 8,
  "maxDeliveryAttempts": 10,
  "retryScheduleMinutes": [5, 15, 60, 240, 720],
  "maxConcurrentConnectionsPerMxDomain": 4,
  "strictThrottleDomains": ["t-online.de", "gmx.de", "web.de", "yahoo.com"],
  "strictThrottleMaxConcurrency": 2,
  "outboundUseStartTls": true,
  "requireOutboundTls": false,
  "outboundTlsCertValidation": "Opportunistic",
  "maxMessageSizeMb": 50,
  "maxRecipientsPerTransaction": 100,
  "tarpitDelayMs": 1500,
  "requireTlsForAuth": true
}
# Outbound-TLS auf Opportunistic (RFC 7435) setzen & MaxMessageSize auf 75 MiB erhöhen:
nextxch-cli update SmtpQueue \
  --set outboundTlsCertValidation=Opportunistic \
  --set maxMessageSizeMb=75
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/SmtpQueue/singleton" \
  -H "Authorization: Bearer smk_..." \
  -H "Content-Type: application/json" \
  -d '{"outboundTlsCertValidation":"Opportunistic","maxMessageSizeMb":75}'
await http.PatchAsJsonAsync(
    "/api/admin/cli/objects/SmtpQueue/singleton",
    new { outboundTlsCertValidation = "Opportunistic", maxMessageSizeMb = 75 });
سياسة Singleton

TransportRules & Server (Singletons)

المفتاح: singleton RBAC: ServerAdmin+
11 خاصية

إخلاء مسؤولية قانوني على مستوى المؤسسة (يُدرج قبل توقيع DKIM)، وسكربت Sieve عام للبريد الوارد، وعتبات الحظر التلقائي في Fail2Ban، وServerHostName القياسي.

GET /api/admin/cli/objects/TransportRules/singleton يجلب إعدادات إخلاء المسؤولية وSieve العام والحظر التلقائي
PATCH /api/admin/cli/objects/TransportRules/singleton يحدّث قواعد النقل في مكانها
GET /api/admin/cli/objects/Server/singleton يجلب ServerHostName ومحرك التخزين وعمق قائمة الانتظار وحالة الترخيص
PATCH /api/admin/cli/objects/Server/singleton يحدّث ServerHostName القياسي في 0 ms
{ } مخطط الكائن والخصائص ذات الأنواع application/json · camelCase
├─ outboundDisclaimerEnabled boolean اختياري
الافتراضي: false
يُلحق تذييلًا مؤسسيًا إلزاميًا بالرسائل الصادرة.
├─ outboundDisclaimerExternalOnly boolean اختياري
الافتراضي: true
إلحاق التذييل فقط عند الإرسال إلى نطاقات خارجية.
├─ outboundDisclaimerText string اختياري
الافتراضي: ""
تذييل قانوني بنص عادي.
├─ outboundDisclaimerHtml string اختياري
الافتراضي: ""
تذييل قانوني بصيغة HTML.
├─ inboundSystemSieve string اختياري
الافتراضي: ""
سكربت Sieve عام وفق RFC 5228 يُنفَّذ قبل سكربتات المستخدمين.
├─ autoBanThreshold integer اختياري
الافتراضي: 8
عدد محاولات الدخول الفاشلة قبل الحظر التلقائي لعنوان IP.
├─ autoBanDurationMinutes integer اختياري
الافتراضي: 30
مدة الحظر التلقائي لعنوان IP بالدقائق.
├─ serverHostName string اختياري
الافتراضي: mail.<domain>
اسم FQDN المعتمد لـ EHLO وTLS وAutodiscover (الكائن: Server).
├─ storageProvider string للقراءة فقط
الافتراضي: Sqlite | SqlServer | Postgres
محرك التخزين النشط (الكائن: Server).
├─ activeQueueCount integer للقراءة فقط
الافتراضي: 0
العدد الحالي في قائمة انتظار البريد الصادر (الكائن: Server).
├─ licenseState string للقراءة فقط
الافتراضي: EnterpriseActive
حالة الترخيص (الكائن: Server).
{
  "outboundDisclaimerEnabled": true,
  "outboundDisclaimerExternalOnly": true,
  "outboundDisclaimerText": "-- \nMuster Logistik GmbH · Industriestraße 18 · 70565 Stuttgart · HRB 774819",
  "outboundDisclaimerHtml": "<p style='font-size:11px;color:#64748b'><strong>Muster Logistik GmbH</strong> &middot; 70565 Stuttgart &middot; HRB 774819</p>",
  "inboundSystemSieve": "require [\"fileinto\"];\nif header :contains \"X-Spam-Flag\" \"YES\" { fileinto \"Junk\"; }",
  "autoBanThreshold": 8,
  "autoBanDurationMinutes": 30
}
# Pflicht-Impressum & Auto-Ban aktualisieren:
nextxch-cli update TransportRules \
  --set outboundDisclaimerEnabled=true \
  --set autoBanThreshold=8

# Kanonischen Server-Hostnamen abfragen oder setzen:
nextxch-cli get Server
nextxch-cli update Server --set serverHostName=mail.muster-logistik.de
curl -fsS -X GET "https://mail.firma.de/api/admin/cli/objects/Server/singleton" \
  -H "Authorization: Bearer smk_..."
var status = await http.GetFromJsonAsync<JsonElement>("/api/admin/cli/objects/Server/singleton");
Console.WriteLine($"Host: {status.GetProperty("serverHostName")}, Queue: {status.GetProperty("activeQueueCount")}");