إنشاء مستخدم مرحل عبر استدعاء واجهة برمجة التطبيقات

نمتلك حاليًا سير عمل حيث يرسل المستخدمون البيانات عبر إرسال بريد إلكتروني إلى عنوان بريد إلكتروني وارد مخصص، مما يؤدي إلى إنشاء مستخدم مؤقت (staged user) ورسالة خاصة لمجموعة في Discourse.

هل من الممكن تحقيق نفس سير العمل باستخدام استدعاءات واجهة برمجة التطبيقات (API)؟ أي: 1) إنشاء مستخدم مؤقت، 2) توليد مفتاح API لذلك المستخدم، ثم 3) النشر باسم ذلك المستخدم؟ لقد رأيت كيفية نشر رسائل المجموعة للمستخدمين الحاليين باستخدام وثائق واجهة برمجة التطبيقات، لكنني لا أعرف ما إذا كانت الخطوتان 1 و 2 ممكنتين حاليًا.

Yes, just create a user via the api. They won’t be “staged” at this point since they actually exist. If they ever need to log in, they can just reset their password.

This is also possible


Here is a rough example of how to create a user, active them, and generate an api key for them.
    def create_user
      user = {
        name: example1,
        email: "example1@example.com",
        password: "ZvAmmkcSWQfsPQLBksg7wK59",
        username: example1,
        active: "false",
        approved: "true",
        approved_by_id: 1,
        approved_at: DateTime.now
      }

      new_user = @client.create_user(user)
      id = new_user['user_id']
      @client.activate(id)
      uri = URI.parse(@config.full_discourse_url)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true
      request = Net::HTTP::Post.new("/admin/users/#{id}/generate_api_key?api_key=#{@client.api_key}&api_username=#{@client.api_username}")
      response = http.request(request)
      result = JSON.parse(response.body)
    end

Another option instead of generating an api key for each user is you can just instantiate a new discourse client using the same admin api key and just specify the new username:

client = DiscourseApi::Client.new("http://127.0.0.1:3000")
client.api_key = "a71cb5058c6be27e42806ad788bc7b0008af9c15170d1be1827a24c8e8334107"
client.api_username = "system"

... create user here...

client2 = DiscourseApi::Client.new("http://127.0.0.1:3000")
client2.api_key = "a71cb5058c6be27e42806ad788bc7b0008af9c15170d1be1827a24c8e8334107"
client2.api_username = example1

... create post here ...

I’m trying to avoid creating a full-fledged user account and picking a username. Essentially I want to replicate whatever is happening in the email trigger (‘custom incoming email address’ in the group settings) where the sender’s email address will be ‘staged,’ such that if/when they do register, they’ll be able to claim any messages that were created on their behalf via the email trigger.

Does that make sense? Is there a way to ‘spoof’ an incoming email using API calls? Thanks for all your help!

You might just have to generate an email and send that to your Discourse instance.

EDIT: Actually there is an /admin/email/handle_mail POST route that you can send an API request to.

Thank you, this is exactly what I was looking for!

هل يمكنك توضيح الرؤوس (headers) والحقول (fields) التي يجب تضمينها في استدعاء واجهة برمجة التطبيقات إلى /admin/email/handle_email لإنشاء مستخدم مؤقت وموضوع باسمه؟

أيضًا، هل فهمتُ بشكل صحيح أن هذا المستخدم سيستقبل إشعارات للمنشورات الجديدة في هذا الموضوع وسيتمكن من الرد عليها عبر البريد الإلكتروني؟

وماذا يحدث إذا حاولت إنشاء مستخدم مؤقت وموضوع عبر استدعاء واجهة برمجة التطبيقات باستخدام عنوان بريد إلكتروني ينتمي إلى مستخدم نشط؟ هل سيتم إنشاء هذا الموضوع باسم هذا المستخدم؟

لقد اكتشفت بالفعل أن نقطة النهاية الصحيحة هي /admin/email/handle_mail (وليس “handle_email”)، لكنني ما زلت غير قادر على تحديد ما يجب أن يكون في طلب الـ API.

المعلمة الوحيدة التي يقبلها هذا الطرف هي رسالة email صالحة:

curl -i -sS -X POST "http://localhost:3000/admin/email/handle_mail" \
-H "Api-Key: 852b2d8556777aeb62346e0d8b36ed248a89b03f0261165a685c0aae9c8c2fdd" \
-H "Api-Username: system" \
-F "email=Date: Mon, 24 Feb 2020 13:13:34 -0700
From: stageduser2@example.com
To: awesome@example.com
Subject: test email5

This is a sample email message.
"

ستحتاج إلى التأكد من تمكين email_in وإعداد فئة أو مجموعة لاستقبال هذه الرسائل الإلكترونية بشكل صحيح:

نعم، أعتقد ذلك.

نعم، سيتم إنشاء الموضوع باسم المستخدم.

شكرًا لك، بليك. ومع ذلك، لا يزال الأمر لا يعمل بالنسبة لي. لقد حصلت على رد من واجهة برمجة التطبيقات يقول “تم استلام البريد الإلكتروني وهو في قائمة الانتظار للمعالجة”، لكن لا يظهر أي شيء في Discourse - لا موضوع جديد ولا مستخدم مؤقت.

إليك مراجعة للإعدادات:
عام:

  • email_in: مفعل
  • email_in_min_trust: 0
  • enable_staged_users: مفعل

الفئة:

  • عنوان البريد الإلكتروني الوارد المخصص: مضبوط على [my_name]@gmail.com
  • قبول رسائل البريد الإلكتروني من المستخدمين المجهولين الذين لا يملكون حسابات: مفعل

استدعاء واجهة برمجة التطبيقات:
curl -i -sS -X POST "[my_domain]/admin/email/handle_mail" -H "Content-Type: multipart/form-data;" -H "Api-Key: [...]" -H "Api-Username: system" -F "email=Date: Mon, 24 Feb 2020 13:13:34 -0700 From: [some_name]@gmail.com To: [my_name]@gmail.com Subject: test API email post This is a sample email message."

ما الذي قد يكون خاطئًا؟

هل يعمل sidekiq الخاص بك بشكل صحيح؟

كيف يمكنني التحقق من ذلك؟

يمكنك التحقق مما إذا كان sidekiq يعمل عن طريق التصفح إلى /sidekiq، لكنني أعتقد أن هناك مشكلة محتملة في البريد الخام الآن بعد نجاح طلب الـ API. توجد عدة علامات تبويب في لوحة تحكم المسؤول يمكنك التحقق منها لاكتشاف أخطاء البريد الإلكتروني:

  • /admin/email/sent
  • /admin/email/skipped
  • /admin/email/bounced
  • /admin/email/received
  • /admin/email/rejected

تحقق مما إذا كنت تستطيع العثور على رسائل البريد الإلكتروني التي تنشئها عبر استدعاءات الـ API تحت إحدى هذه العلامات التبويب، وقد تتمكن من رؤية رسالة خطأ مرتبطة بها.

نعم، يعمل Sidekiq. لقد تفقدت تبويبات /admin/email - يبدو أن رسائلي الإلكترونية “مرفوضة” فعليًا.
هذا ما أحصل عليه:

لقد قمت بإدراج نفس نص البريد الإلكتروني في تبويب “النص المتقدم”، ويبدو أنه يعمل، بشرط أن يبدأ كل جزء (التاريخ، من، إلى، الموضوع) بسطر جديد، وأن يكون النص الأساسي مفصولًا بسطرين فارغين. عند إدراج النص تمامًا كما هو في curl، لا يتم إرجاع أي شيء. هل يمكن أن يكون ذلك بسبب سطور الانتقال في البريد الإلكتروني الخام؟ إذا كان الأمر كذلك، فماذا يجب أن أفعل؟

لقد جربت /n و %0A و $'[text/n]'، ولم ينجح أي منها.

لست متأكدًا. يبدو أنه لا يقبل أيًا من الحقول في بريدك الإلكتروني.

استخدمت Ruby لتوليد أمر curl وقراءة ملف نصي للبريد الإلكتروني الذي كتبته، لكن يبدو أن المشكلة تتعلق بسطر جديد.

هل يمكنك استخدام curl لقراءة ملف بريد إلكتروني يحتوي على أسطر جديدة فعلية؟

curl -X POST -i -F parametername=@filename host:port/xxx

كنت محقًا - كانت المشكلة تتعلق بسطر جديد. جربت استدعاء الـ API نفسه من Postman، وقد نجح ذلك: تم إنشاء مستخدم جديد في المرحلة المؤقتة، وتم إنشاء موضوع باسمه.

لكن: لم يتم إرسال أي بريد إلكتروني إلى عنوان البريد الإلكتروني الخاص بهذا المستخدم! كما أنني نشرت تعليقًا في الموضوع، ولم تصلني أي إشعارات عبر البريد الإلكتروني. هل هناك إعداد يمنع ذلك؟ حاولت البحث عنه لكن دون جدوى.

تحديث: كان هناك بالفعل إعداد يمنع إرسال إشعارات المنشورات :slight_smile: لذا لدي الآن سؤالان مختلفان:

  1. لماذا لم يتم إرسال بريد إلكتروني إلى المستخدم المؤقت يخبره بأن الموضوع قد تم إنشاؤه ويرسل له رابطًا إليه؟
    (أود أيضًا إضافة بعض الإرشادات حول كيفية تسجيل الدخول إلى المنتدى، لو كنت أعرف أي قالب يجب تعديله.)
  2. لماذا لا يوجد رابط للموضوع في رسائل البريد الإلكتروني الخاصة بإشعارات المنشورات؟ كما لا يوجد رابط إلغاء الاشتراك.
    يبدو أن القالب هو نفسه: “user_posted”.

أي إعداد تقصد؟ لأي شخص يتابع الموضوع. لا أعتقد أنني اضطرت إلى تغيير أي شيء، لذا أنا فقط فضولي.

أعتقد أن هذا مقصود بالتصميم، ويحدث نفس الشيء عند إرسال بريد إلكتروني إلى مجموعة في Discourse. تم تصميمه للعمل تمامًا مثل البريد الإلكتروني، بمعنى أن المستخدم قد لا يعرف حتى أنه يرسل بريدًا إلكترونيًا إلى منتدى Discourse. إذا أرسلت لك بريدًا إلكترونيًا عاديًا إلى حساب بريدك الإلكتروني، فلن أحصل على رد من مزود البريد الخاص بك يؤكد استلامك للبريد؛ نحن ببساطة نثق في أن الأمر يعمل.

إليك مثال على إشعار البريد الإلكتروني الذي سيستقبله المستخدم المؤقت:

أما هذا فماذا سيستقبله المستخدم غير المؤقت:

يبدو أن هناك فرقًا بين المستخدمين المؤقتين والمستخدمين غير المؤقتين. وعلى الأرجح، لأن المستخدم مؤقت، فإن التفاعل يكون مشابهًا تمامًا للتفاعل عبر البريد الإلكتروني العادي.

في الواقع، كانت هناك عدة إعدادات.

  • default email level - الافتراضي هو “فقط عند الغياب”
  • email time window - الافتراضي هو 10 دقائق، لذا لا يتم إرسال بريد الإشعار فورًا
  • disable emails - الافتراضي هو “لا”، لكنني قمت بتغييره سابقًا ونسيت ذلك :man_facepalming:

حسنًا، بالنسبة لي، فإن إشعار المنشور لا يبدو مثل البريد الإلكتروني العادي على أي حال - على سبيل المثال، يحتوي على رابط لملف المؤلف الشخصي في المنتدى (مرتين!)، ولكن لا يوجد رابط للموضوع.

علاوة على ذلك، أود إعلام المستخدم المرحّب به بأنه يمكنه فعليًا تسجيل الدخول إلى المنتدى.
هل هناك طريقة لتخصيص قالب البريد الإلكتروني هذا؟

بالتصميم، هناك عدة حقول تُحذف من المستخدمين المؤقتين في قوالب البريد الإلكتروني (مثل تعليمات الرد):

لست متأكدًا تمامًا من السبب وراء ذلك، لكنني فقط أذكر أن الكود مصمم بهذه الطريقة، لذا فإنك تواجه حاليًا معركة شاقة لأنك تحاول فعل شيء لا صمم discourse للقيام به.

نعم، يمكنك تعديل قوالب البريد الإلكتروني، لكن خيارات التخصيص محدودة جدًا. على سبيل المثال، لا أعتقد أنه يمكنك جعل قالب البريد الإلكتروني يبدو بشكل مختلف للمستخدمين المؤقتين عنه للمستخدمين غير المؤقتين، لكن يمكنك إضافة رسالة مع رابط في أسفل بريد الإشعار تدعوهم لزيارة موقعك بدلاً من التفاعل عبر البريد الإلكتروني فقط.

في الواقع، سيكون كافيًا إذا كان القالب يبدو بنفس الطريقة للمستخدمين العاديين والمؤقتين :slight_smile:
سأفكر فيما يمكنني فعله. شكرًا لك على الشرح المفصل!

سؤال أخير (نأمل): كيف يمكن للمستخدم المرحلي إلغاء الاشتراك في تلقي منشورات جديدة للموضوع الذي تم إنشاؤه نيابةً عنه؟