We currently have a workflow where users submit data by sending an email to a custom incoming email address, creating a staged user and a private message to a Discourse group.
Is it possible to achieve the same workflow using API calls? Basically 1) create staged user, 2) generate API key for that user, then 3) post on that users behalf? I see how to post group messages for existing users using the API docs, but don’t know if steps 1) and 2) are possible currently.
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!
Could you specify, what headers and fields should be in the API call to /admin/email/handle_email that creates a staged user and a topic on his behalf?
Also, did I get it right, that such a user will receive notifications for new posts in such a topic and will be able to reply to it via email?
And what happens, if I try to create a staged user and a topic via an API call with an email address that belongs to an active user? Will this topic be created on behalf of such user?
I already found out, that the correct endpoint is /admin/email/handle_mail (not “handle_email”), but still can’t figure out, what should be in the API request.
Thank you, Blake. However, it still doesn’t work for me. I got a response from API “email has been received and is queued for processing”, but nothing appears in Discourse - neither a new topic, nor a staged user.
Here’s the review of the settings:
Global:
email_in: on
email_in_min_trust: 0
enable_staged_users: on
Category:
Custom incoming email address: set as [my_name]@gmail.com
Accept emails from anonymous users with no accounts: on
API call: 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."
You can check if sidekiq is running by browsing to /sidekiq, but I think there is likely an issue with the raw email now that the api request is succeeding. There are several tabs in the admin dashboard you can check for email errors.
/admin/email/sent
/admin/email/skipped
/admin/email/bounced
/admin/email/received
/admin/email/rejected
See if you can find the emails you are creating via api calls under one of those tabs and you might be able do see an error message associated with it.
I inserted the same email text in the “Advanced text” tab, and it seems to be working, if each part (Date, From, To, Subject) starts with a new line, and the body is separated by two line breaks. When inserting the text exactly like in curl, it returns nothing. Could it be the line breaks in the raw email? If yes, what should I do?
You were right - that was a newline issue. I tried the same API call from Postman, and it worked - a new staged user was created and a topic on his behalf.
But: no email was sent to this user’s address! I also posted a comment in the topic - no email notification either. Is there a setting that prevents this? I tried to find one, but I couldn’t.
UPD: There was a indeed a setting that prevented sending post notifications so now I have two different questions:
Why there wasn’t an email informing the staged user that the topic was created and sending him the link to it?
(I would also add some instructions about how to log in to the forum if I knew, which template to edit.)
Why there’s no link to the topic in the post notification emails? Also no unsubscribe link.
The template seems to be the same - “user_posted”.
Which setting for anyone following along? I don’t think I had to change anything, so just curious.
I think this is by design and the same happens if you send an email to a Discourse group. It is designed to work just like email as in the user might not even know they are sending an email into a Discourse forum. If I send you a regular email to your email account I don’t get a reply back from your email provider that says you received my email, we just trust that it works.
Here is an example email notification a staged user will receive:
There appears to be a difference between staged users and non-staged users. Likely because the user is staged it is to be just like interacting via regular email.
email time window - default is 10 minutes, so the notification email is not sent immediately
disable emails - default is “no”, but I had it changed before and forgot about it
Well, for me the post notification doesn’t really look like a regular email anyway - e.g. it has a link to the post author’s profile at the forum (twice!), but not to the topic.
I’m not entirely sure of the reasoning, jut stating that in code this is how it is, so you are currently fighting an up hill battle here because you are attempting to do something discourse is designed not to do.
Yes, you can edit the email templates, but you are pretty limited in what you can customize. Like I don’t think you can customize the email template to look one way for staged users and another way for non-staged users, but you can add a message with a link to the bottom of the notification email inviting them to visit your site instead of just interacting via email.
Actually, it would be enought if the template looks the same way for regular and staged users
I’ll think, what I could do. Thank you for the detailed explanation!