Criando um usuário em estágio com uma chamada de API

Atualmente, temos um fluxo de trabalho em que os usuários enviam dados ao enviar um e-mail para um endereço de entrada personalizado, criando um usuário em estágio e uma mensagem privada para um grupo do Discourse.

É possível realizar o mesmo fluxo de trabalho usando chamadas de API? Basicamente: 1) criar um usuário em estágio, 2) gerar uma chave de API para esse usuário e, em seguida, 3) publicar em nome desse usuário? Vejo como publicar mensagens de grupo para usuários existentes usando a documentação da API, mas não sei se as etapas 1) e 2) são possíveis atualmente.

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!

Você poderia especificar quais cabeçalhos e campos devem estar na chamada da API para /admin/email/handle_email que cria um usuário temporário e um tópico em seu nome?

Além disso, entendi corretamente que tal usuário receberá notificações sobre novas postagens nesse tópico e poderá responder a ele por e-mail?

E o que acontece se eu tentar criar um usuário temporário e um tópico via chamada de API com um endereço de e-mail que pertence a um usuário ativo? Esse tópico será criado em nome desse usuário?

Já descobri que o endpoint correto é /admin/email/handle_mail (não “handle_email”), mas ainda não consegui entender o que deve constar na solicitação da API.

O único parâmetro que este endpoint aceita é uma mensagem email válida:

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.
"

Você precisará garantir que o email_in esteja habilitado e que sua categoria ou grupo esteja configurado corretamente para receber esses e-mails:

Sim, acredito que sim.

Sim, o tópico será criado em nome do usuário.

Obrigado, Blake. No entanto, ainda não funciona para mim. Recebi uma resposta da API: “email has been received and is queued for processing”, mas nada aparece no Discourse — nem um novo tópico, nem um usuário em fase de teste.

Aqui está a revisão das configurações:
Global:

  • email_in: ativado
  • email_in_min_trust: 0
  • enable_staged_users: ativado

Categoria:

  • Endereço de e-mail de entrada personalizado: definido como [my_name]@gmail.com
  • Aceitar e-mails de usuários anônimos sem contas: ativado

Chamada da 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."

O que poderia estar errado?

Seu Sidekiq está funcionando corretamente?

Como posso verificar isso?

Você pode verificar se o Sidekiq está em execução acessando /sidekiq, mas acredito que provavelmente haja um problema com o e-mail bruto agora que a solicitação da API está tendo sucesso. Existem várias abas no painel de administração onde você pode verificar erros de e-mail.

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

Veja se consegue encontrar os e-mails que você está criando por meio de chamadas de API em uma dessas abas; talvez seja possível visualizar uma mensagem de erro associada a eles.

Sim, o Sidekiq está em execução. Verifiquei as abas /admin/email — parece que meus “e-mails” estão sendo rejeitados.

É isso que recebo:

Inseri o mesmo texto de e-mail na aba “Texto avançado” e parece estar funcionando, desde que cada parte (Data, De, Para, Assunto) comece em uma nova linha e o corpo seja separado por duas quebras de linha. Ao inserir o texto exatamente como no curl, nada é retornado. Seria devido às quebras de linha no e-mail bruto? Se sim, o que devo fazer?

Tentei /n, %0A e $'[text/n]', mas nenhum funcionou.

Não tenho certeza. Parece que não aceita nenhum dos campos do seu e-mail.

Usei Ruby para gerar o comando curl e Ruby para ler o arquivo de texto do meu e-mail que escrevi, mas sim, parece ser um problema de quebra de linha.

Você consegue fazer o curl ler um arquivo de e-mail que tenha quebras de linha reais nele?

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

Você estava certo — era um problema de quebra de linha. Fiz a mesma chamada de API pelo Postman e funcionou: um novo usuário em staging foi criado e um tópico foi aberto em seu nome.

Mas: nenhum e-mail foi enviado para o endereço desse usuário! Também publiquei um comentário no tópico e não recebi nenhuma notificação por e-mail. Existe alguma configuração que impeça isso? Tentei encontrá-la, mas não consegui.

ATUALIZAÇÃO: Havia, de fato, uma configuração que impedia o envio de notificações de postagens :slight_smile: Agora tenho duas perguntas diferentes:

  1. Por que não houve um e-mail informando o usuário em staging que o tópico foi criado e enviando o link para ele?
    (Também adicionaria algumas instruções sobre como fazer login no fórum, se soubesse qual modelo editar.)
  2. Por que não há link para o tópico nos e-mails de notificação de postagem? Também não há link de cancelamento de assinatura.
    O modelo parece ser o mesmo: “user_posted”.

Qual configuração, para quem está acompanhando? Acredito que não precisei alterar nada, então só estou curioso.

Acho que isso é intencional e ocorre da mesma forma quando você envia um e-mail para um grupo do Discourse. O sistema foi projetado para funcionar como e-mail, ou seja, o usuário pode nem saber que está enviando um e-mail para um fórum do Discourse. Se eu enviar um e-mail comum para sua conta de e-mail, não recebo uma resposta do seu provedor de e-mail confirmando que você recebeu meu e-mail; apenas confiamos que funcione.

Aqui está um exemplo de e-mail de notificação que um usuário em fase de teste receberá:

Mas é isso que um usuário não em fase de teste receberá:

Parece haver uma diferença entre usuários em fase de teste e usuários não em fase de teste. Provavelmente, como o usuário está em fase de teste, a interação deve ser semelhante ao uso de e-mail comum.

Na verdade, havia várias.

  • nível de e-mail padrão - o padrão é “apenas quando ausente”
  • janela de tempo do e-mail - o padrão é 10 minutos, então o e-mail de notificação não é enviado imediatamente
  • desativar e-mails - o padrão é “não”, mas eu tinha alterado antes e esqueci :man_facepalming:

Bem, para mim, a notificação de postagem realmente não parece um e-mail comum de qualquer forma - por exemplo, ela tem um link para o perfil do autor da postagem no fórum (duas vezes!), mas não para o tópico.

Além disso, gostaria de informar ao usuário em fase de teste que ele pode realmente fazer login no fórum.
Existe alguma maneira de personalizar esse modelo de e-mail?

Por design, vários campos são omitidos para usuários em fase de teste nos modelos de e-mail (como as instruções de resposta):

Não tenho certeza total do motivo, apenas estou afirmando que, no código, é assim que funciona. Portanto, você está atualmente enfrentando uma batalha difícil, pois está tentando fazer algo que o Discourse foi projetado para não fazer.

Sim, você pode editar os modelos de e-mail, mas suas opções de personalização são bastante limitadas. Por exemplo, não acho que seja possível fazer com que o modelo de e-mail tenha um visual diferente para usuários em fase de teste e outro para usuários normais. No entanto, você pode adicionar uma mensagem com um link no final do e-mail de notificação, convidando-os a visitar seu site em vez de interagir apenas por e-mail.

Na verdade, seria suficiente se o modelo tivesse a mesma aparência para usuários regulares e em estágio :slight_smile:
Vou pensar no que posso fazer. Obrigado pela explicação detalhada!

Uma última pergunta (espero): como um usuário em estágio pode cancelar a assinatura de receber novas postagens no tópico criado em seu nome?