otwarchive-symphonyarchive/app/mailers/user_mailer.rb
2026-03-11 22:22:11 +00:00

417 lines
15 KiB
Ruby

class UserMailer < ApplicationMailer
helper_method :current_user
helper_method :current_admin
helper_method :logged_in?
helper_method :logged_in_as_admin?
helper :application
helper :tags
helper :works
helper :users
helper :date
helper :series
include HtmlCleaner
# Send an email letting a creator know that their work has been added to a collection by an archivist
def archivist_added_to_collection_notification(user_id, work_id, collection_id)
@user = User.find(user_id)
@work = Work.find(work_id)
@collection = Collection.find(collection_id)
mail(
to: @user.email,
subject: t(".subject", app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title)
)
end
# Send a request to a work owner asking that they approve the inclusion
# of their work in a collection
def invited_to_collection_notification(user_id, work_id, collection_id)
@user = User.find(user_id)
@work = Work.find(work_id)
@collection = Collection.find(collection_id)
mail(
to: @user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title)
)
end
# We use an options hash here, instead of keyword arguments, to avoid
# compatibility issues with resque/resque_mailer.
def anonymous_or_unrevealed_notification(user_id, work_id, collection_id, options = {})
options = options.with_indifferent_access
@becoming_anonymous = options.fetch(:anonymous, false)
@becoming_unrevealed = options.fetch(:unrevealed, false)
return unless @becoming_anonymous || @becoming_unrevealed
@user = User.find(user_id)
@work = Work.find(work_id)
@collection = Collection.find(collection_id)
# Symbol used to pick the appropriate translation string:
@status = if @becoming_anonymous && @becoming_unrevealed
:anonymous_unrevealed
elsif @becoming_anonymous
:anonymous
else
:unrevealed
end
mail(
to: @user.email,
subject: t(".subject.#{@status}", app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Sends an invitation to join the archive
# Must be sent synchronously as it is rescued
# TODO refactor to make it asynchronous
def invitation(invitation_id)
@invitation = Invitation.find(invitation_id)
@user_name = (@invitation.creator.is_a?(User) ? @invitation.creator.login : "")
mail(
to: @invitation.invitee_email,
subject: t("user_mailer.invitation.subject", app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Sends an invitation to join the archive and claim stories that have been imported as part of a bulk import
def invitation_to_claim(invitation_id, archivist_login)
@invitation = Invitation.find(invitation_id)
@external_author = @invitation.external_author
@archivist = archivist_login || "An archivist"
@token = @invitation.token
mail(
to: @invitation.invitee_email,
subject: t("user_mailer.invitation_to_claim.subject", app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Notifies a writer that their imported works have been claimed
def claim_notification(creator_id, claimed_work_ids)
creator = User.find(creator_id)
@external_email = creator.email
@claimed_works = Work.where(id: claimed_work_ids)
mail(
to: creator.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Sends a batched subscription notification
def batch_subscription_notification(subscription_id, entries)
# Here we use find_by_id so that if the subscription is not found
# then the resque job does not error and we just silently fail.
@subscription = Subscription.find_by(id: subscription_id)
return if @subscription.nil?
creation_entries = JSON.parse(entries)
@creations = []
# look up all the creations that have generated updates for this subscription
creation_entries.each do |creation_info|
creation_type, creation_id = creation_info.split("_")
creation = creation_type.constantize.where(id: creation_id).first
next unless creation && creation.try(:posted)
next if creation.is_a?(Chapter) && !creation.work.try(:posted)
next if creation.try(:hidden_by_admin) || (creation.is_a?(Chapter) && creation.work.try(:hidden_by_admin))
next if creation.pseuds.any? { |p| p.user == User.orphan_account } # no notifications for orphan works
# TODO: allow subscriptions to orphan_account to receive notifications
# If the subscription notification is for a user subscription, we don't
# want to send updates about works that have recently become anonymous.
if @subscription.subscribable_type == "User"
next if Subscription.anonymous_creation?(creation)
end
@creations << creation
end
return if @creations.empty?
# make sure we only notify once per creation
@creations.uniq!
subject = @subscription.subject_text(@creations.first)
subject += " and #{@creations.count - 1} more" if @creations.count > 1
I18n.with_locale(@subscription.user.preference.locale_for_mails) do
mail(
to: @subscription.user.email,
subject: "[#{ArchiveConfig.APP_SHORT_NAME}] #{subject}"
)
end
end
# Emails a user to say they have been given more invitations for their friends
def invite_increase_notification(user_id, total)
@user = User.find(user_id)
@total = total
mail(
to: @user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Emails a user to say that their request for invitation codes has been declined
def invite_request_declined(user_id, total, reason)
@user = User.find(user_id)
@total = total
@reason = reason
mail(
to: @user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
def collection_notification(collection_id, subject, message, email)
@message = message
@collection = Collection.find(collection_id)
mail(
to: email,
subject: "[#{ArchiveConfig.APP_SHORT_NAME}][#{@collection.title}] #{subject}"
)
end
def invalid_signup_notification(collection_id, invalid_signup_ids, email)
@collection = Collection.find(collection_id)
@invalid_signups = invalid_signup_ids
@is_collection_email = (email == @collection.collection_email)
mail(
to: email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title)
)
end
# This is sent at the end of matching, i.e., after assignments are generated.
# It is also sent when assignments are regenerated.
def potential_match_generation_notification(collection_id, email)
@collection = Collection.find(collection_id)
@is_collection_email = (email == @collection.collection_email)
mail(
to: email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title)
)
end
def challenge_assignment_notification(collection_id, assigned_user_id, assignment_id)
@collection = Collection.find(collection_id)
@assigned_user = User.find(assigned_user_id)
@assignment = ChallengeAssignment.find(assignment_id)
@request = @assignment.request_signup
mail(
to: @assigned_user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title)
)
end
# Asks a user to validate and activate their new account
def signup_notification(user_id)
@user = User.find(user_id)
I18n.with_locale(@user.preference.locale_for_mails) do
mail(
to: @user.email,
subject: t("user_mailer.signup_notification.subject", app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
end
# Confirms to a user that their email was changed
def change_email(user_id, old_email, new_email)
@user = User.find(user_id)
@old_email = old_email
@new_email = new_email
@pac_footer = true
mail(
to: @old_email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
def change_username(user, old_username)
@user = user
@old_username = old_username
@new_username = user.login
@next_change_time = user.renamed_at + ArchiveConfig.USER_RENAME_LIMIT_DAYS.days
mail(
to: @user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
### WORKS NOTIFICATIONS ###
# Sends email when an archivist adds someone as a co-creator.
def creatorship_notification_archivist(creatorship_id, archivist_id)
@creatorship = Creatorship.find(creatorship_id)
@archivist = User.find(archivist_id)
@user = @creatorship.pseud.user
@creation = @creatorship.creation
mail(
to: @user.email,
subject: t("user_mailer.creatorship_notification_archivist.subject",
app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Sends email when a user is added as a co-creator
def creatorship_notification(creatorship_id, adding_user_id)
@creatorship = Creatorship.find(creatorship_id)
@adding_user = User.find(adding_user_id)
@user = @creatorship.pseud.user
@creation = @creatorship.creation
mail(
to: @user.email,
subject: t("user_mailer.creatorship_notification.subject",
app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Sends email when a user is added as an unapproved/pending co-creator
def creatorship_request(creatorship_id, inviting_user_id)
@creatorship = Creatorship.find(creatorship_id)
@inviting_user = User.find(inviting_user_id)
@user = @creatorship.pseud.user
@creation = @creatorship.creation
mail(
to: @user.email,
subject: t("user_mailer.creatorship_request.subject",
app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Sends emails to creators whose stories were listed as the inspiration of another work
def related_work_notification(user_id, related_work_id)
@user = User.find(user_id)
@related_work = RelatedWork.find(related_work_id)
@related_parent_link = url_for(controller: :works, action: :show, id: @related_work.parent)
@related_child_link = url_for(controller: :works, action: :show, id: @related_work.work)
mail(
to: @user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Emails a recipient to say that a gift has been posted for them
def recipient_notification(user_id, work_id, collection_id = nil)
@user = User.find(user_id)
@work = Work.find(work_id)
@collection = Collection.find(collection_id) if collection_id
subject = if @collection
t("user_mailer.recipient_notification.subject.collection",
app_name: ArchiveConfig.APP_SHORT_NAME,
collection_title: @collection.title)
else
t("user_mailer.recipient_notification.subject.no_collection",
app_name: ArchiveConfig.APP_SHORT_NAME)
end
mail(
to: @user.email,
subject: subject
)
end
# Emails a prompter to say that a response has been posted to their prompt
def prompter_notification(work_id, collection_id = nil)
@work = Work.find(work_id)
@collection = Collection.find(collection_id) if collection_id
@work.challenge_claims.each do |claim|
user = User.find(claim.request_signup.pseud.user.id)
I18n.with_locale(user.preference.locale_for_mails) do
mail(
to: user.email,
subject: "[#{ArchiveConfig.APP_SHORT_NAME}] A response to your prompt"
)
end
end
end
# Sends email to creators when a creation is deleted
# NOTE: this must be sent synchronously! otherwise the work will no longer be there to send
# TODO refactor to make it asynchronous by passing the content in the method
def delete_work_notification(user, work, deleter)
@user = user
@work = work
@deleter = deleter
download = Download.new(@work, mime_type: "text/html", include_draft_chapters: true)
html = DownloadWriter.new(download).generate_html
html = ::Mail::Encodings::Base64.encode(html)
attachments["#{download.file_name}.html"] = { content: html, encoding: "base64" }
attachments["#{download.file_name}.txt"] = { content: html, encoding: "base64" }
mail(
to: user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Sends email to creators when a creation is deleted by an admin
# NOTE: this must be sent synchronously! otherwise the work will no longer be there to send
# TODO refactor to make it asynchronous by passing the content in the method
def admin_deleted_work_notification(user, work)
@user = user
@work = work
download = Download.new(@work, mime_type: "text/html", include_draft_chapters: true)
html = DownloadWriter.new(download).generate_html
html = ::Mail::Encodings::Base64.encode(html)
attachments["#{download.file_name}.html"] = { content: html, encoding: "base64" }
attachments["#{download.file_name}.txt"] = { content: html, encoding: "base64" }
mail(
to: user.email,
subject: t("user_mailer.admin_deleted_work_notification.subject", app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
# Sends email to creators when a creation is hidden by an admin
def admin_hidden_work_notification(creation_ids, user_id)
@pac_footer = true
@user = User.find_by(id: user_id)
@works = Work.where(id: creation_ids)
return if @works.empty?
mail(
to: @user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, count: @works.size)
)
end
def admin_spam_work_notification(creation_id, user_id)
@user = User.find_by(id: user_id)
@work = Work.find_by(id: creation_id)
mail(
to: @user.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME)
)
end
### OTHER NOTIFICATIONS ###
# archive feedback
def feedback(feedback_id)
feedback = Feedback.find(feedback_id)
return unless feedback.email
@summary = feedback.summary
@comment = feedback.comment
@username = feedback.username if feedback.username.present?
@language = feedback.language
mail(
to: feedback.email,
subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, summary: strip_html_breaks_simple(feedback.summary))
)
end
def abuse_report(abuse_report_id)
abuse_report = AbuseReport.find(abuse_report_id)
@username = abuse_report.username
@email = abuse_report.email
@url = abuse_report.url
@summary = abuse_report.summary
@comment = abuse_report.comment
mail(
to: abuse_report.email,
subject: t("user_mailer.abuse_report.subject", app_name: ArchiveConfig.APP_SHORT_NAME, summary: strip_html_breaks_simple(@summary))
)
end
end