2019-04-30 08:27:42 +08:00
# frozen_string_literal: true
2016-01-19 07:57:55 +08:00
require " email/receiver "
2013-06-11 04:46:08 +08:00
2022-07-28 10:27:38 +08:00
RSpec . describe Email :: Receiver do
2013-06-14 06:11:10 +08:00
before do
2016-01-19 07:57:55 +08:00
SiteSetting . email_in = true
SiteSetting . reply_by_email_address = " reply+%{reply_key}@bar.com "
2016-06-10 22:14:42 +08:00
SiteSetting . alternative_reply_by_email_addresses = " alt+%{reply_key}@bar.com "
2013-06-14 06:11:10 +08:00
end
2013-06-11 04:46:08 +08:00
2021-01-20 11:22:41 +08:00
def process ( email_name , opts = { } )
Email :: Receiver . new ( email ( email_name ) , opts ) . process!
2016-01-19 07:57:55 +08:00
end
2014-08-27 08:08:53 +08:00
2016-01-19 07:57:55 +08:00
it " raises an EmptyEmailError when 'mail_string' is blank " do
expect { Email :: Receiver . new ( nil ) } . to raise_error ( Email :: Receiver :: EmptyEmailError )
expect { Email :: Receiver . new ( " " ) } . to raise_error ( Email :: Receiver :: EmptyEmailError )
end
2014-08-29 03:09:42 +08:00
2016-04-19 04:58:30 +08:00
it " raises a ScreenedEmailError when email address is screened " do
ScreenedEmail . expects ( :should_block? ) . with ( " screened@mail.com " ) . returns ( true )
expect { process ( :screened_email ) } . to raise_error ( Email :: Receiver :: ScreenedEmailError )
end
2020-07-27 08:23:54 +08:00
it " raises EmailNotAllowed when email address is not on allowlist " do
SiteSetting . allowed_email_domains = " example.com|bar.com "
2019-04-08 17:36:39 +08:00
Fabricate ( :group , incoming_email : " some_group@bar.com " )
2020-07-27 08:23:54 +08:00
expect { process ( :blocklist_allowlist_email ) } . to raise_error ( Email :: Receiver :: EmailNotAllowed )
2017-10-03 17:23:18 +08:00
end
2020-07-27 08:23:54 +08:00
it " raises EmailNotAllowed when email address is on blocklist " do
SiteSetting . blocked_email_domains = " email.com|mail.com "
2019-04-08 17:36:39 +08:00
Fabricate ( :group , incoming_email : " some_group@bar.com " )
2020-07-27 08:23:54 +08:00
expect { process ( :blocklist_allowlist_email ) } . to raise_error ( Email :: Receiver :: EmailNotAllowed )
2017-10-03 17:23:18 +08:00
end
2016-04-19 04:58:30 +08:00
it " raises an UserNotFoundError when staged users are disabled " do
2016-03-24 01:56:03 +08:00
SiteSetting . enable_staged_users = false
expect { process ( :user_not_found ) } . to raise_error ( Email :: Receiver :: UserNotFoundError )
end
2016-01-19 07:57:55 +08:00
it " raises an AutoGeneratedEmailError when the mail is auto generated " do
expect { process ( :auto_generated_precedence ) } . to raise_error (
Email :: Receiver :: AutoGeneratedEmailError ,
)
expect { process ( :auto_generated_header ) } . to raise_error (
Email :: Receiver :: AutoGeneratedEmailError ,
)
end
2014-11-26 00:44:59 +08:00
2016-01-19 07:57:55 +08:00
it " raises a NoBodyDetectedError when the body is blank " do
expect { process ( :no_body ) } . to raise_error ( Email :: Receiver :: NoBodyDetectedError )
end
2014-12-02 02:21:14 +08:00
2017-09-13 04:35:24 +08:00
it " raises a NoSenderDetectedError when the From header is missing " do
expect { process ( :no_from ) } . to raise_error ( Email :: Receiver :: NoSenderDetectedError )
end
2016-01-19 07:57:55 +08:00
it " raises an InactiveUserError when the sender is inactive " do
Fabricate ( :user , email : " inactive@bar.com " , active : false )
expect { process ( :inactive_sender ) } . to raise_error ( Email :: Receiver :: InactiveUserError )
end
2015-11-19 04:22:50 +08:00
2017-11-11 01:18:08 +08:00
it " raises a SilencedUserError when the sender has been silenced " do
2017-11-14 02:41:36 +08:00
Fabricate ( :user , email : " silenced@bar.com " , silenced_till : 1 . year . from_now )
2017-11-11 01:18:08 +08:00
expect { process ( :silenced_sender ) } . to raise_error ( Email :: Receiver :: SilencedUserError )
2016-02-11 17:39:57 +08:00
end
2017-07-24 21:25:26 +08:00
it " doesn't raise an InactiveUserError when the sender is staged " do
user = Fabricate ( :user , email : " staged@bar.com " , active : false , staged : true )
2018-07-18 16:28:44 +08:00
post = Fabricate ( :post )
2017-07-24 21:25:26 +08:00
2018-07-18 16:28:44 +08:00
post_reply_key =
Fabricate (
:post_reply_key ,
2017-07-24 21:25:26 +08:00
user : user ,
2018-07-18 16:28:44 +08:00
post : post ,
reply_key : " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " ,
2017-07-24 21:25:26 +08:00
)
2016-01-19 07:57:55 +08:00
expect { process ( :staged_sender ) } . not_to raise_error
end
2015-11-19 04:22:50 +08:00
2016-01-19 07:57:55 +08:00
it " raises a BadDestinationAddress when destinations aren't matching any of the incoming emails " do
expect { process ( :bad_destinations ) } . to raise_error ( Email :: Receiver :: BadDestinationAddress )
end
2015-11-19 04:22:50 +08:00
2018-05-10 00:51:01 +08:00
it " raises an OldDestinationError when notification is too old " do
2018-08-21 16:17:08 +08:00
SiteSetting . disallow_reply_by_email_after_days = 2
2022-10-25 15:29:09 +08:00
topic = Fabricate ( :topic )
post = Fabricate ( :post , topic : topic )
2019-04-08 17:36:39 +08:00
user = Fabricate ( :user , email : " discourse@bar.com " )
2018-08-21 16:17:08 +08:00
2022-10-25 15:29:09 +08:00
mail = email ( :old_destination ) . gsub ( " 424242 " , topic . id . to_s )
expect { Email :: Receiver . new ( mail ) . process! } . to raise_error (
2018-08-21 16:17:08 +08:00
Email :: Receiver :: BadDestinationAddress ,
)
IncomingEmail . destroy_all
post . update! ( created_at : 3 . days . ago )
2018-05-10 00:51:01 +08:00
2022-10-25 15:29:09 +08:00
expect { Email :: Receiver . new ( mail ) . process! } . to raise_error (
2018-08-21 16:17:08 +08:00
Email :: Receiver :: OldDestinationError ,
)
2022-03-03 21:28:13 +08:00
expect ( IncomingEmail . last . error ) . to eq ( " Email::Receiver::OldDestinationError " )
2018-08-21 16:17:08 +08:00
SiteSetting . disallow_reply_by_email_after_days = 0
IncomingEmail . destroy_all
2022-10-25 15:29:09 +08:00
expect { Email :: Receiver . new ( mail ) . process! } . to raise_error (
2018-08-21 16:17:08 +08:00
Email :: Receiver :: BadDestinationAddress ,
)
2018-05-10 00:51:01 +08:00
end
2022-07-28 00:14:14 +08:00
describe " bounces " do
2018-11-27 02:59:37 +08:00
it " raises a BouncerEmailError " do
expect { process ( :bounced_email ) } . to raise_error ( Email :: Receiver :: BouncedEmailError )
expect ( IncomingEmail . last . is_bounce ) . to eq ( true )
expect { process ( :bounced_email_multiple_status_codes ) } . to raise_error (
Email :: Receiver :: BouncedEmailError ,
)
expect ( IncomingEmail . last . is_bounce ) . to eq ( true )
end
2018-11-28 10:54:23 +08:00
describe " creating whisper post in PMs for staged users " do
let ( :email_address ) { " linux-admin@b-s-c.co.jp " }
2019-05-07 11:12:20 +08:00
fab! ( :user1 ) { Fabricate ( :user ) }
let ( :user2 ) { Fabricate ( :staged , email : email_address ) }
2018-11-28 23:43:06 +08:00
let ( :topic ) do
Fabricate (
:topic ,
archetype : " private_message " ,
category_id : nil ,
user : user1 ,
allowed_users : [ user1 , user2 ] ,
)
2023-01-09 19:18:21 +08:00
end
2018-11-28 23:43:06 +08:00
let ( :post ) { create_post ( topic : topic , user : user1 ) }
2018-11-28 10:54:23 +08:00
before do
SiteSetting . enable_staged_users = true
2022-12-17 00:42:51 +08:00
SiteSetting . whispers_allowed_groups = " #{ Group :: AUTO_GROUPS [ :staff ] } "
2018-11-28 10:54:23 +08:00
end
def create_post_reply_key ( value )
Fabricate ( :post_reply_key , reply_key : value , user : user2 , post : post )
end
it " when bounce without verp " do
create_post_reply_key ( " 4f97315cc828096c9cb34c6f1a0d6fe8 " )
expect { process ( :bounced_email ) } . to raise_error ( Email :: Receiver :: BouncedEmailError )
post = Post . last
expect ( post . whisper? ) . to eq ( true )
expect ( post . raw ) . to eq (
I18n . t (
" system_messages.email_bounced " ,
email : email_address ,
raw : " Your email bounced " ,
) . strip ,
)
expect ( IncomingEmail . last . is_bounce ) . to eq ( true )
end
2022-02-15 12:17:26 +08:00
context " when bounce with verp " do
let ( :bounce_key ) { " 14b08c855160d67f2e0c2f8ef36e251e " }
before do
SiteSetting . reply_by_email_address = " foo+%{reply_key}@discourse.org "
create_post_reply_key ( bounce_key )
Fabricate (
:email_log ,
to_address : email_address ,
user : user2 ,
bounce_key : bounce_key ,
post : post ,
)
end
it " creates a post with the bounce error " do
expect { process ( :hard_bounce_via_verp ) } . to raise_error (
Email :: Receiver :: BouncedEmailError ,
)
post = Post . last
expect ( post . whisper? ) . to eq ( true )
expect ( post . raw ) . to eq (
I18n . t (
" system_messages.email_bounced " ,
email : email_address ,
raw : " Your email bounced " ,
) . strip ,
)
expect ( IncomingEmail . last . is_bounce ) . to eq ( true )
end
it " updates the email log with the bounce error message " do
expect { process ( :hard_bounce_via_verp ) } . to raise_error (
Email :: Receiver :: BouncedEmailError ,
)
email_log = EmailLog . find_by ( bounce_key : bounce_key )
expect ( email_log . bounced ) . to eq ( true )
expect ( email_log . bounce_error_code ) . to eq ( " 5.1.1 " )
end
2018-11-28 10:54:23 +08:00
end
2018-11-27 02:59:37 +08:00
end
2016-04-07 22:21:17 +08:00
end
2017-08-04 22:20:44 +08:00
it " logs a blank error " do
Email :: Receiver . any_instance . stubs ( :process_internal ) . raises ( RuntimeError , " " )
2023-01-09 19:18:21 +08:00
begin
2017-08-04 22:20:44 +08:00
process ( :existing_user )
rescue StandardError
RuntimeError
2023-01-09 19:18:21 +08:00
end
2017-08-04 22:20:44 +08:00
expect ( IncomingEmail . last . error ) . to eq ( " RuntimeError " )
end
2018-10-11 09:46:32 +08:00
it " strips null bytes from the subject " do
expect do process ( :null_byte_in_subject ) end . to raise_error (
Email :: Receiver :: BadDestinationAddress ,
)
end
2022-07-28 00:14:14 +08:00
describe " bounces to VERP " do
2016-05-03 05:15:32 +08:00
let ( :bounce_key ) { " 14b08c855160d67f2e0c2f8ef36e251e " }
let ( :bounce_key_2 ) { " b542fb5a9bacda6d28cc061d18e4eb83 " }
2019-05-07 11:12:20 +08:00
fab! ( :user ) { Fabricate ( :user , email : " linux-admin@b-s-c.co.jp " ) }
2018-11-28 21:34:09 +08:00
let! ( :email_log ) do
Fabricate ( :email_log , to_address : user . email , user : user , bounce_key : bounce_key )
2023-01-09 19:18:21 +08:00
end
2018-11-28 21:34:09 +08:00
let! ( :email_log_2 ) do
Fabricate ( :email_log , to_address : user . email , user : user , bounce_key : bounce_key_2 )
2023-01-09 19:18:21 +08:00
end
2016-05-03 05:15:32 +08:00
it " deals with soft bounces " do
expect { process ( :soft_bounce_via_verp ) } . to raise_error ( Email :: Receiver :: BouncedEmailError )
email_log . reload
expect ( email_log . bounced ) . to eq ( true )
2018-05-09 22:40:52 +08:00
expect ( email_log . user . user_stat . bounce_score ) . to eq ( SiteSetting . soft_bounce_score )
2016-05-03 05:15:32 +08:00
end
it " deals with hard bounces " do
expect { process ( :hard_bounce_via_verp ) } . to raise_error ( Email :: Receiver :: BouncedEmailError )
email_log . reload
expect ( email_log . bounced ) . to eq ( true )
2018-05-09 22:40:52 +08:00
expect ( email_log . user . user_stat . bounce_score ) . to eq ( SiteSetting . hard_bounce_score )
2016-05-03 05:15:32 +08:00
2017-07-24 21:17:42 +08:00
expect { process ( :hard_bounce_via_verp_2 ) } . to raise_error ( Email :: Receiver :: BouncedEmailError )
email_log_2 . reload
2018-05-09 22:40:52 +08:00
expect ( email_log_2 . user . user_stat . bounce_score ) . to eq ( SiteSetting . hard_bounce_score * 2 )
2017-07-24 21:17:42 +08:00
expect ( email_log_2 . bounced ) . to eq ( true )
2016-05-03 05:15:32 +08:00
end
2019-05-03 19:12:44 +08:00
it " works when the final recipient is different " do
expect { process ( :verp_bounce_different_final_recipient ) } . to raise_error (
Email :: Receiver :: BouncedEmailError ,
)
email_log . reload
expect ( email_log . bounced ) . to eq ( true )
expect ( email_log . user . user_stat . bounce_score ) . to eq ( SiteSetting . soft_bounce_score )
end
2018-08-03 22:39:22 +08:00
it " sends a system message once they reach the 'bounce_score_threshold' " do
expect ( user . active ) . to eq ( true )
user . user_stat . bounce_score = SiteSetting . bounce_score_threshold - 1
user . user_stat . save!
SystemMessage . expects ( :create_from_system_user ) . with ( user , :email_revoked )
expect { process ( :hard_bounce_via_verp ) } . to raise_error ( Email :: Receiver :: BouncedEmailError )
end
2016-05-03 05:15:32 +08:00
end
2022-07-28 00:14:14 +08:00
describe " reply " do
2016-01-19 07:57:55 +08:00
let ( :reply_key ) { " 4f97315cc828096c9cb34c6f1a0d6fe8 " }
2019-05-07 11:12:20 +08:00
fab! ( :category ) { Fabricate ( :category ) }
fab! ( :user ) { Fabricate ( :user , email : " discourse@bar.com " ) }
fab! ( :topic ) { create_topic ( category : category , user : user ) }
fab! ( :post ) { create_post ( topic : topic ) }
2018-07-18 16:28:44 +08:00
let! ( :post_reply_key ) do
Fabricate ( :post_reply_key , reply_key : reply_key , user : user , post : post )
end
2014-11-26 00:44:59 +08:00
2019-03-06 15:38:49 +08:00
let :topic_user do
TopicUser . find_by ( topic_id : topic . id , user_id : user . id )
end
2016-03-15 01:18:58 +08:00
it " uses MD5 of 'mail_string' there is no message_id " do
mail_string = email ( :missing_message_id )
expect { Email :: Receiver . new ( mail_string ) . process! } . to change { IncomingEmail . count }
expect ( IncomingEmail . last . message_id ) . to eq ( Digest :: MD5 . hexdigest ( mail_string ) )
end
2016-01-19 07:57:55 +08:00
it " raises a ReplyUserNotMatchingError when the email address isn't matching the one we sent the notification to " do
2019-04-08 17:36:39 +08:00
Fabricate ( :user , email : " someone_else@bar.com " )
2016-01-19 07:57:55 +08:00
expect { process ( :reply_user_not_matching ) } . to raise_error (
Email :: Receiver :: ReplyUserNotMatchingError ,
)
2014-11-26 00:44:59 +08:00
end
2018-05-23 16:04:45 +08:00
it " raises a FromReplyByAddressError when the email is from the reply by email address " do
expect { process ( :from_reply_by_email_address ) } . to raise_error (
Email :: Receiver :: FromReplyByAddressError ,
)
end
2018-07-03 19:51:22 +08:00
it " accepts reply from secondary email address " do
Fabricate ( :secondary_email , email : " someone_else@bar.com " , user : user )
expect { process ( :reply_user_not_matching ) } . to change { topic . posts . count }
post = Post . last
expect ( post . raw ) . to eq ( " Lorem ipsum dolor sit amet, consectetur adipiscing elit. " )
expect ( post . user ) . to eq ( user )
end
2019-06-03 05:49:05 +08:00
it " raises a ReplyNotAllowedError when user without permissions is replying " do
Fabricate ( :user , email : " bob@bar.com " )
category . set_permissions ( admins : :full )
category . save
expect { process ( :reply_user_not_matching_but_known ) } . to raise_error (
Email :: Receiver :: ReplyNotAllowedError ,
)
end
2016-01-19 07:57:55 +08:00
it " raises a TopicNotFoundError when the topic was deleted " do
topic . update_columns ( deleted_at : 1 . day . ago )
expect { process ( :reply_user_matching ) } . to raise_error ( Email :: Receiver :: TopicNotFoundError )
2015-12-10 01:44:01 +08:00
end
2022-07-28 00:14:14 +08:00
context " with a closed topic " do
2019-03-06 15:38:49 +08:00
before { topic . update_columns ( closed : true ) }
it " raises a TopicClosedError when the topic was closed " do
expect { process ( :reply_user_matching ) } . to raise_error ( Email :: Receiver :: TopicClosedError )
end
it " Can watch topics via the watch command " do
# TODO support other locales as well, the tricky thing is that these string live in
# client.yml not on server yml so it is a bit tricky to find
topic . update_columns ( closed : true )
process ( :watch )
expect ( topic_user . notification_level ) . to eq ( NotificationLevels . topic_levels [ :watching ] )
end
2015-12-10 01:44:01 +08:00
2019-03-06 15:38:49 +08:00
it " Can mute topics via the mute command " do
process ( :mute )
expect ( topic_user . notification_level ) . to eq ( NotificationLevels . topic_levels [ :muted ] )
end
it " can track a topic via the track command " do
process ( :track )
expect ( topic_user . notification_level ) . to eq ( NotificationLevels . topic_levels [ :tracking ] )
end
2016-07-05 23:33:08 +08:00
end
2016-01-19 07:57:55 +08:00
it " raises an InvalidPost when there was an error while creating the post " do
2018-08-03 03:43:53 +08:00
expect { process ( :too_small ) } . to raise_error ( Email :: Receiver :: TooShortPost )
2014-11-26 00:44:59 +08:00
end
2016-01-19 07:57:55 +08:00
it " raises an InvalidPost when there are too may mentions " do
SiteSetting . max_mentions_per_post = 1
Fabricate ( :user , username : " user1 " )
Fabricate ( :user , username : " user2 " )
expect { process ( :too_many_mentions ) } . to raise_error ( Email :: Receiver :: InvalidPost )
2014-11-26 00:44:59 +08:00
end
2016-01-19 07:57:55 +08:00
it " raises an InvalidPostAction when they aren't allowed to like a post " do
topic . update_columns ( archived : true )
expect { process ( :like ) } . to raise_error ( Email :: Receiver :: InvalidPostAction )
2014-11-26 00:44:59 +08:00
end
2022-01-10 16:24:10 +08:00
it " creates a new reply post " do
handler_calls = 0
handler = proc { | _ | handler_calls += 1 }
DiscourseEvent . on ( :topic_created , & handler )
2016-01-19 07:57:55 +08:00
expect { process ( :text_reply ) } . to change { topic . posts . count }
2018-04-26 03:52:54 +08:00
expect ( topic . posts . last . raw ) . to eq (
" This is a text reply :) \n \n Email parsing should not break because of a UTF-8 character: ’ " ,
)
2016-01-19 07:57:55 +08:00
expect ( topic . posts . last . via_email ) . to eq ( true )
expect ( topic . posts . last . cooked ) . not_to match ( / <br / )
2014-11-26 00:44:59 +08:00
2016-01-19 07:57:55 +08:00
expect { process ( :html_reply ) } . to change { topic . posts . count }
2017-04-26 22:49:06 +08:00
expect ( topic . posts . last . raw ) . to eq ( " This is a **HTML** reply ;) " )
2022-01-10 16:24:10 +08:00
DiscourseEvent . off ( :topic_created , & handler )
expect ( handler_calls ) . to eq ( 0 )
2017-05-01 05:30:40 +08:00
end
2014-11-26 00:44:59 +08:00
2021-01-20 11:22:41 +08:00
it " stores the created_via source against the incoming email " do
process ( :text_reply , source : :handle_mail )
expect ( IncomingEmail . last . created_via ) . to eq ( IncomingEmail . created_via_types [ :handle_mail ] )
process ( :text_and_html_reply , source : :imap )
expect ( IncomingEmail . last . created_via ) . to eq ( IncomingEmail . created_via_types [ :imap ] )
end
2022-09-26 07:14:24 +08:00
it " stores the message_id of the incoming email against the post as outbound_message_id " do
expect { process ( :text_reply , source : :handle_mail ) } . to change ( Post , :count )
message_id = IncomingEmail . last . message_id
expect ( Post . last . outbound_message_id ) . to eq ( message_id )
end
2018-02-27 06:54:02 +08:00
it " automatically elides gmail quotes " do
SiteSetting . always_show_trimmed_content = true
expect { process ( :gmail_html_reply ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq (
" This is a **GMAIL** reply ;) \n \n <details class='elided'> \n <summary title='Show trimmed content'>& # 183;& # 183;& # 183;</summary> \n \n This is the *elided* part! \n \n </details> " ,
)
end
2017-05-18 22:43:07 +08:00
it " doesn't process email with same message-id more than once " do
expect do
process ( :text_reply )
process ( :text_reply )
end . to change { topic . posts . count } . by ( 1 )
end
2017-05-01 05:30:40 +08:00
it " handles different encodings correctly " do
2016-01-19 07:57:55 +08:00
expect { process ( :hebrew_reply ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq ( " שלום! מה שלומך היום? " )
2014-11-26 00:44:59 +08:00
2016-01-19 07:57:55 +08:00
expect { process ( :chinese_reply ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq ( " 您好! 你今天好吗? " )
2016-03-12 01:51:53 +08:00
expect { process ( :reply_with_weird_encoding ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq ( " This is a reply with a weird encoding. " )
2017-05-01 05:30:40 +08:00
expect { process ( :reply_with_8bit_encoding ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq ( " hab vergessen kritische zeichen einzufügen: \n äöüÄÖÜß " )
2014-11-26 00:44:59 +08:00
end
2018-02-21 18:26:41 +08:00
it " prefers text over html when site setting is disabled " do
SiteSetting . incoming_email_prefer_html = false
2016-01-19 07:57:55 +08:00
expect { process ( :text_and_html_reply ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq ( " This is the *text* part. " )
2014-10-14 18:12:01 +08:00
end
2017-04-27 20:31:11 +08:00
it " prefers html over text when site setting is enabled " do
SiteSetting . incoming_email_prefer_html = true
expect { process ( :text_and_html_reply ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq ( " This is the **html** part. " )
end
it " uses text when prefer_html site setting is enabled but no html is available " do
SiteSetting . incoming_email_prefer_html = true
expect { process ( :text_reply ) } . to change { topic . posts . count }
2018-04-26 03:52:54 +08:00
expect ( topic . posts . last . raw ) . to eq (
" This is a text reply :) \n \n Email parsing should not break because of a UTF-8 character: ’ " ,
)
2017-04-27 20:31:11 +08:00
end
2016-01-19 07:57:55 +08:00
it " removes the 'on <date>, <contact> wrote' quoting line " do
expect { process ( :on_date_contact_wrote ) } . to change { topic . posts . count }
2016-03-18 06:10:46 +08:00
expect ( topic . posts . last . raw ) . to eq ( " This is the actual reply. " )
2014-08-29 03:09:42 +08:00
end
2014-01-17 10:24:32 +08:00
2016-01-19 07:57:55 +08:00
it " removes the 'Previous Replies' marker " do
expect { process ( :previous_replies ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq (
" This will not include the previous discussion that is present in this email. " ,
)
2014-08-27 08:08:53 +08:00
end
2022-10-25 15:29:09 +08:00
it " removes the translated 'Previous Replies' marker " do
2021-08-19 00:42:04 +08:00
expect { process ( :previous_replies_de ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq (
" This will not include the previous discussion that is present in this email. " ,
)
end
2021-08-04 01:08:19 +08:00
it " removes the 'type reply above' marker " do
expect { process ( :reply_above ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq (
" This will not include the previous discussion that is present in this email. " ,
)
end
2021-08-19 00:42:04 +08:00
it " removes the translated 'Previous Replies' marker " do
expect { process ( :reply_above_de ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq (
" This will not include the previous discussion that is present in this email. " ,
)
end
2016-01-19 07:57:55 +08:00
it " handles multiple paragraphs " do
expect { process ( :paragraphs ) } . to change { topic . posts . count }
2021-05-21 09:43:47 +08:00
expect ( topic . posts . last . raw ) . to eq (
" Do you like liquorice? \n \n I really like them. One could even say that I am *addicted* to liquorice. And if \n you can mix it up with some anise, then I'm in heaven ;) " ,
)
2013-08-22 04:54:01 +08:00
end
2013-07-25 02:22:32 +08:00
2023-05-19 16:33:48 +08:00
it " raises a NoSenderDetectedError when the From header can't be parsed " do
expect { process ( :invalid_from_1 ) } . to raise_error ( Email :: Receiver :: NoSenderDetectedError )
2016-02-25 00:40:57 +08:00
end
2017-09-13 04:35:24 +08:00
it " raises a NoSenderDetectedError when the From header doesn't contain an email address " do
expect { process ( :invalid_from_2 ) } . to raise_error ( Email :: Receiver :: NoSenderDetectedError )
end
2023-05-04 00:17:19 +08:00
it " doesn't raise an AutoGeneratedEmailError due to an X-Auto-Response-Suppress header " do
expect { process ( :quirks_exchange_xars ) } . to change { topic . posts . count }
end
2020-07-27 08:23:54 +08:00
it " doesn't raise an AutoGeneratedEmailError when the mail is auto generated but is allowlisted " do
SiteSetting . auto_generated_allowlist = " foo@bar.com|discourse@bar.com "
expect { process ( :auto_generated_allowlisted ) } . to change { topic . posts . count }
2016-04-21 03:29:27 +08:00
end
it " doesn't raise an AutoGeneratedEmailError when block_auto_generated_emails is disabled " do
SiteSetting . block_auto_generated_emails = false
expect { process ( :auto_generated_unblocked ) } . to change { topic . posts . count }
2016-04-12 04:47:34 +08:00
end
2016-06-27 01:25:45 +08:00
it " allows staged users to reply to a restricted category " do
user . update_columns ( staged : true )
category . email_in = " category@bar.com "
category . email_in_allow_strangers = true
category . set_permissions ( Group [ :trust_level_4 ] = > :full )
2019-06-04 16:40:10 +08:00
category . save!
2016-06-27 01:25:45 +08:00
expect { process ( :staged_reply_restricted ) } . to change { topic . posts . count }
end
2018-09-04 05:06:25 +08:00
it " posts a reply to the topic when the post was deleted " do
post . update_columns ( deleted_at : 1 . day . ago )
expect { process ( :reply_user_matching ) } . to change { topic . posts . count }
expect ( topic . ordered_posts . last . reply_to_post_number ) . to be_nil
end
2016-01-20 17:25:25 +08:00
describe " Unsubscribing via email " do
let ( :last_email ) { ActionMailer :: Base . deliveries . last }
describe " unsubscribe_subject.eml " do
it " sends an email asking the user to confirm the unsubscription " do
expect { process ( " unsubscribe_subject " ) } . to change {
ActionMailer :: Base . deliveries . count
} . by ( 1 )
expect ( last_email . to . length ) . to eq 1
expect ( last_email . from . length ) . to eq 1
expect ( last_email . from ) . to include " noreply@ #{ Discourse . current_hostname } "
expect ( last_email . to ) . to include " discourse@bar.com "
expect ( last_email . subject ) . to eq I18n . t ( :" unsubscribe_mailer.subject_template " ) . gsub (
" %{site_title} " ,
SiteSetting . title ,
)
end
it " does nothing unless unsubscribe_via_email is turned on " do
2017-07-07 14:09:14 +08:00
SiteSetting . unsubscribe_via_email = false
2016-01-20 17:25:25 +08:00
before_deliveries = ActionMailer :: Base . deliveries . count
expect { process ( " unsubscribe_subject " ) } . to raise_error {
Email :: Receiver :: BadDestinationAddress
}
expect ( before_deliveries ) . to eq ActionMailer :: Base . deliveries . count
end
end
describe " unsubscribe_body.eml " do
it " sends an email asking the user to confirm the unsubscription " do
expect { process ( " unsubscribe_body " ) } . to change {
ActionMailer :: Base . deliveries . count
} . by ( 1 )
expect ( last_email . to . length ) . to eq 1
expect ( last_email . from . length ) . to eq 1
expect ( last_email . from ) . to include " noreply@ #{ Discourse . current_hostname } "
expect ( last_email . to ) . to include " discourse@bar.com "
expect ( last_email . subject ) . to eq I18n . t ( :" unsubscribe_mailer.subject_template " ) . gsub (
" %{site_title} " ,
SiteSetting . title ,
)
end
it " does nothing unless unsubscribe_via_email is turned on " do
2017-07-07 14:09:14 +08:00
SiteSetting . unsubscribe_via_email = false
2016-01-20 17:25:25 +08:00
before_deliveries = ActionMailer :: Base . deliveries . count
expect { process ( " unsubscribe_body " ) } . to raise_error { Email :: Receiver :: InvalidPost }
expect ( before_deliveries ) . to eq ActionMailer :: Base . deliveries . count
end
end
2017-10-03 16:13:19 +08:00
it " raises an UnsubscribeNotAllowed and does not send an unsubscribe email " do
before_deliveries = ActionMailer :: Base . deliveries . count
expect { process ( :unsubscribe_new_user ) } . to raise_error {
Email :: Receiver :: UnsubscribeNotAllowed
}
expect ( before_deliveries ) . to eq ActionMailer :: Base . deliveries . count
end
2016-01-20 17:25:25 +08:00
end
2016-01-19 07:57:55 +08:00
it " handles inline reply " do
expect { process ( :inline_reply ) } . to change { topic . posts . count }
2017-07-31 17:29:39 +08:00
expect ( topic . posts . last . raw ) . to eq ( " And this is *my* reply :+1: " )
2013-07-25 02:22:32 +08:00
end
2016-01-19 07:57:55 +08:00
it " retrieves the first part of multiple replies " do
expect { process ( :inline_mixed_replies ) } . to change { topic . posts . count }
2016-01-30 08:29:31 +08:00
expect ( topic . posts . last . raw ) . to eq (
" > WAT <https://bar.com/users/wat> November 28 \n > \n > This is the previous post. \n \n And this is *my* reply :+1: \n \n > This is another post. \n \n And this is **another** reply. " ,
)
2013-07-25 02:22:32 +08:00
end
2014-08-27 08:08:53 +08:00
2016-01-30 08:29:31 +08:00
it " strips mobile/webmail signatures " do
2016-01-19 07:57:55 +08:00
expect { process ( :iphone_signature ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq ( " This is not the signature you're looking for. " )
2014-08-27 08:08:53 +08:00
end
2016-01-19 07:57:55 +08:00
it " strips 'original message' context " do
2016-03-18 06:10:46 +08:00
expect { process ( :original_message ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq ( " This is a reply :) " )
end
it " add the 'elided' part of the original message only for private messages " do
topic . update_columns ( category_id : nil , archetype : Archetype . private_message )
topic . allowed_users << user
topic . save
2016-01-19 07:57:55 +08:00
expect { process ( :original_message ) } . to change { topic . posts . count }
2017-12-06 08:47:31 +08:00
expect ( topic . posts . last . raw ) . to eq (
" This is a reply :) \n \n <details class='elided'> \n <summary title='Show trimmed content'>& # 183;& # 183;& # 183;</summary> \n \n ---Original Message--- \n This part should not be included \n \n </details> " ,
)
2014-12-05 00:45:31 +08:00
end
2017-06-29 12:03:14 +08:00
it " doesn't include the 'elided' part of the original message when always_show_trimmed_content is disabled " do
SiteSetting . always_show_trimmed_content = false
2021-04-28 23:08:48 +08:00
expect { process ( :original_message ) } . to change { topic . posts . count }
2017-06-29 12:03:14 +08:00
expect ( topic . posts . last . raw ) . to eq ( " This is a reply :) " )
end
it " adds the 'elided' part of the original message for public replies when always_show_trimmed_content is enabled " do
SiteSetting . always_show_trimmed_content = true
2021-04-28 23:08:48 +08:00
expect { process ( :original_message ) } . to change { topic . posts . count }
2017-12-06 08:47:31 +08:00
expect ( topic . posts . last . raw ) . to eq (
" This is a reply :) \n \n <details class='elided'> \n <summary title='Show trimmed content'>& # 183;& # 183;& # 183;</summary> \n \n ---Original Message--- \n This part should not be included \n \n </details> " ,
)
2017-06-29 12:03:14 +08:00
end
2021-04-28 23:08:48 +08:00
it " doesn't trim the message when trim_incoming_emails is disabled " do
SiteSetting . trim_incoming_emails = false
expect { process ( :original_message ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to eq (
" This is a reply :) \n \n ---Original Message--- \n This part should not be included " ,
)
end
2017-05-04 04:54:26 +08:00
it " supports attached images in TEXT part " do
2018-02-21 18:26:41 +08:00
SiteSetting . incoming_email_prefer_html = false
2017-04-15 12:11:02 +08:00
2016-01-30 08:29:31 +08:00
expect { process ( :no_body_with_image ) } . to change { topic . posts . count }
2019-06-11 14:46:37 +08:00
post = topic . posts . last
upload = post . uploads . first
expect ( post . raw ) . to include (
" ![ #{ upload . original_filename } | #{ upload . width } x #{ upload . height } ]( #{ upload . short_url } ) " ,
)
2013-07-25 02:22:32 +08:00
2016-01-30 08:29:31 +08:00
expect { process ( :inline_image ) } . to change { topic . posts . count }
2019-06-11 14:46:37 +08:00
post = topic . posts . last
upload = post . uploads . first
expect ( post . raw ) . to include (
" ![ #{ upload . original_filename } | #{ upload . width } x #{ upload . height } ]( #{ upload . short_url } ) " ,
)
2017-05-04 04:54:26 +08:00
end
it " supports attached images in HTML part " do
SiteSetting . incoming_email_prefer_html = true
expect { process ( :inline_image ) } . to change { topic . posts . count }
2019-06-11 14:46:37 +08:00
post = topic . posts . last
upload = post . uploads . last
expect ( post . raw ) . to eq ( << ~ MD . chomp )
** Before **
2022-03-29 17:55:10 +08:00
< img src = " #{ upload . short_url } " alt = " 内嵌图片 1 " >
2019-06-11 14:46:37 +08:00
* After *
MD
2014-10-25 22:36:59 +08:00
end
2021-04-29 15:17:33 +08:00
it " gracefully handles malformed images in HTML part " do
expect { process ( :inline_image_2 ) } . to change { topic . posts . count }
post = topic . posts . last
upload = post . uploads . last
expect ( post . raw ) . to eq ( << ~ MD . chomp )
[ image : #{"0" * 5000}
! [ #{upload.original_filename}|#{upload.width}x#{upload.height}](#{upload.short_url})
MD
end
2020-07-08 13:50:30 +08:00
it " supports attached images in signature " do
SiteSetting . incoming_email_prefer_html = true
SiteSetting . always_show_trimmed_content = true
expect { process ( :body_with_image ) } . to change { topic . posts . count }
post = topic . posts . last
upload = post . uploads . last
expect ( post . raw ) . to eq ( << ~ MD . chomp )
This is a ** GMAIL ** reply ; )
< details class = 'elided' >
< summary title = 'Show trimmed content' > & #183;··</summary>
2022-03-29 17:55:10 +08:00
< img src = " upload://qUm0DGR49PAZshIi7HxMd3cAlzn.png " width = " 300 " height = " 200 " >
2020-07-08 13:50:30 +08:00
< / details>
MD
end
2016-01-30 08:29:31 +08:00
it " supports attachments " do
2019-01-26 02:13:34 +08:00
SiteSetting . authorized_extensions = " txt|jpg "
2016-01-30 08:29:31 +08:00
expect { process ( :attached_txt_file ) } . to change { topic . posts . count }
2019-01-29 01:40:52 +08:00
post = topic . posts . last
2019-06-11 14:46:37 +08:00
upload = post . uploads . first
expect ( post . raw ) . to eq ( << ~ MD . chomp )
Please find some text file attached .
[ #{upload.original_filename}|attachment](#{upload.short_url}) (20 Bytes)
MD
2019-01-26 02:13:34 +08:00
expect { process ( :apple_mail_attachment ) } . to change { topic . posts . count }
2019-01-29 01:40:52 +08:00
post = topic . posts . last
2019-06-11 14:46:37 +08:00
upload = post . uploads . first
expect ( post . raw ) . to eq ( << ~ MD . chomp )
Picture below .
2022-03-29 17:55:10 +08:00
< img apple - inline = " yes " id = " 06C04C58-783E-4753-9B6B-D57403903060 " src = " #{ upload . short_url } " class = " " >
2019-06-11 14:46:37 +08:00
Picture above .
MD
2018-11-01 15:41:13 +08:00
end
2020-02-04 01:21:22 +08:00
it " works with removed attachments " do
SiteSetting . authorized_extensions = " jpg "
expect { process ( :removed_attachments ) } . to change { topic . posts . count }
post = topic . posts . last
expect ( post . uploads ) . to be_empty
end
2018-11-01 15:41:13 +08:00
it " supports eml attachments " do
SiteSetting . authorized_extensions = " eml "
expect { process ( :attached_eml_file ) } . to change { topic . posts . count }
2019-01-29 01:40:52 +08:00
post = topic . posts . last
2019-06-11 14:46:37 +08:00
upload = post . uploads . first
expect ( post . raw ) . to eq ( << ~ MD . chomp )
Please find the eml file attached .
[ #{upload.original_filename}|attachment](#{upload.short_url}) (193 Bytes)
MD
2018-10-04 22:08:28 +08:00
end
2021-02-19 02:15:02 +08:00
it " can decode attachments " do
SiteSetting . authorized_extensions = " pdf "
Fabricate ( :group , incoming_email : " one@foo.com " )
process ( :encoded_filename )
expect ( Upload . last . original_filename ) . to eq ( " This is a test.pdf " )
end
2018-10-04 22:08:28 +08:00
context " when attachment is rejected " do
it " sends out the warning email " do
expect { process ( :attached_txt_file ) } . to change { EmailLog . count } . by ( 1 )
expect ( EmailLog . last . email_type ) . to eq ( " email_reject_attachment " )
2019-01-29 01:40:52 +08:00
expect ( topic . posts . last . uploads . size ) . to eq 0
2018-10-04 22:08:28 +08:00
end
2017-11-08 02:17:33 +08:00
2018-10-04 22:08:28 +08:00
it " doesn't send out the warning email if sender is staged user " do
user . update_columns ( staged : true )
expect { process ( :attached_txt_file ) } . not_to change { EmailLog . count }
2019-01-29 01:40:52 +08:00
expect ( topic . posts . last . uploads . size ) . to eq 0
2018-10-04 22:08:28 +08:00
end
it " creates the post with attachment missing message " do
missing_attachment_regex =
Regexp . escape ( I18n . t ( " emails.incoming.missing_attachment " , filename : " text.txt " ) )
expect { process ( :attached_txt_file ) } . to change { topic . posts . count }
2019-01-29 01:40:52 +08:00
post = topic . posts . last
expect ( post . raw ) . to match ( / #{ missing_attachment_regex } / )
expect ( post . uploads . size ) . to eq 0
2018-10-04 22:08:28 +08:00
end
2016-01-30 08:29:31 +08:00
end
2018-02-17 01:14:56 +08:00
it " supports emails with just an attachment " do
SiteSetting . authorized_extensions = " pdf "
expect { process ( :attached_pdf_file ) } . to change { topic . posts . count }
2019-01-29 01:40:52 +08:00
post = topic . posts . last
2019-06-11 14:46:37 +08:00
upload = post . uploads . last
expect ( post . raw ) . to include (
" [ #{ upload . original_filename } |attachment]( #{ upload . short_url } ) (64 KB) " ,
)
2018-02-17 01:14:56 +08:00
end
2016-01-19 07:57:55 +08:00
it " supports liking via email " do
expect { process ( :like ) } . to change ( PostAction , :count )
2014-10-25 22:36:59 +08:00
end
2016-01-19 07:57:55 +08:00
it " ensures posts aren't dated in the future " do
2020-03-11 05:13:17 +08:00
# PostCreator doesn't provide sub-second accuracy for created_at
now = freeze_time Time . zone . now . round
2016-01-19 07:57:55 +08:00
expect { process ( :from_the_future ) } . to change { topic . posts . count }
2020-03-11 05:13:17 +08:00
expect ( topic . posts . last . created_at ) . to eq_time ( now )
2014-10-27 14:58:31 +08:00
end
2018-03-30 20:37:19 +08:00
it " accepts emails with wrong reply key if the system knows about the forwarded email " do
2019-04-08 17:36:39 +08:00
Fabricate ( :user , email : " bob@bar.com " )
2017-11-13 06:44:22 +08:00
Fabricate (
:incoming_email ,
raw : << ~ RAW ,
2017-11-13 22:20:36 +08:00
Return - Path : < discourse @bar . com >
From : Alice < discourse @bar . com >
To : dave @bar . com , reply + 4 f97315cc828096c9cb34c6f1a0d6fe8 @bar . com
CC : carol @bar . com , bob @bar . com
Subject : Hello world
Date : Fri , 15 Jan 2016 00 : 12 : 43 + 0100
Message - ID : < 10 @foo . bar . mail >
Mime - Version : 1 . 0
Content - Type : text / plain ; charset = UTF - 8
Content - Transfer - Encoding : quoted - printable
This post was created by email .
2017-11-13 06:44:22 +08:00
RAW
from_address : " discourse@bar.com " ,
to_addresses : " dave@bar.com;reply+4f97315cc828096c9cb34c6f1a0d6fe8@bar.com " ,
cc_addresses : " carol@bar.com;bob@bar.com " ,
topic : topic ,
post : post ,
user : user ,
)
expect { process ( :reply_user_not_matching_but_known ) } . to change { topic . posts . count }
2017-11-12 00:27:28 +08:00
end
2018-10-16 07:51:57 +08:00
2019-03-15 22:55:11 +08:00
it " re-enables user's PM email notifications when user replies to a private topic " do
2018-10-16 07:51:57 +08:00
topic . update_columns ( category_id : nil , archetype : Archetype . private_message )
topic . allowed_users << user
topic . save
2019-03-15 22:55:11 +08:00
user . user_option . update_columns ( email_messages_level : UserOption . email_level_types [ :never ] )
2018-10-16 07:51:57 +08:00
expect { process ( :reply_user_matching ) } . to change { topic . posts . count }
user . reload
2019-03-15 22:55:11 +08:00
expect ( user . user_option . email_messages_level ) . to eq ( UserOption . email_level_types [ :always ] )
2018-10-16 07:51:57 +08:00
end
2014-10-27 14:58:31 +08:00
end
2019-08-07 18:32:19 +08:00
shared_examples " creates topic with forwarded message as quote " do | destination , address |
it " creates topic with forwarded message as quote " do
expect { process ( :forwarded_email_1 ) } . to change ( Topic , :count )
topic = Topic . last
if destination == :category
expect ( topic . category ) . to eq ( Category . where ( email_in : address ) . first )
else
expect ( topic . archetype ) . to eq ( Archetype . private_message )
expect ( topic . allowed_groups ) . to eq ( Group . where ( incoming_email : address ) )
end
post = Post . last
expect ( post . user . email ) . to eq ( " ba@bar.com " )
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
expect ( post . raw ) . to eq ( << ~ RAW . chomp )
2019-08-07 18:32:19 +08:00
@team , can you have a look at this email below?
[ quote ]
From : Some One & lt ; some @one \ \ . com & gt ;
To : Ba Bar & lt ; ba @bar \ \ . com & gt ;
Date : Mon , 1 Dec 2016 00 : 13 : 37 \ \ + 0100
Subject : Discoursing much?
Hello Ba Bar ,
Discoursing much today?
XoXo
[ / quote]
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
RAW
2019-08-07 18:32:19 +08:00
end
end
2022-07-28 00:14:14 +08:00
describe " new message to a group " do
2019-05-07 11:12:20 +08:00
fab! ( :group ) { Fabricate ( :group , incoming_email : " team@bar.com|meat@bar.com " ) }
2013-06-26 02:05:14 +08:00
2016-01-19 07:57:55 +08:00
it " handles encoded display names " do
expect { process ( :encoded_display_name ) } . to change ( Topic , :count )
2014-08-27 08:08:53 +08:00
2016-01-19 07:57:55 +08:00
topic = Topic . last
2016-02-01 19:16:15 +08:00
expect ( topic . title ) . to eq ( " I need help " )
2016-01-19 07:57:55 +08:00
expect ( topic . private_message? ) . to eq ( true )
expect ( topic . allowed_groups ) . to include ( group )
2013-06-26 02:05:14 +08:00
2016-01-19 07:57:55 +08:00
user = topic . user
expect ( user . staged ) . to eq ( true )
2016-01-20 22:37:34 +08:00
expect ( user . username ) . to eq ( " random.name " )
2016-01-19 07:57:55 +08:00
expect ( user . name ) . to eq ( " Случайная Имя " )
2013-06-26 02:05:14 +08:00
end
2014-08-27 08:08:53 +08:00
2016-02-01 19:16:15 +08:00
it " handles email with no subject " do
expect { process ( :no_subject ) } . to change ( Topic , :count )
2017-01-20 06:01:51 +08:00
expect ( Topic . last . title ) . to eq ( " This topic needs a title " )
2016-02-01 19:16:15 +08:00
end
2016-01-21 06:08:27 +08:00
it " invites everyone in the chain but emails configured as 'incoming' (via reply, group or category) " do
2016-01-19 07:57:55 +08:00
expect { process ( :cc ) } . to change ( Topic , :count )
2017-10-06 22:37:28 +08:00
topic = Topic . last
emails = topic . allowed_users . joins ( :user_emails ) . pluck ( :" user_emails.email " )
expect ( emails ) . to contain_exactly ( " someone@else.com " , " discourse@bar.com " , " wat@bar.com " )
expect ( topic . topic_users . count ) . to eq ( 3 )
2014-03-28 21:57:12 +08:00
end
2018-07-03 19:51:22 +08:00
it " invites users with a secondary email in the chain " do
user1 =
Fabricate (
:user ,
trust_level : SiteSetting . email_in_min_trust ,
user_emails : [
Fabricate . build ( :secondary_email , email : " discourse@bar.com " ) ,
Fabricate . build ( :secondary_email , email : " someone@else.com " ) ,
] ,
)
user2 =
Fabricate (
:user ,
trust_level : SiteSetting . email_in_min_trust ,
user_emails : [
Fabricate . build ( :secondary_email , email : " team@bar.com " ) ,
Fabricate . build ( :secondary_email , email : " wat@bar.com " ) ,
] ,
)
expect { process ( :cc ) } . to change ( Topic , :count )
expect ( Topic . last . allowed_users ) . to contain_exactly ( user1 , user2 )
end
2016-05-17 03:45:34 +08:00
it " cap the number of staged users created per email " do
SiteSetting . maximum_staged_users_per_email = 1
2022-08-18 23:19:20 +08:00
expect { process ( :cc ) } . to change ( Topic , :count ) . by ( 1 ) . and change ( User , :count ) . by ( 1 )
expect ( Topic . last . ordered_posts [ - 1 ] . post_type ) . to eq ( Post . types [ :moderator_action ] )
end
it " cap the number of staged users existing per email " do
Fabricate ( :user , email : " discourse@bar.com " , staged : true ) # from
Fabricate ( :user , email : " someone@else.com " , staged : true ) # to
SiteSetting . maximum_staged_users_per_email = 1
expect { process ( :cc ) } . to change ( Topic , :count ) . and not_change ( User , :count )
2016-05-17 03:45:34 +08:00
expect ( Topic . last . ordered_posts [ - 1 ] . post_type ) . to eq ( Post . types [ :moderator_action ] )
end
2022-08-18 23:18:58 +08:00
it " rejects messages with too many recipients " do
SiteSetting . maximum_recipients_per_new_group_email = 3
expect { process ( :cc ) } . to raise_error ( Email :: Receiver :: TooManyRecipientsError )
end
2022-09-26 07:14:24 +08:00
it " uses the incoming_email message-id as the new post's outbound_message_id " do
expect { process ( :cc ) } . to change ( Topic , :count )
message_id = IncomingEmail . last . message_id
expect ( Topic . last . first_post . outbound_message_id ) . to eq ( message_id )
end
2021-08-03 06:01:17 +08:00
describe " reply-to header " do
before { SiteSetting . block_auto_generated_emails = false }
2021-10-05 17:42:19 +08:00
it " extracts address and uses it for comparison " do
expect { process ( :reply_to_whitespaces ) } . to change ( Topic , :count ) . by ( 1 )
user = User . last
incoming = IncomingEmail . find_by ( message_id : " TXULO4v6YU0TzeL2buFAJNU2MK21c7t4@example.com " )
topic = incoming . topic
expect ( incoming . from_address ) . to eq ( " johndoe@example.com " )
expect ( user . email ) . to eq ( " johndoe@example.com " )
end
it " handles emails where there is a Reply-To address, using that instead of the from address, if X-Original-From is present " do
2021-09-20 14:26:18 +08:00
expect { process ( :reply_to_different_to_from ) } . to change ( Topic , :count ) . by ( 1 )
2021-08-03 06:01:17 +08:00
user = User . last
incoming = IncomingEmail . find_by ( message_id : " 3848c3m98r439c348mc349@test.mailinglist.com " )
topic = incoming . topic
expect ( incoming . from_address ) . to eq ( " arthurmorgan@reddeadtest.com " )
expect ( user . email ) . to eq ( " arthurmorgan@reddeadtest.com " )
end
2021-09-20 14:26:18 +08:00
it " allows for quotes around the display name of the Reply-To address " do
expect { process ( :reply_to_different_to_from_quoted_display_name ) } . to change (
Topic ,
:count ,
) . by ( 1 )
user = User . last
incoming = IncomingEmail . find_by ( message_id : " 3848c3m98r439c348mc349@test.mailinglist.com " )
topic = incoming . topic
expect ( incoming . from_address ) . to eq ( " johnmarston@reddeadtest.com " )
expect ( user . email ) . to eq ( " johnmarston@reddeadtest.com " )
end
2021-08-03 06:01:17 +08:00
it " does not use the reply-to address if an X-Original-From header is not present " do
2021-09-20 14:26:18 +08:00
expect { process ( :reply_to_different_to_from_no_x_original ) } . to change ( Topic , :count ) . by ( 1 )
2021-08-03 06:01:17 +08:00
user = User . last
incoming = IncomingEmail . find_by ( message_id : " 3848c3m98r439c348mc349@test.mailinglist.com " )
topic = incoming . topic
expect ( incoming . from_address ) . to eq ( " westernsupport@test.mailinglist.com " )
expect ( user . email ) . to eq ( " westernsupport@test.mailinglist.com " )
end
it " does not use the reply-to address if the X-Original-From header is different from the reply-to address " do
2021-09-20 14:26:18 +08:00
expect { process ( :reply_to_different_to_from_x_original_different ) } . to change (
Topic ,
:count ,
) . by ( 1 )
2021-08-03 06:01:17 +08:00
user = User . last
incoming = IncomingEmail . find_by ( message_id : " 3848c3m98r439c348mc349@test.mailinglist.com " )
topic = incoming . topic
expect ( incoming . from_address ) . to eq ( " westernsupport@test.mailinglist.com " )
expect ( user . email ) . to eq ( " westernsupport@test.mailinglist.com " )
end
end
2018-08-21 14:00:45 +08:00
describe " when 'find_related_post_with_key' is disabled " do
before { SiteSetting . find_related_post_with_key = false }
2017-08-01 06:03:04 +08:00
2018-08-21 14:00:45 +08:00
it " associates email replies using both 'In-Reply-To' and 'References' headers " do
expect { process ( :email_reply_1 ) } . to change ( Topic , :count ) . by ( 1 ) &
change ( Post , :count ) . by ( 3 )
2016-01-21 05:52:08 +08:00
2018-08-21 14:00:45 +08:00
topic = Topic . last
ordered_posts = topic . ordered_posts
2016-01-21 05:52:08 +08:00
2018-08-21 14:00:45 +08:00
expect ( ordered_posts . first . raw ) . to eq ( " This is email reply **1**. " )
2016-01-21 05:52:08 +08:00
2018-08-21 14:00:45 +08:00
ordered_posts [ 1 .. - 1 ] . each do | post |
expect ( post . action_code ) . to eq ( " invited_user " )
expect ( post . user . email ) . to eq ( " one@foo.com " )
2016-01-21 05:52:08 +08:00
2018-08-21 14:00:45 +08:00
expect ( %w[ two three ] . include? ( post . custom_fields [ " action_code_who " ] ) ) . to eq ( true )
end
2016-01-21 05:52:08 +08:00
2018-08-21 14:00:45 +08:00
expect { process ( :email_reply_2 ) } . to change { topic . posts . count } . by ( 1 )
expect { process ( :email_reply_3 ) } . to change { topic . posts . count } . by ( 1 )
ordered_posts [ 1 .. - 1 ] . each ( & :trash! )
expect { process ( :email_reply_4 ) } . to change { topic . posts . count } . by ( 1 )
end
2021-12-06 08:34:39 +08:00
2022-09-26 07:14:24 +08:00
describe " replying with various message-id formats using In-Reply-To header " do
2021-12-06 08:34:39 +08:00
let! ( :topic ) do
process ( :email_reply_1 )
Topic . last
end
let! ( :post ) { Fabricate ( :post , topic : topic ) }
def process_mail_with_message_id ( message_id )
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
mail_string = << ~ EMAIL
2021-12-06 08:34:39 +08:00
Return - Path : < two @foo . com >
From : Two < two @foo . com >
To : one @foo . com
Subject : RE : Testing email threading
Date : Fri , 15 Jan 2016 00 : 12 : 43 + 0100
Message - ID : < 44 @foo . bar . mail >
In - Reply - To : < #{message_id}>
Mime - Version : 1 . 0
Content - Type : text / plain
Content - Transfer - Encoding : 7 bit
This is email reply testing with Message - ID formats .
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
EMAIL
2021-12-06 08:34:39 +08:00
Email :: Receiver . new ( mail_string ) . process!
end
it " posts a reply using a message-id in the format topic/TOPIC_ID/POST_ID@HOST " do
expect {
process_mail_with_message_id ( " topic/ #{ topic . id } / #{ post . id } @test.localhost " )
} . to change { Post . count } . by ( 1 )
expect ( topic . reload . posts . last . raw ) . to include (
" This is email reply testing with Message-ID formats " ,
)
end
it " posts a reply using a message-id in the format topic/TOPIC_ID@HOST " do
expect { process_mail_with_message_id ( " topic/ #{ topic . id } @test.localhost " ) } . to change {
Post . count
} . by ( 1 )
expect ( topic . reload . posts . last . raw ) . to include (
" This is email reply testing with Message-ID formats " ,
)
end
it " posts a reply using a message-id in the format topic/TOPIC_ID/POST_ID.RANDOM_SUFFIX@HOST " do
expect {
process_mail_with_message_id ( " topic/ #{ topic . id } / #{ post . id } .rjc3yr79834y@test.localhost " )
} . to change { Post . count } . by ( 1 )
expect ( topic . reload . posts . last . raw ) . to include (
" This is email reply testing with Message-ID formats " ,
)
end
it " posts a reply using a message-id in the format topic/TOPIC_ID.RANDOM_SUFFIX@HOST " do
expect {
process_mail_with_message_id (
" topic/ #{ topic . id } / #{ post . id } .x3487nxy877843x@test.localhost " ,
)
} . to change { Post . count } . by ( 1 )
expect ( topic . reload . posts . last . raw ) . to include (
" This is email reply testing with Message-ID formats " ,
)
end
2022-09-26 07:14:24 +08:00
it " posts a reply using a message-id in the format discourse/post/POST_ID@HOST " do
expect {
process_mail_with_message_id ( " discourse/post/ #{ post . id } @test.localhost " )
} . to change { Post . count } . by ( 1 )
expect ( topic . reload . posts . last . raw ) . to include (
" This is email reply testing with Message-ID formats " ,
)
end
2021-12-06 08:34:39 +08:00
end
2016-01-21 05:52:08 +08:00
end
2016-03-01 05:39:24 +08:00
it " supports any kind of attachments when 'allow_all_attachments_for_group_messages' is enabled " do
SiteSetting . allow_all_attachments_for_group_messages = true
expect { process ( :attached_rb_file ) } . to change ( Topic , :count )
2019-06-11 14:46:37 +08:00
post = Topic . last . first_post
upload = post . uploads . first
expect ( post . raw ) . to include (
" [ #{ upload . original_filename } |attachment]( #{ upload . short_url } ) ( #{ upload . filesize } Bytes) " ,
)
2016-03-01 05:39:24 +08:00
end
2019-03-15 22:55:11 +08:00
it " reenables user's PM email notifications when user emails new topic to group " do
2018-10-02 02:01:24 +08:00
user = Fabricate ( :user , email : " existing@bar.com " )
2019-03-15 22:55:11 +08:00
user . user_option . update_columns ( email_messages_level : UserOption . email_level_types [ :never ] )
2018-10-02 02:01:24 +08:00
expect { process ( :group_existing_user ) } . to change ( Topic , :count )
user . reload
2019-03-15 22:55:11 +08:00
expect ( user . user_option . email_messages_level ) . to eq ( UserOption . email_level_types [ :always ] )
2018-10-02 02:01:24 +08:00
end
2019-08-07 18:32:19 +08:00
context " with forwarded emails behaviour set to create replies " do
2019-04-08 17:36:39 +08:00
before do
Fabricate ( :group , incoming_email : " some_group@bar.com " )
2019-08-07 18:32:19 +08:00
SiteSetting . forwarded_emails_behaviour = " create_replies "
2019-04-08 17:36:39 +08:00
end
2016-12-02 01:34:47 +08:00
2017-01-10 05:59:30 +08:00
it " handles forwarded emails " do
expect { process ( :forwarded_email_1 ) } . to change ( Topic , :count )
2016-12-02 01:34:47 +08:00
2017-01-10 05:59:30 +08:00
forwarded_post , last_post = * Post . last ( 2 )
2016-12-02 01:34:47 +08:00
2017-01-10 05:59:30 +08:00
expect ( forwarded_post . user . email ) . to eq ( " some@one.com " )
expect ( last_post . user . email ) . to eq ( " ba@bar.com " )
2016-12-02 01:43:56 +08:00
2017-01-10 05:59:30 +08:00
expect ( forwarded_post . raw ) . to match ( / XoXo / )
expect ( last_post . raw ) . to match ( / can you have a look at this email below / )
expect ( last_post . post_type ) . to eq ( Post . types [ :regular ] )
end
it " handles weirdly forwarded emails " do
group . add ( Fabricate ( :user , email : " ba@bar.com " ) )
group . save
2016-12-02 01:34:47 +08:00
2019-08-07 18:32:19 +08:00
SiteSetting . forwarded_emails_behaviour = " create_replies "
2017-01-10 05:59:30 +08:00
expect { process ( :forwarded_email_2 ) } . to change ( Topic , :count )
2016-12-02 01:43:56 +08:00
2017-01-10 05:59:30 +08:00
forwarded_post , last_post = * Post . last ( 2 )
2016-12-02 01:34:47 +08:00
2017-01-10 05:59:30 +08:00
expect ( forwarded_post . user . email ) . to eq ( " some@one.com " )
expect ( last_post . user . email ) . to eq ( " ba@bar.com " )
2016-12-02 01:34:47 +08:00
2017-01-10 05:59:30 +08:00
expect ( forwarded_post . raw ) . to match ( / XoXo / )
expect ( last_post . raw ) . to match ( / can you have a look at this email below / )
2016-12-02 01:34:47 +08:00
2017-01-10 05:59:30 +08:00
expect ( last_post . post_type ) . to eq ( Post . types [ :whisper ] )
end
# Who thought this was a good idea?!
it " doesn't blow up with localized email headers " do
expect { process ( :forwarded_email_3 ) } . to change ( Topic , :count )
end
2016-12-02 01:43:56 +08:00
2020-02-11 22:48:58 +08:00
it " adds a small action post to explain who forwarded the email when the sender didn't write anything " do
expect { process ( :forwarded_email_4 ) } . to change ( Topic , :count )
forwarded_post , last_post = * Post . last ( 2 )
expect ( forwarded_post . user . email ) . to eq ( " some@one.com " )
expect ( forwarded_post . raw ) . to match ( / XoXo / )
expect ( last_post . user . email ) . to eq ( " ba@bar.com " )
expect ( last_post . post_type ) . to eq ( Post . types [ :small_action ] )
expect ( last_post . action_code ) . to eq ( " forwarded " )
end
2016-12-02 01:34:47 +08:00
end
2019-08-07 18:32:19 +08:00
context " with forwarded emails behaviour set to quote " do
before { SiteSetting . forwarded_emails_behaviour = " quote " }
include_examples " creates topic with forwarded message as quote " ,
:group ,
" team@bar.com|meat@bar.com "
end
2021-06-03 12:47:32 +08:00
context " when a reply is sent to a group's email_username " do
let! ( :topic ) do
group . update ( email_username : " team@somesmtpaddress.com " )
process ( :email_reply_1 )
Topic . last
end
it " does not invite the group email_username as a staged user " do
process ( :email_reply_to_group_email_username )
expect ( User . find_by_email ( " team@somesmtpaddress.com " ) ) . to eq ( nil )
end
it " creates the reply when the sender and referenced messsage id are known " do
2022-07-19 22:03:03 +08:00
expect { process ( :email_reply_to_group_email_username ) } . to change { topic . posts . count } . by (
2023-01-09 19:18:21 +08:00
1 ,
2022-07-19 22:03:03 +08:00
) . and not_change { Topic . count }
2021-06-03 12:47:32 +08:00
end
end
2021-08-24 06:57:28 +08:00
context " when a group forwards an email to its inbox " do
2021-09-06 13:02:13 +08:00
before do
2021-08-24 06:57:28 +08:00
group . update! (
email_username : " team@somesmtpaddress.com " ,
incoming_email : " team@somesmtpaddress.com|support+team@bar.com " ,
smtp_server : " smtp.test.com " ,
smtp_port : 587 ,
smtp_ssl : true ,
smtp_enabled : true ,
)
end
it " does not use the team's address as the from_address; it uses the original sender address " do
2021-09-06 13:02:13 +08:00
process ( :forwarded_by_group_to_inbox )
topic = Topic . last
2021-08-24 06:57:28 +08:00
expect ( topic . incoming_email . first . to_addresses ) . to include ( " support+team@bar.com " )
expect ( topic . incoming_email . first . from_address ) . to eq ( " fred@bedrock.com " )
end
2021-09-06 13:02:13 +08:00
context " with forwarded emails behaviour set to create replies " do
before { SiteSetting . forwarded_emails_behaviour = " create_replies " }
it " does not use the team's address as the from_address; it uses the original sender address " do
process ( :forwarded_by_group_to_inbox )
topic = Topic . last
expect ( topic . incoming_email . first . to_addresses ) . to include ( " support+team@bar.com " )
expect ( topic . incoming_email . first . from_address ) . to eq ( " fred@bedrock.com " )
end
it " does not say the email was forwarded by the original sender, it says the email is forwarded by the group " do
2021-09-07 06:46:28 +08:00
expect { process ( :forwarded_by_group_to_inbox ) } . to change {
User . where ( staged : true ) . count
} . by ( 4 )
2021-09-06 13:02:13 +08:00
topic = Topic . last
forwarded_small_post = topic . ordered_posts . last
expect ( forwarded_small_post . action_code ) . to eq ( " forwarded " )
expect ( forwarded_small_post . user ) . to eq ( User . find_by_email ( " team@somesmtpaddress.com " ) )
end
2021-09-07 06:46:28 +08:00
it " keeps track of the cc addresses of the forwarded email and creates staged users for them " do
expect { process ( :forwarded_by_group_to_inbox ) } . to change {
User . where ( staged : true ) . count
} . by ( 4 )
topic = Topic . last
cc_user1 = User . find_by_email ( " terry@ccland.com " )
cc_user2 = User . find_by_email ( " don@ccland.com " )
fred_user = User . find_by_email ( " fred@bedrock.com " )
team_user = User . find_by_email ( " team@somesmtpaddress.com " )
expect ( topic . incoming_email . first . cc_addresses ) . to eq ( " terry@ccland.com;don@ccland.com " )
expect ( topic . topic_allowed_users . pluck ( :user_id ) ) . to match_array (
[ fred_user . id , team_user . id , cc_user1 . id , cc_user2 . id ] ,
)
end
it " keeps track of the cc addresses of the final forwarded email as well " do
expect { process ( :forwarded_by_group_to_inbox_double_cc ) } . to change {
User . where ( staged : true ) . count
} . by ( 5 )
topic = Topic . last
cc_user1 = User . find_by_email ( " terry@ccland.com " )
cc_user2 = User . find_by_email ( " don@ccland.com " )
fred_user = User . find_by_email ( " fred@bedrock.com " )
team_user = User . find_by_email ( " team@somesmtpaddress.com " )
someother_user = User . find_by_email ( " someotherparty@test.com " )
expect ( topic . incoming_email . first . cc_addresses ) . to eq (
" someotherparty@test.com;terry@ccland.com;don@ccland.com " ,
)
expect ( topic . topic_allowed_users . pluck ( :user_id ) ) . to match_array (
[ fred_user . id , team_user . id , someother_user . id , cc_user1 . id , cc_user2 . id ] ,
)
end
2021-09-06 13:02:13 +08:00
context " when staged user for the team email already exists " do
let! ( :staged_team_user ) do
User . create! (
email : " team@somesmtpaddress.com " ,
username : UserNameSuggester . suggest ( " team@somesmtpaddress.com " ) ,
name : " team teamson " ,
staged : true ,
)
end
it " uses that and does not create another staged user " do
2021-09-07 06:46:28 +08:00
expect { process ( :forwarded_by_group_to_inbox ) } . to change {
User . where ( staged : true ) . count
} . by ( 3 )
2021-09-06 13:02:13 +08:00
topic = Topic . last
forwarded_small_post = topic . ordered_posts . last
expect ( forwarded_small_post . action_code ) . to eq ( " forwarded " )
expect ( forwarded_small_post . user ) . to eq ( staged_team_user )
end
end
end
2021-08-24 06:57:28 +08:00
end
2022-07-28 00:14:14 +08:00
context " when emailing a group by email_username and following reply flow " do
2021-06-21 09:45:00 +08:00
let! ( :original_inbound_email_topic ) do
group . update! (
email_username : " team@somesmtpaddress.com " ,
2021-08-24 06:57:28 +08:00
incoming_email : " team@somesmtpaddress.com|suppor+team@bar.com " ,
2021-06-21 09:45:00 +08:00
smtp_server : " smtp.test.com " ,
smtp_port : 587 ,
smtp_ssl : true ,
smtp_enabled : true ,
)
2021-06-10 13:28:50 +08:00
process ( :email_to_group_email_username_1 )
Topic . last
end
fab! ( :user_in_group ) do
u = Fabricate ( :user )
Fabricate ( :group_user , user : u , group : group )
u
end
before do
NotificationEmailer . enable
2021-06-21 09:45:00 +08:00
SiteSetting . disallow_reply_by_email_after_days = 10_000
2021-06-10 13:28:50 +08:00
Jobs . run_immediately!
end
def reply_as_group_user
group_post =
PostCreator . create (
user_in_group ,
raw : " Thanks for your request. Please try to restart. " ,
2021-06-21 09:45:00 +08:00
topic_id : original_inbound_email_topic . id ,
2021-06-10 13:28:50 +08:00
)
email_log = EmailLog . last
[ email_log , group_post ]
end
it " the inbound processed email creates an incoming email and topic record correctly, and adds the group to the topic " do
2021-06-21 09:45:00 +08:00
incoming = IncomingEmail . find_by ( topic : original_inbound_email_topic )
2021-06-10 13:28:50 +08:00
user = User . find_by_email ( " two@foo.com " )
2021-06-21 09:45:00 +08:00
expect ( original_inbound_email_topic . topic_allowed_users . first . user_id ) . to eq ( user . id )
expect ( original_inbound_email_topic . topic_allowed_groups . first . group_id ) . to eq ( group . id )
2021-06-10 13:28:50 +08:00
expect ( incoming . to_addresses ) . to eq ( " team@somesmtpaddress.com " )
expect ( incoming . from_address ) . to eq ( " two@foo.com " )
expect ( incoming . message_id ) . to eq ( " u4w8c9r4y984yh98r3h69873@foo.bar.mail " )
end
it " creates an EmailLog when someone from the group replies, and does not create an IncomingEmail record for the reply " do
email_log , group_post = reply_as_group_user
2022-09-26 07:14:24 +08:00
expect ( email_log . message_id ) . to eq ( " discourse/post/ #{ group_post . id } @test.localhost " )
2021-06-10 13:28:50 +08:00
expect ( email_log . to_address ) . to eq ( " two@foo.com " )
expect ( email_log . email_type ) . to eq ( " user_private_message " )
expect ( email_log . post_id ) . to eq ( group_post . id )
expect ( IncomingEmail . exists? ( post_id : group_post . id ) ) . to eq ( false )
end
it " processes a reply from the OP user to the group SMTP username, linking the reply_to_post_number correctly by
matching in_reply_to to the email log " do
email_log , group_post = reply_as_group_user
reply_email = email ( :email_to_group_email_username_2 )
reply_email . gsub! ( " MESSAGE_ID_REPLY_TO " , email_log . message_id )
expect do Email :: Receiver . new ( reply_email ) . process! end . to not_change {
2022-07-19 22:03:03 +08:00
Topic . count
} . and change { Post . count } . by ( 1 )
2021-06-10 13:28:50 +08:00
reply_post = Post . last
expect ( reply_post . reply_to_user ) . to eq ( user_in_group )
expect ( reply_post . reply_to_post_number ) . to eq ( group_post . post_number )
end
it " processes the reply from the user as a brand new topic if they have replied from a different address (e.g. auto forward) and allow_unknown_sender_topic_replies is disabled " do
email_log , group_post = reply_as_group_user
reply_email = email ( :email_to_group_email_username_2_as_unknown_sender )
reply_email . gsub! ( " MESSAGE_ID_REPLY_TO " , email_log . message_id )
expect do Email :: Receiver . new ( reply_email ) . process! end . to change { Topic . count } . by (
2023-01-09 19:18:21 +08:00
1 ,
2021-06-10 13:28:50 +08:00
) . and change { Post . count } . by ( 1 )
reply_post = Post . last
2021-06-21 09:45:00 +08:00
expect ( reply_post . topic_id ) . not_to eq ( original_inbound_email_topic . id )
2021-06-10 13:28:50 +08:00
end
it " processes the reply from the user as a reply if they have replied from a different address (e.g. auto forward) and allow_unknown_sender_topic_replies is enabled " do
group . update! ( allow_unknown_sender_topic_replies : true )
email_log , group_post = reply_as_group_user
reply_email = email ( :email_to_group_email_username_2_as_unknown_sender )
reply_email . gsub! ( " MESSAGE_ID_REPLY_TO " , email_log . message_id )
expect do Email :: Receiver . new ( reply_email ) . process! end . to not_change {
2022-07-19 22:03:03 +08:00
Topic . count
} . and change { Post . count } . by ( 1 )
2021-06-10 13:28:50 +08:00
reply_post = Post . last
2021-06-21 09:45:00 +08:00
expect ( reply_post . topic_id ) . to eq ( original_inbound_email_topic . id )
end
it " creates a new topic with a reference back to the original if replying to a too old topic " do
SiteSetting . disallow_reply_by_email_after_days = 2
email_log , group_post = reply_as_group_user
group_post . update ( created_at : 10 . days . ago )
group_post . topic . update ( created_at : 10 . days . ago )
reply_email = email ( :email_to_group_email_username_2 )
reply_email . gsub! ( " MESSAGE_ID_REPLY_TO " , email_log . message_id )
expect do Email :: Receiver . new ( reply_email ) . process! end . to change { Topic . count } . by (
2023-01-09 19:18:21 +08:00
1 ,
2021-06-21 09:45:00 +08:00
) . and change { Post . count } . by ( 1 )
reply_post = Post . last
new_topic = Topic . last
expect ( reply_post . topic ) . to eq ( new_topic )
expect ( reply_post . raw ) . to include (
I18n . t (
" emails.incoming.continuing_old_discussion " ,
url : group_post . topic . url ,
title : group_post . topic . title ,
count : SiteSetting . disallow_reply_by_email_after_days ,
) ,
)
2021-06-10 13:28:50 +08:00
end
end
2018-03-30 20:37:19 +08:00
context " when message sent to a group has no key and find_related_post_with_key is enabled " do
let! ( :topic ) do
process ( :email_reply_1 )
Topic . last
end
it " creates a reply when the sender and referenced message id are known " do
2022-07-19 22:03:03 +08:00
expect { process ( :email_reply_2 ) } . to change { topic . posts . count } . by ( 1 ) . and not_change {
Topic . count
}
2018-03-30 20:37:19 +08:00
end
2021-01-29 07:59:10 +08:00
it " creates a new topic when the sender is not known and the group does not allow unknown senders to reply to topics " do
2018-03-30 20:37:19 +08:00
IncomingEmail . where ( message_id : " 34@foo.bar.mail " ) . update ( cc_addresses : " three@foo.com " )
2021-01-29 07:59:10 +08:00
group . update ( allow_unknown_sender_topic_replies : false )
2022-07-19 22:03:03 +08:00
expect { process ( :email_reply_2 ) } . to not_change { topic . posts . count } . and change {
Topic . count
} . by ( 1 )
2018-03-30 20:37:19 +08:00
end
it " creates a new topic when the referenced message id is not known " do
IncomingEmail . where ( message_id : " 34@foo.bar.mail " ) . update ( message_id : " 99@foo.bar.mail " )
2022-07-19 22:03:03 +08:00
expect { process ( :email_reply_2 ) } . to not_change { topic . posts . count } . and change {
Topic . count
} . by ( 1 )
2018-03-30 20:37:19 +08:00
end
2021-01-29 07:59:10 +08:00
it " includes the sender on the topic when the message id is known, the sender is not known, and the group allows unknown senders to reply to topics " do
IncomingEmail . where ( message_id : " 34@foo.bar.mail " ) . update ( cc_addresses : " three@foo.com " )
group . update ( allow_unknown_sender_topic_replies : true )
2022-07-19 22:03:03 +08:00
expect { process ( :email_reply_2 ) } . to change { topic . posts . count } . by ( 1 ) . and not_change {
Topic . count
}
2021-01-29 07:59:10 +08:00
end
context " when the sender is not in the topic allowed users " do
before do
user = User . find_by_email ( " two@foo.com " )
topic . topic_allowed_users . find_by ( user : user ) . destroy
end
it " adds them to the topic at the same time " do
IncomingEmail . where ( message_id : " 34@foo.bar.mail " ) . update ( cc_addresses : " three@foo.com " )
group . update ( allow_unknown_sender_topic_replies : true )
2022-07-19 22:03:03 +08:00
expect { process ( :email_reply_2 ) } . to change { topic . posts . count } . by ( 1 ) . and not_change {
Topic . count
}
2021-01-29 07:59:10 +08:00
end
end
2018-03-30 20:37:19 +08:00
end
2013-06-11 04:46:08 +08:00
end
2022-07-28 00:14:14 +08:00
describe " new topic in a category " do
2019-05-07 11:12:20 +08:00
fab! ( :category ) do
Fabricate (
:category ,
email_in : " category@bar.com|category@foo.com " ,
email_in_allow_strangers : false ,
)
2023-01-09 19:18:21 +08:00
end
2015-12-16 07:43:05 +08:00
2016-01-19 07:57:55 +08:00
it " raises a StrangersNotAllowedError when 'email_in_allow_strangers' is disabled " do
2016-02-23 02:57:53 +08:00
expect { process ( :new_user ) } . to raise_error ( Email :: Receiver :: StrangersNotAllowedError )
2014-02-27 20:44:21 +08:00
end
2016-01-19 07:57:55 +08:00
it " raises an InsufficientTrustLevelError when user's trust level isn't enough " do
2016-02-23 02:57:53 +08:00
Fabricate ( :user , email : " existing@bar.com " , trust_level : 3 )
2016-01-19 07:57:55 +08:00
SiteSetting . email_in_min_trust = 4
2016-02-23 02:57:53 +08:00
expect { process ( :existing_user ) } . to raise_error (
Email :: Receiver :: InsufficientTrustLevelError ,
)
2014-02-25 00:36:53 +08:00
end
2016-02-23 02:57:53 +08:00
it " works " do
2021-12-10 04:45:07 +08:00
handler_calls = 0
handler =
proc do | topic |
2023-01-27 09:27:15 +08:00
expect ( topic . incoming_email_addresses ) . to contain_exactly (
" discourse@bar.com " ,
" category@foo.com " ,
)
2021-12-10 04:45:07 +08:00
handler_calls += 1
2023-01-09 19:18:21 +08:00
end
2021-12-10 04:45:07 +08:00
DiscourseEvent . on ( :topic_created , & handler )
2016-02-23 02:57:53 +08:00
user =
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
2016-01-19 07:57:55 +08:00
group = Fabricate ( :group )
2015-04-10 17:29:45 +08:00
2016-01-19 07:57:55 +08:00
group . add ( user )
group . save
2015-04-10 17:29:45 +08:00
2016-02-23 02:57:53 +08:00
category . set_permissions ( group = > :create_post )
2019-06-04 16:40:10 +08:00
category . save!
2015-04-10 17:29:45 +08:00
2016-02-23 02:57:53 +08:00
# raises an InvalidAccess when the user doesn't have the privileges to create a topic
expect { process ( :existing_user ) } . to raise_error ( Discourse :: InvalidAccess )
2014-02-27 23:36:33 +08:00
2016-02-23 02:57:53 +08:00
category . update_columns ( email_in_allow_strangers : true )
# allows new user to create a topic
expect { process ( :new_user ) } . to change ( Topic , :count )
2021-12-10 04:45:07 +08:00
DiscourseEvent . off ( :topic_created , & handler )
expect ( handler_calls ) . to eq ( 1 )
2015-12-11 06:49:16 +08:00
end
2018-07-05 17:07:46 +08:00
it " creates visible topic for ham " do
SiteSetting . email_in_spam_header = " none "
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
expect { process ( :existing_user ) } . to change { Topic . count } . by ( 1 ) # Topic created
topic = Topic . last
expect ( topic . visible ) . to eq ( true )
post = Post . last
expect ( post . hidden ) . to eq ( false )
expect ( post . hidden_at ) . to eq ( nil )
expect ( post . hidden_reason_id ) . to eq ( nil )
end
it " creates hidden topic for X-Spam-Flag " do
SiteSetting . email_in_spam_header = " X-Spam-Flag "
2020-01-22 00:12:00 +08:00
user =
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
expect { process ( :spam_x_spam_flag ) } . to change { ReviewableQueuedPost . count } . by ( 1 )
expect ( user . reload . silenced? ) . to be ( true )
2018-07-05 17:07:46 +08:00
end
it " creates hidden topic for X-Spam-Status " do
SiteSetting . email_in_spam_header = " X-Spam-Status "
2020-01-22 00:12:00 +08:00
user =
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
expect { process ( :spam_x_spam_status ) } . to change { ReviewableQueuedPost . count } . by ( 1 )
expect ( user . reload . silenced? ) . to be ( true )
2018-07-05 17:07:46 +08:00
end
2019-10-29 00:46:53 +08:00
it " creates hidden topic for X-SES-Spam-Verdict " do
SiteSetting . email_in_spam_header = " X-SES-Spam-Verdict "
2020-01-22 00:12:00 +08:00
user =
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
expect { process ( :spam_x_ses_spam_verdict ) } . to change { ReviewableQueuedPost . count } . by ( 1 )
expect ( user . reload . silenced? ) . to be ( true )
2019-10-29 00:46:53 +08:00
end
2019-11-26 22:55:22 +08:00
it " creates hidden topic for failed Authentication-Results header " do
2020-01-22 00:12:00 +08:00
SiteSetting . email_in_authserv_id = " example.com "
2019-11-26 22:55:22 +08:00
2020-01-22 00:12:00 +08:00
user =
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
expect { process ( :dmarc_fail ) } . to change { ReviewableQueuedPost . count } . by ( 1 )
expect ( user . reload . silenced? ) . to be ( false )
2019-11-26 22:55:22 +08:00
end
2017-06-29 12:03:14 +08:00
it " adds the 'elided' part of the original message when always_show_trimmed_content is enabled " do
SiteSetting . always_show_trimmed_content = true
2017-07-21 04:01:16 +08:00
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
2017-06-29 12:03:14 +08:00
expect { process ( :forwarded_email_to_category ) } . to change { Topic . count } . by ( 1 ) # Topic created
new_post , = Post . last
expect ( new_post . raw ) . to include (
" Hi everyone, can you have a look at the email below? " ,
" <summary title='Show trimmed content'>& # 183;& # 183;& # 183;</summary> " ,
" Discoursing much today? " ,
)
end
2016-04-12 00:20:26 +08:00
it " works when approving is enabled " do
SiteSetting . approve_unless_trust_level = 4
Fabricate ( :user , email : " tl3@bar.com " , trust_level : TrustLevel [ 3 ] )
Fabricate ( :user , email : " tl4@bar.com " , trust_level : TrustLevel [ 4 ] )
category . set_permissions ( Group [ :trust_level_4 ] = > :full )
2019-06-04 16:40:10 +08:00
category . save!
2016-04-12 00:20:26 +08:00
Group . refresh_automatic_group! ( :trust_level_4 )
2018-11-10 01:24:28 +08:00
expect { process ( :tl3_user ) } . to raise_error ( Email :: Receiver :: InvalidPost )
2016-04-12 00:20:26 +08:00
expect { process ( :tl4_user ) } . to change ( Topic , :count )
end
2017-11-12 08:43:18 +08:00
it " ignores by case-insensitive title " do
2016-05-19 05:07:01 +08:00
SiteSetting . ignore_by_title = " foo "
expect { process ( :ignored ) } . to_not change ( Topic , :count )
end
2018-07-03 19:51:22 +08:00
it " associates email from a secondary address with user " do
user =
Fabricate (
:user ,
trust_level : SiteSetting . email_in_min_trust ,
user_emails : [ Fabricate . build ( :secondary_email , email : " existing@bar.com " ) ] ,
)
expect { process ( :existing_user ) } . to change ( Topic , :count ) . by ( 1 )
topic = Topic . last
expect ( topic . posts . last . raw ) . to eq ( " Hey, this is a topic from an existing user ;) " )
expect ( topic . user ) . to eq ( user )
end
2015-12-11 06:49:16 +08:00
end
2022-07-28 00:14:14 +08:00
describe " new topic in a category that allows strangers " do
2019-05-07 11:12:20 +08:00
fab! ( :category ) do
Fabricate (
:category ,
email_in : " category@bar.com|category@foo.com " ,
email_in_allow_strangers : true ,
)
2023-01-09 19:18:21 +08:00
end
2016-06-30 20:21:47 +08:00
it " lets an email in from a stranger " do
expect { process ( :new_user ) } . to change ( Topic , :count )
end
it " lets an email in from a high-TL user " do
Fabricate ( :user , email : " tl4@bar.com " , trust_level : TrustLevel [ 4 ] )
expect { process ( :tl4_user ) } . to change ( Topic , :count )
end
it " fails on email from a low-TL user " do
SiteSetting . email_in_min_trust = 4
Fabricate ( :user , email : " tl3@bar.com " , trust_level : TrustLevel [ 3 ] )
expect { process ( :tl3_user ) } . to raise_error ( Email :: Receiver :: InsufficientTrustLevelError )
end
end
2022-07-27 18:21:10 +08:00
describe " # reply_by_email_address_regex " do
2017-05-23 05:35:41 +08:00
before do
SiteSetting . reply_by_email_address = nil
SiteSetting . alternative_reply_by_email_addresses = nil
end
2021-05-21 09:43:47 +08:00
it " it matches nothing if there is not reply_by_email_address " do
2018-05-23 16:04:45 +08:00
expect ( Email :: Receiver . reply_by_email_address_regex ) . to eq ( / $a / )
2017-05-23 05:35:41 +08:00
end
it " uses 'reply_by_email_address' site setting " do
SiteSetting . reply_by_email_address = " foo+%{reply_key}@bar.com "
2018-05-23 16:04:45 +08:00
expect ( Email :: Receiver . reply_by_email_address_regex ) . to eq ( / foo \ +?( \ h{32})?@bar \ .com / )
2017-05-23 05:35:41 +08:00
end
it " uses 'alternative_reply_by_email_addresses' site setting " do
SiteSetting . alternative_reply_by_email_addresses = " alt.foo+%{reply_key}@bar.com "
2018-05-23 16:04:45 +08:00
expect ( Email :: Receiver . reply_by_email_address_regex ) . to eq ( / alt \ .foo \ +?( \ h{32})?@bar \ .com / )
2017-05-23 05:35:41 +08:00
end
it " combines both 'reply_by_email' settings " do
SiteSetting . reply_by_email_address = " foo+%{reply_key}@bar.com "
SiteSetting . alternative_reply_by_email_addresses = " alt.foo+%{reply_key}@bar.com "
2018-05-23 16:04:45 +08:00
expect ( Email :: Receiver . reply_by_email_address_regex ) . to eq (
/ foo \ +?( \ h{32})?@bar \ .com|alt \ .foo \ +?( \ h{32})?@bar \ .com / ,
)
2017-05-23 05:35:41 +08:00
end
end
2022-07-28 00:14:14 +08:00
describe " check_address " do
2017-06-09 02:28:48 +08:00
before { SiteSetting . reply_by_email_address = " foo+%{reply_key}@bar.com " }
it " returns nil when the key is invalid " do
expect ( Email :: Receiver . check_address ( " fake@fake.com " ) ) . to be_nil
expect (
Email :: Receiver . check_address ( " foo+4f97315cc828096c9cb34c6f1a0d6fe8@bar.com " ) ,
) . to be_nil
end
context " with a valid reply " do
it " returns the destination when the key is valid " do
2018-07-18 16:28:44 +08:00
post_reply_key = Fabricate ( :post_reply_key , reply_key : " 4f97315cc828096c9cb34c6f1a0d6fe8 " )
2017-06-09 02:28:48 +08:00
dest = Email :: Receiver . check_address ( " foo+4f97315cc828096c9cb34c6f1a0d6fe8@bar.com " )
2018-07-18 16:28:44 +08:00
2020-07-10 17:05:55 +08:00
expect ( dest ) . to eq ( post_reply_key )
2017-06-09 02:28:48 +08:00
end
end
end
2022-07-28 00:14:14 +08:00
describe " staged users " do
2017-10-03 16:13:19 +08:00
before { SiteSetting . enable_staged_users = true }
2019-04-08 17:36:39 +08:00
shared_examples " does not create staged users " do | email_name , expected_exception |
2017-10-03 16:13:19 +08:00
it " does not create staged users " do
2019-04-08 17:36:39 +08:00
staged_user_count = User . where ( staged : true ) . count
User . expects ( :create ) . never
User . expects ( :create! ) . never
2019-05-10 05:47:32 +08:00
if expected_exception
expect { process ( email_name ) } . to raise_error ( expected_exception )
else
process ( email_name )
end
2019-04-08 17:36:39 +08:00
expect ( User . where ( staged : true ) . count ) . to eq ( staged_user_count )
end
end
shared_examples " cleans up staged users " do | email_name , expected_exception |
it " cleans up staged users " do
2017-10-03 16:13:19 +08:00
staged_user_count = User . where ( staged : true ) . count
2017-10-03 23:28:41 +08:00
expect { process ( email_name ) } . to raise_error ( expected_exception )
2017-10-03 16:13:19 +08:00
expect ( User . where ( staged : true ) . count ) . to eq ( staged_user_count )
end
end
context " when email address is screened " do
before { ScreenedEmail . expects ( :should_block? ) . with ( " screened@mail.com " ) . returns ( true ) }
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " ,
:screened_email ,
Email :: Receiver :: ScreenedEmailError
2017-10-03 16:13:19 +08:00
end
context " when the mail is auto generated " do
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " ,
:auto_generated_header ,
Email :: Receiver :: AutoGeneratedEmailError
2017-10-03 16:13:19 +08:00
end
context " when email is a bounced email " do
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " ,
:bounced_email ,
Email :: Receiver :: BouncedEmailError
2017-10-03 16:13:19 +08:00
end
context " when the body is blank " do
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " ,
:no_body ,
Email :: Receiver :: NoBodyDetectedError
2017-10-03 16:13:19 +08:00
end
context " when unsubscribe via email is not allowed " do
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " ,
:unsubscribe_new_user ,
Email :: Receiver :: UnsubscribeNotAllowed
2017-10-03 16:13:19 +08:00
end
2017-10-03 17:23:18 +08:00
2020-07-27 08:23:54 +08:00
context " when From email address is not on allowlist " do
2017-10-03 17:23:18 +08:00
before do
2020-07-27 08:23:54 +08:00
SiteSetting . allowed_email_domains = " example.com|bar.com "
2019-04-08 17:36:39 +08:00
Fabricate ( :group , incoming_email : " some_group@bar.com " )
2017-10-03 17:23:18 +08:00
end
2020-07-27 08:23:54 +08:00
include_examples " does not create staged users " ,
:blocklist_allowlist_email ,
Email :: Receiver :: EmailNotAllowed
2017-10-03 17:23:18 +08:00
end
2020-07-27 08:23:54 +08:00
context " when From email address is on blocklist " do
2017-10-03 17:23:18 +08:00
before do
2020-07-27 08:23:54 +08:00
SiteSetting . blocked_email_domains = " email.com|mail.com "
2019-04-08 17:36:39 +08:00
Fabricate ( :group , incoming_email : " some_group@bar.com " )
2017-10-03 17:23:18 +08:00
end
2020-07-27 08:23:54 +08:00
include_examples " does not create staged users " ,
:blocklist_allowlist_email ,
Email :: Receiver :: EmailNotAllowed
2017-10-03 23:28:41 +08:00
end
2022-07-28 00:14:14 +08:00
context " with blocklist and allowlist for To and Cc " do
2018-01-10 23:50:27 +08:00
before { Fabricate ( :group , incoming_email : " some_group@bar.com " ) }
2020-07-27 08:23:54 +08:00
it " does not create staged users for email addresses not on allowlist " do
SiteSetting . allowed_email_domains = " mail.com|example.com "
process ( :blocklist_allowlist_email )
2018-01-10 23:50:27 +08:00
expect ( User . find_by_email ( " alice@foo.com " ) ) . to be_nil
expect ( User . find_by_email ( " bob@foo.com " ) ) . to be_nil
expect ( User . find_by_email ( " carol@example.com " ) ) . to be_present
end
2020-07-27 08:23:54 +08:00
it " does not create staged users for email addresses on blocklist " do
SiteSetting . blocked_email_domains = " email.com|foo.com "
process ( :blocklist_allowlist_email )
2018-01-10 23:50:27 +08:00
expect ( User . find_by_email ( " alice@foo.com " ) ) . to be_nil
expect ( User . find_by_email ( " bob@foo.com " ) ) . to be_nil
expect ( User . find_by_email ( " carol@example.com " ) ) . to be_present
end
end
2017-10-03 23:28:41 +08:00
context " when destinations aren't matching any of the incoming emails " do
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " ,
:bad_destinations ,
Email :: Receiver :: BadDestinationAddress
2017-10-03 23:28:41 +08:00
end
context " when email is sent to category " do
context " when email is sent by a new user and category does not allow strangers " do
2019-05-07 11:12:20 +08:00
fab! ( :category ) do
Fabricate ( :category , email_in : " category@foo.com " , email_in_allow_strangers : false )
2023-01-09 19:18:21 +08:00
end
2017-10-03 23:28:41 +08:00
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " ,
:new_user ,
Email :: Receiver :: StrangersNotAllowedError
2017-10-03 23:28:41 +08:00
end
context " when email has no date " do
2019-05-07 11:12:20 +08:00
fab! ( :category ) do
Fabricate ( :category , email_in : " category@foo.com " , email_in_allow_strangers : true )
2023-01-09 19:18:21 +08:00
end
2017-10-03 23:28:41 +08:00
2019-04-08 17:36:39 +08:00
it " includes the translated string in the error " do
expect { process ( :no_date ) } . to raise_error ( Email :: Receiver :: InvalidPost ) . with_message (
I18n . t ( " system_messages.email_reject_invalid_post_specified.date_invalid " ) ,
)
end
include_examples " does not create staged users " , :no_date , Email :: Receiver :: InvalidPost
2017-10-03 23:28:41 +08:00
end
2019-08-07 18:32:19 +08:00
context " with forwarded emails behaviour set to quote " do
before { SiteSetting . forwarded_emails_behaviour = " quote " }
context " with a category which allows strangers " do
fab! ( :category ) do
Fabricate ( :category , email_in : " team@bar.com " , email_in_allow_strangers : true )
2023-01-09 19:18:21 +08:00
end
2019-08-07 18:32:19 +08:00
include_examples " creates topic with forwarded message as quote " ,
:category ,
" team@bar.com "
end
context " with a category which doesn't allow strangers " do
fab! ( :category ) do
Fabricate ( :category , email_in : " team@bar.com " , email_in_allow_strangers : false )
end
include_examples " cleans up staged users " ,
:forwarded_email_1 ,
Email :: Receiver :: StrangersNotAllowedError
end
end
2017-10-03 23:28:41 +08:00
end
2022-07-28 00:14:14 +08:00
context " when email is a reply " do
2017-10-03 23:28:41 +08:00
let ( :reply_key ) { " 4f97315cc828096c9cb34c6f1a0d6fe8 " }
2019-05-07 11:12:20 +08:00
fab! ( :category ) { Fabricate ( :category ) }
fab! ( :user ) { Fabricate ( :user , email : " discourse@bar.com " ) }
fab! ( :user2 ) { Fabricate ( :user , email : " someone_else@bar.com " ) }
fab! ( :topic ) { create_topic ( category : category , user : user ) }
fab! ( :post ) { create_post ( topic : topic , user : user ) }
2018-07-18 16:28:44 +08:00
let! ( :post_reply_key ) do
Fabricate ( :post_reply_key , reply_key : reply_key , user : user , post : post )
end
2017-10-03 23:28:41 +08:00
context " when the email address isn't matching the one we sent the notification to " do
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " ,
:reply_user_not_matching ,
Email :: Receiver :: ReplyUserNotMatchingError
2017-10-03 23:28:41 +08:00
end
2019-05-10 05:47:32 +08:00
2019-08-07 18:32:19 +08:00
context " with forwarded emails behaviour set to create replies " do
before { SiteSetting . forwarded_emails_behaviour = " create_replies " }
2019-05-10 05:47:32 +08:00
2021-05-21 09:43:47 +08:00
context " when a reply contains a forwarded email " do
2019-05-10 05:47:32 +08:00
include_examples " does not create staged users " , :reply_and_forwarded
end
2022-07-28 00:14:14 +08:00
context " with forwarded email to category that doesn't allow strangers " do
2019-05-10 05:47:32 +08:00
before { category . update! ( email_in : " team@bar.com " , email_in_allow_strangers : false ) }
include_examples " cleans up staged users " ,
:forwarded_email_1 ,
Email :: Receiver :: StrangersNotAllowedError
end
end
2017-10-03 23:28:41 +08:00
end
2022-07-28 00:14:14 +08:00
context " when replying without key is allowed " do
2019-05-07 11:12:20 +08:00
fab! ( :group ) { Fabricate ( :group , incoming_email : " team@bar.com " ) }
2017-10-03 23:28:41 +08:00
let! ( :topic ) do
SiteSetting . find_related_post_with_key = false
process ( :email_reply_1 )
Topic . last
end
context " when the topic was deleted " do
before { topic . update_columns ( deleted_at : 1 . day . ago ) }
2019-04-08 17:36:39 +08:00
include_examples " cleans up staged users " ,
:email_reply_staged ,
Email :: Receiver :: TopicNotFoundError
2017-10-03 23:28:41 +08:00
end
context " when the topic was closed " do
before { topic . update_columns ( closed : true ) }
2019-04-08 17:36:39 +08:00
include_examples " cleans up staged users " ,
:email_reply_staged ,
Email :: Receiver :: TopicClosedError
2017-10-03 23:28:41 +08:00
end
context " when they aren't allowed to like a post " do
before { topic . update_columns ( archived : true ) }
2019-04-08 17:36:39 +08:00
include_examples " cleans up staged users " ,
:email_reply_like ,
Email :: Receiver :: InvalidPostAction
2017-10-03 23:28:41 +08:00
end
2017-10-03 17:23:18 +08:00
end
2017-10-31 22:13:23 +08:00
it " does not remove the incoming email record when staged users are deleted " do
expect { process ( :bad_destinations ) } . to change { IncomingEmail . count } . and raise_error (
Email :: Receiver :: BadDestinationAddress ,
)
expect ( IncomingEmail . last . message_id ) . to eq ( " 9@foo.bar.mail " )
end
2017-10-03 16:13:19 +08:00
end
2023-05-19 16:33:48 +08:00
describe " mailman mirror " do
fab! ( :category ) { Fabricate ( :mailinglist_mirror_category ) }
it " uses 'from' email address " do
expect { process ( :mailman_1 ) } . to change { Topic . count }
user = Topic . last . user
expect ( user . email ) . to eq ( " some@one.com " )
expect ( user . name ) . to eq ( " Some One " )
end
it " uses 'reply-to' email address " do
expect { process ( :mailman_2 ) } . to change { Topic . count }
user = Topic . last . user
expect ( user . email ) . to eq ( " some@one.com " )
expect ( user . name ) . to eq ( " Some " )
end
it " uses 'x-mailfrom' email address and name from CC " do
expect { process ( :mailman_3 ) } . to change { Topic . count }
user = Topic . last . user
expect ( user . email ) . to eq ( " some@one.com " )
expect ( user . name ) . to eq ( " Some One " )
end
it " uses 'x-original-from' email address " do
expect { process ( :mailman_4 ) } . to change { Topic . count }
user = Topic . last . user
expect ( user . email ) . to eq ( " some@one.com " )
expect ( user . name ) . to eq ( " Some " )
end
end
2022-07-28 00:14:14 +08:00
describe " mailing list mirror " do
2019-05-07 11:12:20 +08:00
fab! ( :category ) { Fabricate ( :mailinglist_mirror_category ) }
2018-01-04 20:38:06 +08:00
2017-11-17 21:49:10 +08:00
before { SiteSetting . block_auto_generated_emails = true }
it " should allow creating topic even when email is autogenerated " do
expect { process ( :mailinglist ) } . to change { Topic . count }
2018-01-03 22:29:06 +08:00
expect ( IncomingEmail . last . is_auto_generated ) . to eq ( false )
2017-11-17 21:49:10 +08:00
end
it " should allow replying without reply key " do
process ( :mailinglist )
topic = Topic . last
expect { process ( :mailinglist_reply ) } . to change { topic . posts . count }
end
2018-01-04 20:38:06 +08:00
2018-01-04 20:39:29 +08:00
it " should skip validations for staged users " do
Fabricate ( :user , email : " alice@foo.com " , staged : true )
expect { process ( :mailinglist_short_message ) } . to change { Topic . count }
end
it " should skip validations for regular users " do
Fabricate ( :user , email : " alice@foo.com " )
expect { process ( :mailinglist_short_message ) } . to change { Topic . count }
end
2022-07-28 00:14:14 +08:00
context " with read-only category " do
2018-01-04 20:38:06 +08:00
before do
category . set_permissions ( everyone : :readonly )
2019-06-04 16:40:10 +08:00
category . save!
2018-01-04 20:38:06 +08:00
Fabricate ( :user , email : " alice@foo.com " )
Fabricate ( :user , email : " bob@bar.com " )
end
it " should allow creating topic within read-only category " do
expect { process ( :mailinglist ) } . to change { Topic . count }
end
it " should allow replying within read-only category " do
process ( :mailinglist )
topic = Topic . last
expect { process ( :mailinglist_reply ) } . to change { topic . posts . count }
end
end
2018-10-11 22:08:57 +08:00
it " ignores unsubscribe email " do
SiteSetting . unsubscribe_via_email = true
Fabricate ( :user , email : " alice@foo.com " )
expect { process ( " mailinglist_unsubscribe " ) } . to_not change {
ActionMailer :: Base . deliveries . count
}
end
2019-12-06 20:29:39 +08:00
it " ignores dmarc fails " do
expect { process ( " mailinglist_dmarc_fail " ) } . to change { Topic . count }
post = Topic . last . first_post
expect ( post . hidden ) . to eq ( false )
expect ( post . hidden_reason_id ) . to be_nil
end
2017-11-17 21:49:10 +08:00
end
2018-03-28 00:28:37 +08:00
2018-03-30 20:37:19 +08:00
it " tries to fix unparsable email addresses in To and CC headers " do
2018-03-28 00:28:37 +08:00
expect { process ( :unparsable_email_addresses ) } . to raise_error (
Email :: Receiver :: BadDestinationAddress ,
)
email = IncomingEmail . last
expect ( email . to_addresses ) . to eq ( " foo@bar.com " )
expect ( email . cc_addresses ) . to eq ( " bob@example.com;carol@example.com " )
end
2019-04-15 14:26:00 +08:00
2022-07-27 18:21:10 +08:00
describe " # select_body " do
2019-04-15 14:26:00 +08:00
let ( :email ) { << ~ EMAIL }
MIME - Version : 1 . 0
Date : Tue , 01 Jan 2019 00 : 00 : 00 + 0300
Subject : An email with whitespaces
From : Foo < foo @discourse . org >
To : bar @discourse . org
Content - Type : text / plain ; charset = " UTF-8 "
This is a line that will be stripped
This is another line that will be stripped
This is a line that will not be touched .
This is another line that will not be touched .
2019-04-16 16:39:16 +08:00
* list
* sub - list
- list
- sub - list
+ list
+ sub - list
2019-04-15 14:26:00 +08:00
[ code ]
1 . upto ( 10 ) . each do | i |
puts i
end
` ` `
# comment
[ / code]
This is going to be stripped too .
` ` `
1 . upto ( 10 ) . each do | i |
puts i
end
[ / code]
# comment
` ` `
This is going to be stripped too .
Bye !
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
EMAIL
2019-04-15 14:26:00 +08:00
let ( :stripped_text ) { << ~ MD }
This is a line that will be stripped
This is another line that will be stripped
This is a line that will not be touched .
This is another line that will not be touched .
2019-04-16 16:39:16 +08:00
* list
* sub - list
- list
- sub - list
+ list
+ sub - list
2019-04-15 14:26:00 +08:00
[ code ]
1 . upto ( 10 ) . each do | i |
puts i
end
` ` `
# comment
[ / code]
This is going to be stripped too .
` ` `
1 . upto ( 10 ) . each do | i |
puts i
end
[ / code]
# comment
` ` `
This is going to be stripped too .
Bye !
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
MD
2019-04-15 14:26:00 +08:00
it " strips lines if strip_incoming_email_lines is enabled " do
SiteSetting . strip_incoming_email_lines = true
receiver = Email :: Receiver . new ( email )
text , elided , format = receiver . select_body
expect ( text ) . to eq ( stripped_text )
end
2020-10-02 21:44:35 +08:00
it " works with empty mail body " do
SiteSetting . strip_incoming_email_lines = true
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
email = << ~ EMAIL
2020-10-02 21:44:35 +08:00
Date : Tue , 01 Jan 2019 00 : 00 : 00 + 0300
Subject : An email with whitespaces
From : Foo < foo @discourse . org >
To : bar @discourse . org
Content - Type : text / plain ; charset = " UTF-8 "
- -
my signature
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
EMAIL
2020-10-02 21:44:35 +08:00
receiver = Email :: Receiver . new ( email )
text , _elided , _format = receiver . select_body
expect ( text ) . to be_blank
end
2019-04-15 14:26:00 +08:00
end
2020-05-14 22:04:58 +08:00
describe " replying to digest " do
fab! ( :user ) { Fabricate ( :user ) }
fab! ( :digest_message_id ) { " 7402d8ae-1c6e-44bc-9948-48e007839bcc@localhost " }
fab! ( :email_log ) do
Fabricate (
:email_log ,
user : user ,
email_type : " digest " ,
to_address : user . email ,
message_id : digest_message_id ,
)
2023-01-09 19:18:21 +08:00
end
2020-05-14 22:04:58 +08:00
let ( :email ) { << ~ EMAIL }
MIME - Version : 1 . 0
Date : Tue , 01 Jan 2019 00 : 00 : 00 + 0300
From : someone < #{user.email}>
To : Discourse < #{SiteSetting.notification_email}>
Message - ID : < CANtGPwC3ZmWSxnnEuJHfosbtc9d0 - ZV02b_7KuyircDt4peDC2 @mail . gmail . com >
In - Reply - To : < #{digest_message_id}>
Subject : Re : [ Discourse ] Summary
References : < #{digest_message_id}>
Content - Type : text / plain ; charset = " UTF-8 "
hello there! I like the digest!
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
EMAIL
2020-05-14 22:04:58 +08:00
before { Jobs . run_immediately! }
it " returns a ReplyToDigestError " do
expect { Email :: Receiver . new ( email ) . process! } . to raise_error (
Email :: Receiver :: ReplyToDigestError ,
)
end
end
2020-07-10 17:05:55 +08:00
2022-07-28 00:14:14 +08:00
describe " find_related_post " do
2020-07-10 17:05:55 +08:00
let ( :user ) { Fabricate ( :user ) }
let ( :group ) { Fabricate ( :group , users : [ user ] ) }
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
let ( :email_1 ) {
<< ~ EMAIL
2020-07-10 17:05:55 +08:00
MIME - Version : 1 . 0
Date : Wed , 01 Jan 2019 12 : 00 : 00 + 0200
Message - ID : < 7 aN1uwcokt2xkfG3iYrpKmiuVhy4w9b5 @mail . gmail . com >
Subject : Lorem ipsum dolor sit amet
From : Dan Ungureanu < dan @discourse . org >
To : team - test @discourse . org
Content - Type : text / plain ; charset = " UTF-8 "
Lorem ipsum dolor sit amet , consectetur adipiscing elit . Maecenas
semper , erat tempor sodales commodo , mi diam tempus lorem , in vehicula
leo libero quis lacus . Nullam justo nunc , sagittis nec metus placerat ,
auctor condimentum neque . Sed risus purus , fermentum eget purus
porttitor , finibus efficitur orci . Integer tempus mi nec odio
elementum pulvinar . Pellentesque sed fringilla nulla , ac mollis quam .
Vivamus semper lacinia scelerisque . Cras urna magna , porttitor nec
libero quis , congue viverra sapien . Nulla sodales ac tellus a
suscipit .
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
EMAIL
2020-07-10 17:05:55 +08:00
}
let ( :post_2 ) {
incoming_email =
IncomingEmail . find_by ( message_id : " 7aN1uwcokt2xkfG3iYrpKmiuVhy4w9b5@mail.gmail.com " )
2023-01-09 19:18:21 +08:00
2020-07-10 17:05:55 +08:00
PostCreator . create (
user ,
raw :
" Vestibulum rutrum tortor vitae arcu varius, non vestibulum ipsum tempor. Integer nibh libero, dignissim eu velit vel, interdum posuere mi. Aliquam erat volutpat. Pellentesque id nulla ultricies, eleifend ipsum non, fringilla purus. Aliquam pretium dolor lobortis urna volutpat, vel consectetur arcu porta. In non erat quis nibh gravida pharetra consequat vel risus. Aliquam rutrum consectetur est ac posuere. Praesent mattis nunc risus, a molestie lectus accumsan porta. " ,
topic_id : incoming_email . topic_id ,
)
}
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
let ( :email_3 ) {
<< ~ EMAIL
2020-07-10 17:05:55 +08:00
MIME - Version : 1 . 0
Date : Wed , 01 Jan 2019 12 : 00 : 00 + 0200
References : < 7 aN1uwcokt2xkfG3iYrpKmiuVhy4w9b5 @mail . gmail . com > < topic / #{post_2.topic_id}/#{post_2.id}@test.localhost>
In - Reply - To : < topic / #{post_2.topic_id}/#{post_2.id}@test.localhost>
Message - ID : < w1vdxT8ebJjZQQp7XyDdEJaSscE9qRjr @mail . gmail . com >
Subject : Re : Lorem ipsum dolor sit amet
From : Dan Ungureanu < dan @discourse . org >
To : team - test @discourse . org
Content - Type : text / plain ; charset = " UTF-8 "
Integer mattis suscipit facilisis . Ut ullamcorper libero at faucibus
sodales . Ut suscipit elit ac dui porta consequat . Suspendisse potenti .
Nam ut accumsan dui , eget commodo sapien . Etiam ultrices elementum
cursus . Vivamus et diam et orci lobortis porttitor . Aliquam
scelerisque ex a imperdiet ornare . Donec interdum laoreet posuere .
Nulla sagittis , velit id posuere sollicitudin , elit nunc laoreet
libero , vitae aliquet tortor eros at est . Donec vitae massa vehicula ,
aliquet libero non , porttitor ipsum . Phasellus pellentesque sodales
lacus eu sagittis . Aliquam ut condimentum nisi . Nulla in placerat
felis . Sed pellentesque , massa auctor venenatis gravida , risus lorem
iaculis mi , at hendrerit nisi turpis sit amet metus . Nulla egestas
ante eget nisi luctus consectetur .
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections.
Heredoc tag names we use:
languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS
other: MD, TEXT/TXT, RAW, EMAIL
2022-03-01 03:50:55 +08:00
EMAIL
2020-07-10 17:05:55 +08:00
}
def receive ( email_string )
Email :: Receiver . new ( email_string , destinations : [ group ] ) . process!
end
it " makes all posts in same topic " do
expect { receive ( email_1 ) } . to change { Topic . count } . by ( 1 ) . and change {
Post . where ( post_type : Post . types [ :regular ] ) . count
} . by ( 1 )
2022-07-19 22:03:03 +08:00
expect { post_2 } . to not_change { Topic . count } . and change {
Post . where ( post_type : Post . types [ :regular ] ) . count
} . by ( 1 )
expect { receive ( email_3 ) } . to not_change { Topic . count } . and change {
Post . where ( post_type : Post . types [ :regular ] ) . count
} . by ( 1 )
2020-07-10 17:05:55 +08:00
end
end
2021-10-06 20:07:29 +08:00
it " fixes valid addresses in embedded emails " do
Fabricate ( :group , incoming_email : " group-fwd@example.com " )
process ( :long_embedded_email_headers )
incoming_email = IncomingEmail . find_by ( message_id : " example1@mail.gmail.com " )
expect ( incoming_email . cc_addresses ) . to include ( " a@example.com " )
expect ( incoming_email . cc_addresses ) . to include ( " c@example.com " )
end
2013-06-11 04:46:08 +08:00
end