2013-06-11 03:33:37 +08:00
|
|
|
require_dependency 'email/renderer'
|
2013-06-04 04:12:24 +08:00
|
|
|
|
|
|
|
class Admin::EmailController < Admin::AdminController
|
|
|
|
|
|
|
|
def index
|
2014-02-15 07:50:08 +08:00
|
|
|
data = { delivery_method: delivery_method, settings: delivery_settings }
|
|
|
|
render_json_dump(data)
|
2013-06-04 04:12:24 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def test
|
|
|
|
params.require(:email_address)
|
2014-11-19 23:49:12 +08:00
|
|
|
begin
|
2019-03-22 05:57:09 +08:00
|
|
|
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") }
|
2014-11-19 23:49:12 +08:00
|
|
|
rescue => e
|
2017-07-28 09:20:09 +08:00
|
|
|
render json: { errors: [e.message] }, status: 422
|
2014-11-19 23:49:12 +08:00
|
|
|
end
|
2013-06-04 04:12:24 +08:00
|
|
|
end
|
|
|
|
|
2014-02-15 07:50:08 +08:00
|
|
|
def sent
|
2018-07-27 12:32:07 +08:00
|
|
|
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
|
2018-07-18 16:28:44 +08:00
|
|
|
|
|
|
|
email_logs = filter_logs(email_logs, params)
|
|
|
|
|
2019-01-10 09:56:03 +08:00
|
|
|
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
|
2018-07-18 16:28:44 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
email_logs = email_logs.to_a
|
|
|
|
|
|
|
|
tuples = email_logs.map do |email_log|
|
|
|
|
[email_log.post_id, email_log.user_id]
|
|
|
|
end
|
|
|
|
|
|
|
|
reply_keys = {}
|
|
|
|
|
|
|
|
if tuples.present?
|
|
|
|
PostReplyKey
|
|
|
|
.where(
|
|
|
|
"(post_id,user_id) IN (#{(['(?)'] * tuples.size).join(', ')})",
|
|
|
|
*tuples
|
|
|
|
)
|
|
|
|
.pluck(:post_id, :user_id, "reply_key::text")
|
2019-01-10 10:52:15 +08:00
|
|
|
.each do |post_id, user_id, key|
|
|
|
|
reply_keys[[post_id, user_id]] = key
|
2018-07-18 16:28:44 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
render_serialized(email_logs, EmailLogSerializer, reply_keys: reply_keys)
|
2014-02-15 02:06:21 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def skipped
|
2018-07-24 12:55:43 +08:00
|
|
|
skipped_email_logs = filter_logs(SkippedEmailLog, params)
|
|
|
|
render_serialized(skipped_email_logs, SkippedEmailLogSerializer)
|
2013-06-04 04:12:24 +08:00
|
|
|
end
|
|
|
|
|
2016-05-03 05:15:32 +08:00
|
|
|
def bounced
|
2018-07-24 12:55:43 +08:00
|
|
|
email_logs = filter_logs(EmailLog.bounced, params)
|
2016-05-03 05:15:32 +08:00
|
|
|
render_serialized(email_logs, EmailLogSerializer)
|
|
|
|
end
|
|
|
|
|
2016-01-19 07:57:55 +08:00
|
|
|
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
|
|
|
|
|
2013-06-04 04:12:24 +08:00
|
|
|
def preview_digest
|
|
|
|
params.require(:last_seen_at)
|
2015-10-31 02:05:54 +08:00
|
|
|
params.require(:username)
|
|
|
|
user = User.find_by_username(params[:username])
|
2019-01-30 16:04:47 +08:00
|
|
|
raise Discourse::InvalidParameters unless user
|
|
|
|
|
2015-10-31 02:05:54 +08:00
|
|
|
renderer = Email::Renderer.new(UserNotifications.digest(user, since: params[:last_seen_at]))
|
2013-06-04 04:12:24 +08:00
|
|
|
render json: MultiJson.dump(html_content: renderer.html, text_content: renderer.text)
|
|
|
|
end
|
|
|
|
|
2018-11-29 07:03:50 +08:00
|
|
|
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
|
|
|
|
|
2016-11-24 06:46:57 +08:00
|
|
|
def send_digest
|
|
|
|
params.require(:last_seen_at)
|
|
|
|
params.require(:username)
|
|
|
|
params.require(:email)
|
|
|
|
user = User.find_by_username(params[:username])
|
2017-07-28 09:20:09 +08:00
|
|
|
message, skip_reason = UserNotifications.send(:digest, user, since: params[:last_seen_at])
|
2016-11-24 06:46:57 +08:00
|
|
|
if message
|
|
|
|
message.to = params[:email]
|
|
|
|
begin
|
|
|
|
Email::Sender.new(message, :digest).send
|
2016-11-25 04:05:33 +08:00
|
|
|
render json: success_json
|
2016-11-24 06:46:57 +08:00
|
|
|
rescue => e
|
2017-07-28 09:20:09 +08:00
|
|
|
render json: { errors: [e.message] }, status: 422
|
2016-11-24 06:46:57 +08:00
|
|
|
end
|
|
|
|
else
|
2017-07-28 09:20:09 +08:00
|
|
|
render json: { errors: skip_reason }
|
2016-11-24 06:46:57 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-04-05 14:32:50 +08:00
|
|
|
def smtp_should_reject
|
|
|
|
params.require(:from)
|
|
|
|
params.require(:to)
|
|
|
|
# These strings aren't localized; they are sent to an anonymous SMTP user.
|
2017-04-27 02:47:36 +08:00
|
|
|
if !User.with_email(Email.downcase(params[:from])).exists? && !SiteSetting.enable_staged_users
|
2017-04-06 13:49:34 +08:00
|
|
|
render json: { reject: true, reason: "Mail from your address is not accepted. Do you have an account here?" }
|
2017-04-06 00:45:58 +08:00
|
|
|
elsif Email::Receiver.check_address(Email.downcase(params[:to])).nil?
|
2017-04-06 13:49:34 +08:00
|
|
|
render json: { reject: true, reason: "Mail to this address is not accepted. Check the address and try to send again?" }
|
2017-04-05 14:32:50 +08:00
|
|
|
else
|
2017-04-06 13:49:34 +08:00
|
|
|
render json: { reject: false }
|
2017-04-05 14:32:50 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-19 05:33:24 +08:00
|
|
|
def handle_mail
|
|
|
|
params.require(:email)
|
2017-04-27 16:49:21 +08:00
|
|
|
retry_count = 0
|
|
|
|
|
|
|
|
begin
|
|
|
|
Jobs.enqueue(:process_email, mail: params[:email], retry_on_rate_limit: true)
|
|
|
|
rescue JSON::GeneratorError => e
|
|
|
|
if retry_count == 0
|
|
|
|
params[:email] = params[:email].force_encoding('iso-8859-1').encode("UTF-8")
|
|
|
|
retry_count += 1
|
|
|
|
retry
|
|
|
|
else
|
|
|
|
raise e
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-04-24 12:06:28 +08:00
|
|
|
render plain: "email has been received and is queued for processing"
|
2015-10-19 05:33:24 +08:00
|
|
|
end
|
|
|
|
|
2016-02-02 04:41:49 +08:00
|
|
|
def raw_email
|
|
|
|
params.require(:id)
|
|
|
|
incoming_email = IncomingEmail.find(params[:id].to_i)
|
2017-03-09 06:15:42 +08:00
|
|
|
text, html = Email.extract_parts(incoming_email.raw)
|
|
|
|
render json: { raw_email: incoming_email.raw, text_part: text, html_part: html }
|
2016-02-02 04:41:49 +08:00
|
|
|
end
|
|
|
|
|
2016-02-11 05:00:27 +08:00
|
|
|
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
|
|
|
|
|
2017-02-23 01:51:33 +08:00
|
|
|
def incoming_from_bounced
|
|
|
|
params.require(:id)
|
|
|
|
|
2017-03-03 07:37:28 +08:00
|
|
|
begin
|
|
|
|
bounced = EmailLog.find_by(id: params[:id].to_i)
|
|
|
|
raise Discourse::InvalidParameters if bounced.nil?
|
2017-02-23 01:51:33 +08:00
|
|
|
|
2017-03-03 07:37:28 +08:00
|
|
|
email_local_part, email_domain = SiteSetting.notification_email.split('@')
|
|
|
|
bounced_to_address = "#{email_local_part}+verp-#{bounced.bounce_key}@#{email_domain}"
|
|
|
|
|
|
|
|
incoming_email = IncomingEmail.find_by(to_addresses: bounced_to_address)
|
|
|
|
raise Discourse::NotFound if incoming_email.nil?
|
|
|
|
|
|
|
|
serializer = IncomingEmailDetailsSerializer.new(incoming_email, root: false)
|
|
|
|
render_json_dump(serializer)
|
|
|
|
rescue => e
|
2017-07-28 09:20:09 +08:00
|
|
|
render json: { errors: [e.message] }, status: 404
|
2017-03-03 07:37:28 +08:00
|
|
|
end
|
2017-02-23 01:51:33 +08:00
|
|
|
end
|
|
|
|
|
2013-06-12 07:00:13 +08:00
|
|
|
private
|
|
|
|
|
2018-07-24 12:55:43 +08:00
|
|
|
def filter_logs(logs, params)
|
|
|
|
table_name = logs.table_name
|
|
|
|
|
|
|
|
logs = logs.includes(:user, post: :topic)
|
2017-07-28 09:20:09 +08:00
|
|
|
.references(:user)
|
|
|
|
.order(created_at: :desc)
|
|
|
|
.offset(params[:offset] || 0)
|
|
|
|
.limit(50)
|
2016-01-19 07:57:55 +08:00
|
|
|
|
2018-07-24 12:55:43 +08:00
|
|
|
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?
|
|
|
|
logs
|
2016-01-19 07:57:55 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def filter_incoming_emails(incoming_emails, params)
|
2017-07-28 09:20:09 +08:00
|
|
|
incoming_emails = incoming_emails.includes(:user, post: :topic)
|
|
|
|
.order(created_at: :desc)
|
|
|
|
.offset(params[:offset] || 0)
|
|
|
|
.limit(50)
|
2016-01-19 07:57:55 +08:00
|
|
|
|
|
|
|
incoming_emails = incoming_emails.where("from_address ILIKE ?", "%#{params[:from]}%") if params[:from].present?
|
2016-07-14 04:43:25 +08:00
|
|
|
incoming_emails = incoming_emails.where("to_addresses ILIKE :to OR cc_addresses ILIKE :to", to: "%#{params[:to]}%") if params[:to].present?
|
2016-01-19 07:57:55 +08:00
|
|
|
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
|
2014-02-15 07:50:08 +08:00
|
|
|
end
|
|
|
|
|
2013-06-12 07:00:13 +08:00
|
|
|
def delivery_settings
|
|
|
|
action_mailer_settings
|
2014-08-15 05:54:55 +08:00
|
|
|
.reject { |k, _| k == :password }
|
2017-07-28 09:20:09 +08:00
|
|
|
.map { |k, v| { name: k, value: v } }
|
2013-06-12 07:00:13 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def delivery_method
|
|
|
|
ActionMailer::Base.delivery_method
|
|
|
|
end
|
|
|
|
|
|
|
|
def action_mailer_settings
|
|
|
|
ActionMailer::Base.public_send "#{delivery_method}_settings"
|
|
|
|
end
|
2013-06-04 04:12:24 +08:00
|
|
|
end
|