Crear un usuario escalonado con una llamada a la API

Actualmente tenemos un flujo de trabajo donde los usuarios envían datos mediante un correo electrónico a una dirección de correo entrante personalizada, creando un usuario en estado de espera y un mensaje privado a un grupo de Discourse.

¿Es posible lograr el mismo flujo de trabajo mediante llamadas a la API? Básicamente: 1) crear un usuario en estado de espera, 2) generar una clave API para ese usuario y luego 3) publicar en nombre de ese usuario? Veo cómo publicar mensajes de grupo para usuarios existentes usando la documentación de la API, pero no sé si los pasos 1) y 2) son posibles actualmente.

4 Me gusta

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 Me gusta

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 Me gusta

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

1 me gusta

¿Podrías especificar qué encabezados y campos debe incluir la llamada a la API a /admin/email/handle_email para crear un usuario en estado de espera y un tema en su nombre?

Además, ¿es correcto que dicho usuario recibirá notificaciones sobre nuevas publicaciones en ese tema y podrá responder a ellas por correo electrónico?

Y, ¿qué sucede si intento crear un usuario en estado de espera y un tema mediante una llamada a la API con una dirección de correo electrónico que pertenece a un usuario activo? ¿Se creará este tema en nombre de dicho usuario?

Ya descubrí que el endpoint correcto es /admin/email/handle_mail (no “handle_email”), pero aún no logro entender qué debe incluir la solicitud de la API.

1 me gusta

El único parámetro que acepta este endpoint es un mensaje email válido:

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

Deberás asegurarte de habilitar email_in y configurar correctamente tu categoría o grupo para recibir estos correos electrónicos:

Sí, creo que es así.

Sí, el tema se creará en nombre del usuario.

5 Me gusta

Gracias, Blake. Sin embargo, todavía no funciona para mí. Recibí una respuesta de la API: “el correo electrónico ha sido recibido y está en cola para su procesamiento”, pero no aparece nada en Discourse: ni un nuevo tema ni un usuario en etapa.

Aquí está la revisión de la configuración:
Global:

  • email_in: activado
  • email_in_min_trust: 0
  • enable_staged_users: activado

Categoría:

  • Dirección de correo electrónico entrante personalizada: configurada como [my_name]@gmail.com
  • Aceptar correos electrónicos de usuarios anónimos sin cuentas: activado

Llamada a la 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."

¿Qué podría estar mal?

¿Está tu Sidekiq funcionando correctamente?

¿Cómo puedo verificar eso?

Puedes verificar si Sidekiq está en ejecución accediendo a /sidekiq, pero creo que es probable que haya un problema con el correo electrónico en bruto ahora que la solicitud de la API se está completando con éxito. Hay varias pestañas en el panel de administración donde puedes revisar errores de correo electrónico:

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

Verifica si puedes encontrar los correos electrónicos que estás creando mediante llamadas a la API en alguna de esas pestañas; es posible que puedas ver un mensaje de error asociado a ellos.

1 me gusta

Sí, sidekiq está en ejecución. Revisé las pestañas de /admin/email: parece que mis “correos” están siendo rechazados.
Esto es lo que obtengo:

Inserté el mismo texto del correo en la pestaña “Texto avanzado” y parece funcionar, siempre que cada parte (Fecha, De, Para, Asunto) comience en una nueva línea y el cuerpo esté separado por dos saltos de línea. Al insertar el texto exactamente como en curl, no devuelve nada. ¿Podría ser por los saltos de línea en el correo en bruto? De ser así, ¿qué debería hacer?

Probé con /n, %0A y $'[text/n]', pero ninguno funciona.

No estoy seguro. Parece que no le gustan ninguno de los campos de tu correo electrónico.

Usé Ruby para generar el comando curl y Ruby para leer el archivo de texto de mi correo electrónico que escribí, pero sí, parece ser un problema de salto de línea.

¿Puedes hacer que curl lea un archivo de correo electrónico que tenga saltos de línea reales?

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

3 Me gusta

Tenías razón: era un problema de salto de línea. Probé la misma llamada a la API desde Postman y funcionó: se creó un nuevo usuario en etapa y un tema en su nombre.

Pero: ¡no se envió ningún correo electrónico a la dirección de este usuario! También publiqué un comentario en el tema y no llegó ninguna notificación por correo. ¿Existe alguna configuración que lo impida? Lo intenté buscar, pero no lo encontré.

ACTUALIZACIÓN: ¡De hecho, había una configuración que impedía el envío de notificaciones de publicaciones! Así que ahora tengo dos preguntas distintas:

  1. ¿Por qué no se envió un correo al usuario en etapa informándole que se había creado el tema y proporcionándole el enlace?
    (También añadiría algunas instrucciones sobre cómo iniciar sesión en el foro si supiera qué plantilla editar).
  2. ¿Por qué no hay enlace al tema en los correos de notificación de publicaciones? Tampoco hay enlace para darse de baja.
    Parece que la plantilla es la misma: “user_posted”.

¿Qué configuración es, para cualquiera que esté siguiendo? No creo que tuviera que cambiar nada, solo tengo curiosidad.

Creo que esto es intencional y ocurre lo mismo si envías un correo electrónico a un grupo de Discourse. Está diseñado para funcionar como el correo electrónico, es decir, el usuario podría ni siquiera saber que está enviando un correo electrónico a un foro de Discourse. Si te envío un correo electrónico regular a tu cuenta de correo, no recibo una respuesta de tu proveedor de correo electrónico que diga que recibiste mi mensaje; simplemente confiamos en que funcione.

Aquí hay un ejemplo de notificación por correo electrónico que recibirá un usuario provisional:

pero esto es lo que recibirá un usuario no provisional:

Parece haber una diferencia entre los usuarios provisionales y los no provisionales. Probablemente, porque el usuario es provisional, se trata de interactuar como si fuera a través del correo electrónico regular.

2 Me gusta

En realidad, había varias.

  • nivel de correo predeterminado: el valor predeterminado es “solo cuando esté ausente”.
  • ventana de tiempo del correo: el valor predeterminado es 10 minutos, por lo que el correo de notificación no se envía de inmediato.
  • deshabilitar correos: el valor predeterminado es “no”, pero yo lo había cambiado antes y se me olvidó :man_facepalming:

Bueno, para mí la notificación de publicación no se parece realmente a un correo electrónico normal de todos modos; por ejemplo, tiene un enlace al perfil del autor de la publicación en el foro (¡dos veces!), pero no al tema.

Además, me gustaría informar al usuario provisional de que en realidad puede iniciar sesión en el foro.
¿Hay alguna forma de personalizar esta plantilla de correo electrónico?

Por diseño, hay varios campos que se omiten para los usuarios en fase de prueba en las plantillas de correo electrónico (como las instrucciones de respuesta):

No estoy completamente seguro de la razón, solo digo que en el código es así, por lo que actualmente estás luchando una batalla cuesta arriba porque estás intentando hacer algo que Discourse está diseñado para no hacer.

Sí, puedes editar las plantillas de correo electrónico, pero tienes muchas limitaciones en lo que puedes personalizar. Por ejemplo, no creo que puedas hacer que la plantilla de correo electrónico se vea de una manera para los usuarios en fase de prueba y de otra para los usuarios que no lo están, pero sí puedes agregar un mensaje con un enlace al final del correo de notificación invitándolos a visitar tu sitio en lugar de interactuar solo por correo electrónico.

1 me gusta

En realidad, bastaría con que la plantilla se vea de la misma manera para los usuarios regulares y los usuarios en etapa de prueba :slight_smile:
Pensaré en qué podría hacer. ¡Gracias por la explicación detallada!

3 Me gusta

Una última pregunta (espero): ¿cómo puede un usuario en etapa de prueba darse de baja para dejar de recibir nuevas publicaciones en el tema creado en su nombre?