2019-05-02 02:57:12 -04:00
# frozen_string_literal: true
2013-06-03 16:12:24 -04:00
class Admin :: EmailController < Admin :: AdminController
def index
2014-02-14 18:50:08 -05:00
data = { delivery_method : delivery_method , settings : delivery_settings }
render_json_dump ( data )
2013-06-03 16:12:24 -04:00
end
def test
params . require ( :email_address )
2014-11-19 10:49:12 -05:00
begin
2019-03-21 17:57:09 -04: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 10:49:12 -05:00
rescue = > e
render json : { errors : [ e . message ] } , status : 422
end
2013-06-03 16:12:24 -04:00
end
2014-02-14 18:50:08 -05:00
def sent
2018-07-27 00:32:07 -04: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 04:28:44 -04:00
email_logs = filter_logs ( email_logs , params )
2019-01-09 20:56:03 -05: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 04:28:44 -04: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-09 21:52:15 -05:00
. each do | post_id , user_id , key |
reply_keys [ [ post_id , user_id ] ] = key
2018-07-18 04:28:44 -04:00
end
end
render_serialized ( email_logs , EmailLogSerializer , reply_keys : reply_keys )
2014-02-14 13:06:21 -05:00
end
def skipped
2018-07-24 00:55:43 -04:00
skipped_email_logs = filter_logs ( SkippedEmailLog , params )
render_serialized ( skipped_email_logs , SkippedEmailLogSerializer )
2013-06-03 16:12:24 -04:00
end
2016-05-02 17:15:32 -04:00
def bounced
2018-07-24 00:55:43 -04:00
email_logs = filter_logs ( EmailLog . bounced , params )
2016-05-02 17:15:32 -04:00
render_serialized ( email_logs , EmailLogSerializer )
end
2016-01-18 18:57:55 -05: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-03 16:12:24 -04:00
def preview_digest
params . require ( :last_seen_at )
2015-10-30 14:05:54 -04:00
params . require ( :username )
user = User . find_by_username ( params [ :username ] )
2019-01-30 03:04:47 -05:00
raise Discourse :: InvalidParameters unless user
2015-10-30 14:05:54 -04:00
renderer = Email :: Renderer . new ( UserNotifications . digest ( user , since : params [ :last_seen_at ] ) )
2013-06-03 16:12:24 -04:00
render json : MultiJson . dump ( html_content : renderer . html , text_content : renderer . text )
end
2018-11-28 18:03:50 -05: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-23 17:46:57 -05:00
def send_digest
params . require ( :last_seen_at )
params . require ( :username )
params . require ( :email )
user = User . find_by_username ( params [ :username ] )
2019-05-06 21:27:05 -04:00
message , skip_reason = UserNotifications . public_send ( :digest , user ,
since : params [ :last_seen_at ]
)
2016-11-23 17:46:57 -05:00
if message
message . to = params [ :email ]
begin
Email :: Sender . new ( message , :digest ) . send
2016-11-24 15:05:33 -05:00
render json : success_json
2016-11-23 17:46:57 -05:00
rescue = > e
render json : { errors : [ e . message ] } , status : 422
end
else
render json : { errors : skip_reason }
end
end
2017-04-05 02:32:50 -04: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-26 14:47:36 -04:00
if ! User . with_email ( Email . downcase ( params [ :from ] ) ) . exists? && ! SiteSetting . enable_staged_users
2017-04-06 01:49:34 -04:00
render json : { reject : true , reason : " Mail from your address is not accepted. Do you have an account here? " }
2017-04-05 12:45:58 -04:00
elsif Email :: Receiver . check_address ( Email . downcase ( params [ :to ] ) ) . nil?
2017-04-06 01:49:34 -04:00
render json : { reject : true , reason : " Mail to this address is not accepted. Check the address and try to send again? " }
2017-04-05 02:32:50 -04:00
else
2017-04-06 01:49:34 -04:00
render json : { reject : false }
2017-04-05 02:32:50 -04:00
end
end
2015-10-18 17:33:24 -04:00
def handle_mail
2021-05-05 22:59:52 -04: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 04:49:21 -04:00
retry_count = 0
begin
2022-02-04 14:58:34 -05:00
Jobs . enqueue ( :process_email , mail : email_raw , retry_on_rate_limit : true , source : " handle_mail " )
2021-05-10 00:26:23 -04:00
rescue JSON :: GeneratorError , Encoding :: UndefinedConversionError = > e
2017-04-27 04:49:21 -04:00
if retry_count == 0
2021-05-05 22:59:52 -04:00
email_raw = email_raw . force_encoding ( 'iso-8859-1' ) . encode ( " UTF-8 " )
2017-04-27 04:49:21 -04:00
retry_count += 1
retry
else
raise e
end
end
2021-05-05 22:59:52 -04:00
# TODO: 2022-05-01 Remove this route once all sites have migrated over
# to using the new email_encoded param.
if deprecated_email_param_used
2022-01-13 18:33:15 -05:00
render plain : " 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 "
2021-05-05 22:59:52 -04:00
else
render plain : " email has been received and is queued for processing "
end
2015-10-18 17:33:24 -04:00
end
2016-02-01 15:41:49 -05:00
def raw_email
params . require ( :id )
incoming_email = IncomingEmail . find ( params [ :id ] . to_i )
2017-03-08 17:15:42 -05:00
text , html = Email . extract_parts ( incoming_email . raw )
render json : { raw_email : incoming_email . raw , text_part : text , html_part : html }
2016-02-01 15:41:49 -05:00
end
2016-02-10 16:00:27 -05: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-22 12:51:33 -05:00
def incoming_from_bounced
params . require ( :id )
2017-03-02 18:37:28 -05:00
begin
2019-03-26 12:59:56 -04:00
email_log = EmailLog . find_by ( id : params [ :id ] . to_i , bounced : true )
raise Discourse :: InvalidParameters if email_log & . bounce_key . blank?
2017-02-22 12:51:33 -05:00
2019-03-26 12:59:56 -04: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-02 18:37:28 -05:00
2022-04-11 23:22:15 -04: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-02 18:37:28 -05: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-22 12:51:33 -05:00
end
2013-06-11 19:00:13 -04:00
private
2018-07-24 00:55:43 -04:00
def filter_logs ( logs , params )
table_name = logs . table_name
logs = logs . includes ( :user , post : :topic )
2016-01-18 18:57:55 -05:00
. references ( :user )
. order ( created_at : :desc )
. offset ( params [ :offset ] || 0 )
. limit ( 50 )
2018-07-24 00:55:43 -04: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-18 18:57:55 -05: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 )
incoming_emails = incoming_emails . where ( " from_address ILIKE ? " , " % #{ params [ :from ] } % " ) if params [ :from ] . present?
2016-07-13 16:43:25 -04:00
incoming_emails = incoming_emails . where ( " to_addresses ILIKE :to OR cc_addresses ILIKE :to " , to : " % #{ params [ :to ] } % " ) if params [ :to ] . present?
2016-01-18 18:57:55 -05: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-14 18:50:08 -05:00
end
2013-06-11 19:00:13 -04:00
def delivery_settings
action_mailer_settings
2014-08-14 17:54:55 -04:00
. reject { | k , _ | k == :password }
2013-06-11 19:00:13 -04:00
. 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-03 16:12:24 -04:00
end