mirror of
https://github.com/discourse/discourse.git
synced 2024-12-01 00:33:44 +08:00
7c0534c292
We have a number of raw comments indicating that certain methods and classes are deprecated and marked for removal. This change turn those comments into deprecation warnings so that we can 1) see them in the logs of our own hosting and 2) give some warning to self hosters.
294 lines
8.9 KiB
Ruby
294 lines
8.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Admin::EmailController < Admin::AdminController
|
|
def index
|
|
data = { delivery_method: delivery_method, settings: delivery_settings }
|
|
render_json_dump(data)
|
|
end
|
|
|
|
def test
|
|
params.require(:email_address)
|
|
begin
|
|
message = TestMailer.send_test(params[:email_address])
|
|
Email::Sender.new(message, :test_message).send
|
|
|
|
render json: { sent_test_email_message: I18n.t("admin.email.sent_test") }
|
|
rescue => e
|
|
render json: { errors: [e.message] }, status: 422
|
|
end
|
|
end
|
|
|
|
def sent
|
|
email_logs = EmailLog.joins(<<~SQL)
|
|
LEFT JOIN post_reply_keys
|
|
ON post_reply_keys.post_id = email_logs.post_id
|
|
AND post_reply_keys.user_id = email_logs.user_id
|
|
SQL
|
|
|
|
email_logs = filter_logs(email_logs, params)
|
|
|
|
if (reply_key = params[:reply_key]).present?
|
|
email_logs =
|
|
if reply_key.length == 32
|
|
email_logs.where("post_reply_keys.reply_key = ?", reply_key)
|
|
else
|
|
email_logs.where(
|
|
"replace(post_reply_keys.reply_key::VARCHAR, '-', '') ILIKE ?",
|
|
"%#{reply_key}%",
|
|
)
|
|
end
|
|
end
|
|
|
|
email_logs = email_logs.to_a
|
|
|
|
tuples = email_logs.map { |email_log| [email_log.post_id, email_log.user_id] }
|
|
|
|
reply_keys = {}
|
|
|
|
if tuples.present?
|
|
PostReplyKey
|
|
.where("(post_id,user_id) IN (#{(["(?)"] * tuples.size).join(", ")})", *tuples)
|
|
.pluck(:post_id, :user_id, "reply_key::text")
|
|
.each { |post_id, user_id, key| reply_keys[[post_id, user_id]] = key }
|
|
end
|
|
|
|
render_serialized(email_logs, EmailLogSerializer, reply_keys: reply_keys)
|
|
end
|
|
|
|
def skipped
|
|
skipped_email_logs = filter_logs(SkippedEmailLog, params)
|
|
render_serialized(skipped_email_logs, SkippedEmailLogSerializer)
|
|
end
|
|
|
|
def bounced
|
|
email_logs = filter_logs(EmailLog.bounced, params)
|
|
render_serialized(email_logs, EmailLogSerializer)
|
|
end
|
|
|
|
def received
|
|
incoming_emails = filter_incoming_emails(IncomingEmail, params)
|
|
render_serialized(incoming_emails, IncomingEmailSerializer)
|
|
end
|
|
|
|
def rejected
|
|
incoming_emails = filter_incoming_emails(IncomingEmail.errored, params)
|
|
render_serialized(incoming_emails, IncomingEmailSerializer)
|
|
end
|
|
|
|
def preview_digest
|
|
params.require(:last_seen_at)
|
|
params.require(:username)
|
|
user = User.find_by_username(params[:username])
|
|
raise Discourse::InvalidParameters unless user
|
|
|
|
renderer = Email::Renderer.new(UserNotifications.digest(user, since: params[:last_seen_at]))
|
|
render json: MultiJson.dump(html_content: renderer.html, text_content: renderer.text)
|
|
end
|
|
|
|
def advanced_test
|
|
params.require(:email)
|
|
|
|
receiver = Email::Receiver.new(params["email"])
|
|
text, elided, format = receiver.select_body
|
|
|
|
render json: success_json.merge!(text: text, elided: elided, format: format)
|
|
end
|
|
|
|
def send_digest
|
|
params.require(:last_seen_at)
|
|
params.require(:username)
|
|
params.require(:email)
|
|
user = User.find_by_username(params[:username])
|
|
|
|
message, skip_reason =
|
|
UserNotifications.public_send(:digest, user, since: params[:last_seen_at])
|
|
|
|
if message
|
|
message.to = params[:email]
|
|
begin
|
|
Email::Sender.new(message, :digest).send
|
|
render json: success_json
|
|
rescue => e
|
|
render json: { errors: [e.message] }, status: 422
|
|
end
|
|
else
|
|
render json: { errors: skip_reason }
|
|
end
|
|
end
|
|
|
|
def smtp_should_reject
|
|
params.require(:from)
|
|
params.require(:to)
|
|
# These strings aren't localized; they are sent to an anonymous SMTP user.
|
|
if !User.with_email(Email.downcase(params[:from])).exists? && !SiteSetting.enable_staged_users
|
|
render json: {
|
|
reject: true,
|
|
reason: "Mail from your address is not accepted. Do you have an account here?",
|
|
}
|
|
elsif Email::Receiver.check_address(Email.downcase(params[:to])).nil?
|
|
render json: {
|
|
reject: true,
|
|
reason:
|
|
"Mail to this address is not accepted. Check the address and try to send again?",
|
|
}
|
|
else
|
|
render json: { reject: false }
|
|
end
|
|
end
|
|
|
|
def handle_mail
|
|
deprecated_email_param_used = false
|
|
|
|
if params[:email_encoded].present?
|
|
email_raw = Base64.strict_decode64(params[:email_encoded])
|
|
elsif params[:email].present?
|
|
deprecated_email_param_used = true
|
|
email_raw = params[:email]
|
|
else
|
|
raise ActionController::ParameterMissing.new("email_encoded or email")
|
|
end
|
|
|
|
retry_count = 0
|
|
|
|
begin
|
|
Jobs.enqueue(
|
|
:process_email,
|
|
mail: email_raw,
|
|
retry_on_rate_limit: true,
|
|
source: "handle_mail",
|
|
)
|
|
rescue JSON::GeneratorError, Encoding::UndefinedConversionError => e
|
|
if retry_count == 0
|
|
email_raw = email_raw.force_encoding("iso-8859-1").encode("UTF-8")
|
|
retry_count += 1
|
|
retry
|
|
else
|
|
raise e
|
|
end
|
|
end
|
|
|
|
if deprecated_email_param_used
|
|
warning =
|
|
"warning: the email parameter is deprecated. all POST requests to this route should be sent with a base64 strict encoded email_encoded parameter instead. email has been received and is queued for processing"
|
|
|
|
Discourse.deprecate(warning, drop_from: "3.3.0")
|
|
|
|
render plain: warning
|
|
else
|
|
render plain: "email has been received and is queued for processing"
|
|
end
|
|
end
|
|
|
|
def incoming
|
|
params.require(:id)
|
|
incoming_email = IncomingEmail.find(params[:id].to_i)
|
|
serializer = IncomingEmailDetailsSerializer.new(incoming_email, root: false)
|
|
render_json_dump(serializer)
|
|
end
|
|
|
|
def incoming_from_bounced
|
|
params.require(:id)
|
|
|
|
begin
|
|
email_log = EmailLog.find_by(id: params[:id].to_i, bounced: true)
|
|
raise Discourse::InvalidParameters if email_log&.bounce_key.blank?
|
|
|
|
if Email::Sender.bounceable_reply_address?
|
|
bounced_to_address = Email::Sender.bounce_address(email_log.bounce_key)
|
|
incoming_email = IncomingEmail.find_by(to_addresses: bounced_to_address)
|
|
end
|
|
|
|
if incoming_email.nil?
|
|
email_local_part, email_domain = SiteSetting.notification_email.split("@")
|
|
bounced_to_address = "#{email_local_part}+verp-#{email_log.bounce_key}@#{email_domain}"
|
|
incoming_email = IncomingEmail.find_by(to_addresses: bounced_to_address)
|
|
end
|
|
|
|
# Temporary fix until all old format of emails has been purged via lib/email/cleaner.rb
|
|
if incoming_email.nil?
|
|
email_local_part, email_domain = SiteSetting.reply_by_email_address.split("@")
|
|
subdomain, root_domain, extension = email_domain&.split(".")
|
|
bounced_to_address = "#{subdomain}+verp-#{email_log.bounce_key}@#{root_domain}.#{extension}"
|
|
incoming_email = IncomingEmail.find_by(to_addresses: bounced_to_address)
|
|
end
|
|
|
|
raise Discourse::NotFound if incoming_email.nil?
|
|
|
|
serializer = IncomingEmailDetailsSerializer.new(incoming_email, root: false)
|
|
render_json_dump(serializer)
|
|
rescue => e
|
|
render json: { errors: [e.message] }, status: 404
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def filter_logs(logs, params)
|
|
table_name = logs.table_name
|
|
|
|
logs =
|
|
logs
|
|
.includes(:user, post: :topic)
|
|
.references(:user)
|
|
.order(created_at: :desc)
|
|
.offset(params[:offset] || 0)
|
|
.limit(50)
|
|
|
|
logs = logs.where("users.username ILIKE ?", "%#{params[:user]}%") if params[:user].present?
|
|
logs = logs.where("#{table_name}.to_address ILIKE ?", "%#{params[:address]}%") if params[
|
|
:address
|
|
].present?
|
|
logs = logs.where("#{table_name}.email_type ILIKE ?", "%#{params[:type]}%") if params[
|
|
:type
|
|
].present?
|
|
|
|
if table_name == "email_logs" && params[:smtp_transaction_response].present?
|
|
logs =
|
|
logs.where(
|
|
"#{table_name}.smtp_transaction_response ILIKE ?",
|
|
"%#{params[:smtp_transaction_response]}%",
|
|
)
|
|
end
|
|
|
|
logs
|
|
end
|
|
|
|
def filter_incoming_emails(incoming_emails, params)
|
|
incoming_emails =
|
|
incoming_emails
|
|
.includes(:user, post: :topic)
|
|
.order(created_at: :desc)
|
|
.offset(params[:offset] || 0)
|
|
.limit(50)
|
|
|
|
incoming_emails = incoming_emails.where("from_address ILIKE ?", "%#{params[:from]}%") if params[
|
|
:from
|
|
].present?
|
|
incoming_emails =
|
|
incoming_emails.where(
|
|
"to_addresses ILIKE :to OR cc_addresses ILIKE :to",
|
|
to: "%#{params[:to]}%",
|
|
) if params[:to].present?
|
|
incoming_emails = incoming_emails.where("subject ILIKE ?", "%#{params[:subject]}%") if params[
|
|
:subject
|
|
].present?
|
|
incoming_emails = incoming_emails.where("error ILIKE ?", "%#{params[:error]}%") if params[
|
|
:error
|
|
].present?
|
|
|
|
incoming_emails
|
|
end
|
|
|
|
def delivery_settings
|
|
action_mailer_settings.reject { |k, _| k == :password }.map { |k, v| { name: k, value: v } }
|
|
end
|
|
|
|
def delivery_method
|
|
ActionMailer::Base.delivery_method
|
|
end
|
|
|
|
def action_mailer_settings
|
|
ActionMailer::Base.public_send "#{delivery_method}_settings"
|
|
end
|
|
end
|