The discussion is about creating a script to send a welcome message to a large user base in the background. Jacob_Peebles initially asked for help with the script, and CocoQuark provided a starting point using a Rails script. The script queues users, sends a message to each user one at a time, and organizes the send by most recent login/visit.
CocoQuark also provided an updated script that allows the message to be sent from a specific admin user instead of the ‘system’ user. Jacob_Peebles mentioned that they have 3.5 million users and plan to run the script in batches of 10k, stopping for a few days to check activity and email reputation before starting again.
The conversation also touched on the idea of making the script more automated, allowing it to run for batches of users and stop itself after a certain number of records. CocoQuark suggested setting up a system to restart the script from the last user in case it is interrupted.
NateDhaliwal and CocoQuark discussed editing the script to change the sender user. Finally, Jacob_Peebles asked how to keep track of where the script is in the process, so they can start again from the correct record after stopping.
As seen in posts by CocoQuark, the script can be updated to include a sender username, and CocoQuark also suggested using a session manager to run the script in the background.
Overall, the discussion is focused on creating and refining a script to send welcome messages to a large user base in a controlled and automated way.
MAX_MESSAGES = 1000 # Optional limit for testing
SECONDS_BETWEEN_MESSAGES = 3 # 3 second interval
Rails.logger.info "Starting bulk message script..."
# Define the content of your message
message_title = "Welcome to Our Community"
message_body = "Hello! We're so excited to have you here. Let us know if you have any questions!"
# Fetch users ordered by last seen
users = User.where(active: true)
.where.not(staged: true) # Exclude staged users
.order(last_seen_at: :desc)
.limit(MAX_MESSAGES)
Rails.logger.info "Found #{users.count} active users to message."
users.each_with_index do |user, index|
begin
Rails.logger.info "Queuing message for #{user.username} (#{index + 1}/#{users.count})..."
PostCreator.create!(
Discourse.system_user,
title: message_title,
raw: message_body,
archetype: Archetype.private_message,
target_usernames: user.username,
skip_validations: true
)
Rails.logger.info "Message successfully queued for #{user.username}."
# Wait for the specified interval before processing the next user
sleep(SECONDS_BETWEEN_MESSAGES)
rescue => e
Rails.logger.error "Failed to send message to #{user.username}: #{e.message}"
end
end
Rails.logger.info "Bulk message script completed!"
I didn’t do any modification, and the user system sent the MP to all my users in my test instance:
@Canapin first that’s an amazing handle…but your response is even more amazing! This is really right along the lines of what we want to do. Some more detail.
We have 3.5 million users. We do not plan to send to all of them at once, the idea would be to run this script, maybe for batches of 10k, then stop for a few days, see what kinda of activity we have, check email reputation, and then start again, and so on.
We would like to send this though from an admin with a profile rather than ‘system’, I assume that’s possible?
Yes, just replace system with the desired username in the script.
Sorry, I skimmed the code, there is no system to replace, so it must be done another way.
You’ll probably want to use a session manager like screen or tmux so your script can run in the background.
I assume you’ll also want to be able stop the script when desired and restart it later from the user it stopped at.
Since I’m not a programmer (I mean, besides printing hello world…), I’ll let others give advice on how to set up this feature properly, as well as safely managing the sending to millions of users
@Canapin All sensible, and thanks. Yes I am thinking there is a way to just do some sort of count of records the system would run through, so basically it would just stop itself, but understood on the other options.
If anyone else has any ideas on how to make this more automated (run for batches of 10k users for example) that would be great.
Yeah. If I were to create this kind of script, I’d set up something that would allow me to restart from the last user in case the script is forcibly interrupted by something (server restart, crash…, etc.).
Here’s the updated script with the sender username:
MAX_MESSAGES = 1000 # Optional limit for testing
SECONDS_BETWEEN_MESSAGES = 3 # 3 second interval
SENDER_USERNAME = "coco"
message_sender = User.find_by(username: SENDER_USERNAME)
if message_sender.nil?
Rails.logger.error "Sender user '#{message_sender_username}' not found!"
exit
end
Rails.logger.info "Starting bulk message script..."
# Define the content of your message
message_title = "Welcome to Our Community"
message_body = "Hello! We're so excited to have you here. Let us know if you have any questions!"
# Fetch users ordered by last seen
users = User.where(active: true)
.where.not(staged: true) # Exclude staged users
.order(last_seen_at: :desc)
.limit(MAX_MESSAGES)
Rails.logger.info "Found #{users.count} active users to message."
users.each_with_index do |user, index|
begin
Rails.logger.info "Queuing message for #{user.username} (#{index + 1}/#{users.count})..."
PostCreator.create!(
message_sender,
title: message_title,
raw: message_body,
archetype: Archetype.private_message,
target_usernames: user.username,
skip_validations: true
)
Rails.logger.info "Message successfully queued for #{user.username}."
# Wait for the specified interval before processing the next user
sleep(SECONDS_BETWEEN_MESSAGES)
rescue => e
Rails.logger.error "Failed to send message to #{user.username}: #{e.message}"
end
end
Rails.logger.info "Bulk message script completed!"
Another question here. Does anyone have any idea how to keep track of where the script is in the process? For example we send 10k emails and stop. Then want to start again, how would we know which record to start with?