2019-04-30 08:27:42 +08:00
# frozen_string_literal: true
2016-01-19 07:57:55 +08:00
require " rails_helper "
require " email/receiver "
2013-06-11 04:46:08 +08:00
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
2016-01-19 07:57:55 +08:00
def process ( email_name )
2016-03-07 23:56:17 +08:00
Email :: Receiver . new ( email ( email_name ) ) . 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
2017-10-03 17:23:18 +08:00
it " raises EmailNotAllowed when email address is not on whitelist " do
SiteSetting . email_domains_whitelist = " 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
expect { process ( :blacklist_whitelist_email ) } . to raise_error ( Email :: Receiver :: EmailNotAllowed )
end
it " raises EmailNotAllowed when email address is on blacklist " do
SiteSetting . email_domains_blacklist = " 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
expect { process ( :blacklist_whitelist_email ) } . to raise_error ( Email :: Receiver :: EmailNotAllowed )
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
2018-05-10 00:51:01 +08:00
topic = Fabricate ( :topic , id : 424242 )
2018-08-21 16:17:08 +08:00
post = Fabricate ( :post , topic : topic , id : 123456 )
2019-04-08 17:36:39 +08:00
user = Fabricate ( :user , email : " discourse@bar.com " )
2018-08-21 16:17:08 +08:00
expect { process ( :old_destination ) } . to raise_error (
Email :: Receiver :: BadDestinationAddress
)
IncomingEmail . destroy_all
post . update! ( created_at : 3 . days . ago )
2018-05-10 00:51:01 +08:00
2018-08-21 16:17:08 +08:00
expect { process ( :old_destination ) } . to raise_error (
Email :: Receiver :: OldDestinationError
)
SiteSetting . disallow_reply_by_email_after_days = 0
IncomingEmail . destroy_all
expect { process ( :old_destination ) } . to raise_error (
Email :: Receiver :: BadDestinationAddress
)
2018-05-10 00:51:01 +08:00
end
2018-11-27 02:59:37 +08:00
context " bounces " do
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 ) { Fabricate ( :topic , archetype : 'private_message' , category_id : nil , user : user1 , allowed_users : [ user1 , user2 ] ) }
let ( :post ) { create_post ( topic : topic , user : user1 ) }
2018-11-28 10:54:23 +08:00
before do
SiteSetting . enable_staged_users = true
SiteSetting . enable_whispers = true
end
def create_post_reply_key ( value )
Fabricate ( :post_reply_key ,
reply_key : value ,
2018-11-28 21:34:09 +08:00
user : user2 ,
2018-11-28 23:43:06 +08:00
post : post
2018-11-28 10:54:23 +08:00
)
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
2018-11-28 21:34:09 +08:00
it " when bounce with verp " do
2018-11-28 10:54:23 +08:00
SiteSetting . reply_by_email_address = " foo+%{reply_key}@discourse.org "
2018-11-28 21:34:09 +08:00
bounce_key = " 14b08c855160d67f2e0c2f8ef36e251e "
create_post_reply_key ( bounce_key )
2018-11-28 23:43:06 +08:00
Fabricate ( :email_log , to_address : email_address , user : user2 , bounce_key : bounce_key , post : post )
2018-11-28 10:54:23 +08:00
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
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 , " " )
process ( :existing_user ) rescue RuntimeError
expect ( IncomingEmail . last . error ) . to eq ( " RuntimeError " )
end
2018-11-30 14:59:51 +08:00
it " matches the correct user " do
user = Fabricate ( :user )
email_log = Fabricate ( :email_log , to_address : user . email , user : user , bounce_key : nil )
email , name = Email :: Receiver . new ( email ( :existing_user ) ) . parse_from_field
expect ( email ) . to eq ( " existing@bar.com " )
expect ( name ) . to eq ( " Foo Bar " )
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
2016-05-03 05:15:32 +08:00
context " bounces to VERP " do
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 ) { Fabricate ( :email_log , to_address : user . email , user : user , bounce_key : bounce_key ) }
let! ( :email_log_2 ) { Fabricate ( :email_log , to_address : user . email , user : user , bounce_key : bounce_key_2 ) }
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
2018-05-09 22:40:52 +08:00
it " automatically deactive users once they reach the 'bounce_score_threshold_deactivate' threshold " do
expect ( user . active ) . to eq ( true )
user . user_stat . bounce_score = SiteSetting . bounce_score_threshold_deactivate - 1
user . user_stat . save!
expect { process ( :soft_bounce_via_verp ) } . to raise_error ( Email :: Receiver :: BouncedEmailError )
user . reload
email_log . reload
expect ( email_log . bounced ) . to eq ( true )
expect ( user . active ) . to eq ( false )
end
2016-05-03 05:15:32 +08:00
end
2016-01-19 07:57:55 +08:00
context " reply " do
2015-11-19 04:22:50 +08:00
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
2019-03-06 15:38:49 +08:00
context " a closed topic " do
before do
topic . update_columns ( closed : true )
end
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
2016-01-19 07:57:55 +08:00
it " works " do
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 ;) " )
2017-05-01 05:30:40 +08:00
end
2014-11-26 00:44:59 +08:00
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
2016-01-19 07:57:55 +08:00
it " handles multiple paragraphs " do
expect { process ( :paragraphs ) } . to change { topic . posts . count }
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. Anf 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
2016-02-25 00:40:57 +08:00
it " handles invalid from header " do
2017-09-13 04:35:24 +08:00
expect { process ( :invalid_from_1 ) } . to change { topic . posts . count }
2016-02-25 00:40:57 +08:00
expect ( topic . posts . last . raw ) . to eq ( " This email was sent with an invalid from header field. " )
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
2016-04-12 04:47:34 +08:00
it " doesn't raise an AutoGeneratedEmailError when the mail is auto generated but is whitelisted " do
SiteSetting . auto_generated_whitelist = " foo@bar.com|discourse@bar.com "
2016-04-21 03:29:27 +08:00
expect { process ( :auto_generated_whitelisted ) } . to change { topic . posts . count }
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
expect { process ( :original_message ) } . to change { topic . posts . count } . from ( 1 ) . to ( 2 )
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
expect { process ( :original_message ) } . to change { topic . posts . count } . from ( 1 ) . to ( 2 )
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
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 **
! [ #{upload.original_filename}|#{upload.width}x#{upload.height}](#{upload.short_url})
* After *
MD
2014-10-25 22:36:59 +08:00
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 .
! [ #{upload.original_filename}|#{upload.width}x#{upload.height}](#{upload.short_url})
Picture above .
MD
2018-11-01 15:41:13 +08:00
end
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
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
expect { process ( :from_the_future ) } . to change { topic . posts . count }
expect ( topic . posts . last . created_at ) . to be_within ( 1 . minute ) . of ( DateTime . 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
2016-01-19 07:57:55 +08:00
context " new message to a group " do
2015-12-22 00:54:02 +08:00
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
expect { process ( :cc ) } . to change ( Topic , :count )
expect ( Topic . last . ordered_posts [ - 1 ] . post_type ) . to eq ( Post . types [ :moderator_action ] )
end
2018-08-21 14:00:45 +08:00
describe " when 'find_related_post_with_key' is disabled " do
before do
SiteSetting . find_related_post_with_key = false
end
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
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
2017-01-10 05:59:30 +08:00
context " with forwarded emails enabled " do
2019-04-08 17:36:39 +08:00
before do
Fabricate ( :group , incoming_email : " some_group@bar.com " )
SiteSetting . enable_forwarded_emails = true
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
2017-01-10 05:59:30 +08:00
SiteSetting . enable_forwarded_emails = true
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
2016-12-02 01:34:47 +08:00
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
expect { process ( :email_reply_2 ) } . to change { topic . posts . count } . by ( 1 ) . and change { Topic . count } . by ( 0 )
end
it " creates a new topic when the sender is not known " do
IncomingEmail . where ( message_id : '34@foo.bar.mail' ) . update ( cc_addresses : 'three@foo.com' )
expect { process ( :email_reply_2 ) } . to change { topic . posts . count } . by ( 0 ) . and change { Topic . count } . by ( 1 )
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' )
expect { process ( :email_reply_2 ) } . to change { topic . posts . count } . by ( 0 ) . and change { Topic . count } . by ( 1 )
end
end
2013-06-11 04:46:08 +08:00
end
2016-01-19 07:57:55 +08:00
context " new topic in a category " do
2015-12-16 07:43:05 +08:00
2019-05-07 11:12:20 +08:00
fab! ( :category ) { Fabricate ( :category , email_in : " category@bar.com|category@foo.com " , email_in_allow_strangers : false ) }
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
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 )
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'
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
expect { process ( :spam_x_spam_flag ) } . to change { Topic . count } . by ( 1 ) # Topic created
topic = Topic . last
expect ( topic . visible ) . to eq ( false )
post = Post . last
expect ( post . hidden ) . to eq ( true )
expect ( post . hidden_at ) . not_to eq ( nil )
expect ( post . hidden_reason_id ) . to eq ( Post . hidden_reasons [ :email_spam_header_found ] )
end
it " creates hidden topic for X-Spam-Status " do
SiteSetting . email_in_spam_header = 'X-Spam-Status'
Fabricate ( :user , email : " existing@bar.com " , trust_level : SiteSetting . email_in_min_trust )
expect { process ( :spam_x_spam_status ) } . to change { Topic . count } . by ( 1 ) # Topic created
topic = Topic . last
expect ( topic . visible ) . to eq ( false )
post = Post . last
expect ( post . hidden ) . to eq ( true )
expect ( post . hidden_at ) . not_to eq ( nil )
expect ( post . hidden_reason_id ) . to eq ( Post . hidden_reasons [ :email_spam_header_found ] )
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-07-28 09:20:09 +08:00
expect { process ( :forwarded_email_to_category ) } . to change { Topic . count } . by ( 1 ) # Topic created
2017-06-29 12:03:14 +08:00
new_post , = Post . last
2017-07-28 09:20:09 +08:00
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? " )
2017-06-29 12:03:14 +08:00
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
2016-06-30 20:21:47 +08:00
context " new topic in a category that allows strangers " do
2019-05-07 11:12:20 +08:00
fab! ( :category ) { Fabricate ( :category , email_in : " category@bar.com|category@foo.com " , email_in_allow_strangers : true ) }
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
2017-05-23 05:35:41 +08:00
context " # reply_by_email_address_regex " do
before do
SiteSetting . reply_by_email_address = nil
SiteSetting . alternative_reply_by_email_addresses = nil
end
2018-05-23 16:04:45 +08:00
it " it maches nothing if there is not reply_by_email_address " do
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
2017-06-09 02:28:48 +08:00
context " check_address " do
before do
SiteSetting . reply_by_email_address = " foo+%{reply_key}@bar.com "
end
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
2017-06-09 02:28:48 +08:00
expect ( dest ) . to be_present
expect ( dest [ :type ] ) . to eq ( :reply )
2018-07-18 16:28:44 +08:00
expect ( dest [ :obj ] ) . to eq ( post_reply_key )
2017-06-09 02:28:48 +08:00
end
end
end
2018-01-10 23:50:27 +08:00
context " staged users " do
2017-10-03 16:13:19 +08:00
before do
SiteSetting . enable_staged_users = true
end
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 do
ScreenedEmail . expects ( :should_block? ) . with ( " screened@mail.com " ) . returns ( true )
end
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
2018-01-10 23:50:27 +08:00
context " when From email address is not on whitelist " do
2017-10-03 17:23:18 +08:00
before do
SiteSetting . email_domains_whitelist = " 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
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " , :blacklist_whitelist_email , Email :: Receiver :: EmailNotAllowed
2017-10-03 17:23:18 +08:00
end
2018-01-10 23:50:27 +08:00
context " when From email address is on blacklist " do
2017-10-03 17:23:18 +08:00
before do
SiteSetting . email_domains_blacklist = " 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
2019-04-08 17:36:39 +08:00
include_examples " does not create staged users " , :blacklist_whitelist_email , Email :: Receiver :: EmailNotAllowed
2017-10-03 23:28:41 +08:00
end
2018-01-10 23:50:27 +08:00
context " blacklist and whitelist for To and Cc " do
before do
Fabricate ( :group , incoming_email : " some_group@bar.com " )
end
it " does not create staged users for email addresses not on whitelist " do
SiteSetting . email_domains_whitelist = " mail.com|example.com "
process ( :blacklist_whitelist_email )
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
it " does not create staged users for email addresses on blacklist " do
SiteSetting . email_domains_blacklist = " email.com|foo.com "
process ( :blacklist_whitelist_email )
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 ) { Fabricate ( :category , email_in : " category@foo.com " , email_in_allow_strangers : false ) }
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 ) { Fabricate ( :category , email_in : " category@foo.com " , email_in_allow_strangers : true ) }
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
end
context " email is a reply " do
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
context " when forwarded emails are enabled " do
before do
SiteSetting . enable_forwarded_emails = true
end
context " when a reply contains a forwareded email " do
include_examples " does not create staged users " , :reply_and_forwarded
end
context " forwarded email to category that doesn't allow strangers " do
before do
category . update! ( 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
context " 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 do
topic . update_columns ( deleted_at : 1 . day . ago )
end
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 do
topic . update_columns ( closed : true )
end
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 do
topic . update_columns ( archived : true )
end
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
2018-01-04 20:38:06 +08:00
context " 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 do
SiteSetting . block_auto_generated_emails = true
end
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
2018-01-04 20:38:06 +08:00
context " read-only category " do
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
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
context " # select_body " do
let ( :email ) {
<< ~ EOF
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 !
EOF
}
let ( :stripped_text ) {
<< ~ EOF
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 !
EOF
}
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
end
2013-06-11 04:46:08 +08:00
end