2019-05-02 14:57:12 +08:00
# frozen_string_literal: true
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
render json : { errors : [ e . message ] } , status : 422
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 { | 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 " )
2019-01-10 10:52:15 +08:00
. each { | post_id , user_id , key | reply_keys [ [ post_id , user_id ] ] = key }
2018-07-18 16:28:44 +08:00
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 ] )
2019-05-07 09:27:05 +08:00
message , skip_reason =
UserNotifications . public_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
render json : { errors : [ e . message ] } , status : 422
end
else
render json : { errors : skip_reason }
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
2021-05-06 10:59:52 +08:00
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
2017-04-27 16:49:21 +08:00
retry_count = 0
begin
2022-02-05 03:58:34 +08:00
Jobs . enqueue (
:process_email ,
mail : email_raw ,
retry_on_rate_limit : true ,
source : " handle_mail " ,
)
2021-05-10 12:26:23 +08:00
rescue JSON :: GeneratorError , Encoding :: UndefinedConversionError = > e
2017-04-27 16:49:21 +08:00
if retry_count == 0
2021-05-06 10:59:52 +08:00
email_raw = email_raw . force_encoding ( " iso-8859-1 " ) . encode ( " UTF-8 " )
2017-04-27 16:49:21 +08:00
retry_count += 1
retry
else
raise e
end
end
2021-05-06 10:59:52 +08:00
if deprecated_email_param_used
2023-07-18 10:13:40 +08:00
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
2021-05-06 10:59:52 +08:00
else
render plain : " email has been received and is queued for processing "
end
2015-10-19 05:33:24 +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
2019-03-27 00:59:56 +08:00
email_log = EmailLog . find_by ( id : params [ :id ] . to_i , bounced : true )
raise Discourse :: InvalidParameters if email_log & . bounce_key . blank?
2017-02-23 01:51:33 +08:00
2019-03-27 00:59:56 +08:00
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
2017-03-03 07:37:28 +08:00
2022-04-12 11:22:15 +08:00
# 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
2017-03-03 07:37:28 +08:00
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
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 )
2016-01-19 07:57:55 +08:00
. references ( :user )
. order ( created_at : :desc )
. offset ( params [ :offset ] || 0 )
. limit ( 50 )
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?
2022-08-03 06:11:54 +08:00
if table_name == " email_logs " && params [ :smtp_transaction_response ] . present?
logs =
logs . where (
" #{ table_name } .smtp_transaction_response ILIKE ? " ,
" % #{ params [ :smtp_transaction_response ] } % " ,
)
end
2018-07-24 12:55:43 +08:00
logs
2016-01-19 07:57:55 +08:00
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 )
2023-01-09 20:20:10 +08:00
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 . 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
2013-06-04 04:12:24 +08:00
end