API 呼び出しによるステージングユーザーの作成

現在、ユーザーがカスタムの受信メールアドレスにメールを送信することでデータを提出し、ステージングユーザーとDiscourseグループへの非公開メッセージを作成するワークフローを採用しています。

このワークフローをAPI呼び出しで実現することは可能でしょうか?具体的には、1) ステージングユーザーの作成、2) そのユーザー向けにAPIキーの生成、3) そのユーザーに代わって投稿することです。APIドキュメントでは既存ユーザー向けにグループメッセージを投稿する方法は確認できましたが、1) と 2) のステップが現在可能かどうかはわかりません。

「いいね!」 4

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 ...
「いいね!」 10

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.

「いいね!」 8

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

「いいね!」 1

/admin/email/handle_email への API リクエストで、ステージングユーザーとそのユーザーに代わってトピックを作成するために必要なヘッダーとフィールドを具体的に教えてください。

また、そのようなユーザーは、そのトピックへの新しい投稿の通知を受け取り、メールを通じて返信できるという理解で正しいでしょうか?

さらに、すでにアクティブなユーザーに所属しているメールアドレスを使用して、API リクエストでステージングユーザーとトピックを作成しようとするとどうなるのでしょうか?そのトピックは、そのアクティブなユーザーに代わって作成されるのでしょうか?

正しいエンドポイントは /admin/email/handle_mail(「handle_email」ではない)であることをすでに確認しましたが、API リクエストに何を記述すべきかがまだわかりません。

「いいね!」 1

このエンドポイントが受け取るパラメータは、有効な 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 を正しく有効にし、カテゴリまたはグループをこれらのメールを受信するように設定する必要があります。

はい、その通りだと思います。

はい、そのトピックはそのユーザーに代わって作成されます。

「いいね!」 5

ありがとう、ブレイク。しかし、まだ私の環境では動作しません。API から「email has been received and is queued for processing」というレスポンスは得られたものの、Discourse には何も表示されません。新しいトピックも、ステージングユーザーも作成されていません。

設定の確認結果は以下の通りです:
グローバル設定:

  • email_in: on
  • email_in_min_trust: 0
  • enable_staged_users: on

カテゴリ設定:

  • カスタム受信メールアドレス:[my_name]@gmail.com に設定
  • アカウントを持たない匿名ユーザーからのメールを受け入れる:on

API 呼び出し:
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 呼び出しで作成したメールがこれらのタブのいずれかに表示されるか確認し、関連するエラーメッセージがないか調べてみてください。

「いいね!」 1

はい、Sidekiq は実行されています。/admin/email タブを確認しましたが、私の「メール」は実際には拒否されているようです。
以下が表示されます:

同じメールテキストを「高度なテキスト」タブに挿入しましたが、Date、From、To、Subject の各部分が新しい行で始まり、本文が 2 つの改行で区切られている場合は動作しているようです。curl と全く同じテキストを挿入すると、何も返されません。これは生メール内の改行が原因でしょうか?もしそうなら、どうすればよいでしょうか?

/n%0A$'[text/n]' を試しましたが、どれも機能しません。

わかりません。あなたのメールのどのフィールドも受け付けていないようです。

curl コマンドを生成するために Ruby を使い、私が作成したメールのテキストファイルを読み取るためにも Ruby を使いましたが、確かに改行の問題のようです。

実際に改行を含むメールファイルを curl で読み取らせることはできますか?

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

「いいね!」 3

おっしゃる通りでした、改行の問題でしたね。Postman から同じ API コールを試したところ、問題なく動作しました。ステージングユーザーが作成され、そのユーザーを代表してトピックも作成されました。

ただし、このユーザーのメールアドレスにはメールが送信されませんでした!トピックにもコメントを投稿しましたが、メール通知も届きませんでした。これを防ぐ設定があるのでしょうか?探してみましたが、見つかりませんでした。

追記:ポスト通知の送信を防ぐ設定が実際にありました :slight_smile: そこで、現在以下の 2 つの異なる質問があります:

  1. ステージングユーザーに対して、トピックが作成されたことを知らせ、そのリンクを送るメールが送信されなかったのはなぜでしょうか?
    (もし分かれば、フォーラムへのログイン方法についての指示も追加したいところです。どのテンプレートを編集すればよいのか。)
  2. ポスト通知メールにトピックへのリンクが含まれていないのはなぜでしょうか?また、購読解除のリンクもありません。
    テンプレートは同じ「user_posted」のようです。

フォローしている方々向けに、どの設定でしょうか?私は何も変更する必要はなかったと思うのですが、気になります。

これは仕様によるもので、Discourse グループにメールを送信した場合と同じ挙動です。ユーザーが Discourse フォーラムにメールを送信していることさえ認識していない可能性があるため、通常のメールのように動作するように設計されています。私があなたのメールアカウントに通常のメールを送信しても、メールプロバイダーから「メールを受信しました」という返信は届きません。単に機能することを信頼しているだけです。

ステージングされたユーザーが受信するメール通知の例を示します:

一方、非ステージングユーザーが受信するのはこちらです:

ステージングされたユーザーと非ステージングされたユーザーの間には違いがあるようです。おそらく、ユーザーがステージングされているため、通常のメールでのやり取りと同様に動作するように設計されているためでしょう。

「いいね!」 2

実際にはいくつかありました。

  • default email level(デフォルトのメールレベル)- デフォルトは「不在時のみ」
  • email time window(メール送信の時間枠)- デフォルトは10分なので、通知メールは即座には送信されません
  • disable emails(メールを無効化)- デフォルトは「いいえ」ですが、以前に変更してしまい、それを忘れていました :man_facepalming:

さて、私にとって投稿通知は通常のメールには見えないのです。例えば、投稿者のプロフィールへのリンクがフォーラム内に2回含まれていますが、トピックへのリンクはありません。

また、ステージングされたユーザーに、実際にフォーラムにログインできることを伝えたいと考えています。
このメールテンプレートをカスタマイズする方法はありますか?

設計上、メールテンプレートではステージングユーザーに対していくつかのフィールド(返信手順など)が省略されています:

その理由については完全には把握していませんが、コード上ではそのように実装されています。つまり、Discourse が本来行わないことを実現しようとしているため、現在非常に困難な状況にあります。

はい、メールテンプレートを編集することは可能ですが、カスタマイズできる範囲は限られています。例えば、ステージングユーザーと非ステージングユーザーで異なる見た目にするようなカスタマイズはできないと思われます。ただし、通知メールの下部に、メールでの対応ではなくサイトを訪問するよう促すメッセージとリンクを追加することは可能です。

「いいね!」 1

実際、通常ユーザーとステージ済みユーザーでテンプレートが同じように表示されれば十分です :slight_smile:
何ができるか考えてみます。詳しいご説明をありがとうございます!

「いいね!」 3

最後の質問(願わくば):ステージングされたユーザーが、彼の名義で作成されたトピックへの新しい投稿の受信を停止するにはどうすればよいでしょうか?