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 "
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 "
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
2016-02-11 17:39:57 +08:00
it " raises a BlockedUserError when the sender has been blocked " do
Fabricate ( :user , email : " blocked@bar.com " , blocked : true )
expect { process ( :blocked_sender ) } . to raise_error ( Email :: Receiver :: BlockedUserError )
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 )
email_log = Fabricate ( :email_log ,
to_address : 'reply+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bar.com' ,
reply_key : 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ,
user : user ,
post : Fabricate ( :post )
)
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
2016-05-03 05:15:32 +08:00
it " raises a BouncerEmailError when email is a bounced email " do
2016-04-07 22:21:17 +08:00
expect { process ( :bounced_email ) } . to raise_error ( Email :: Receiver :: BouncedEmailError )
2016-05-03 05:15:32 +08:00
expect ( IncomingEmail . last . is_bounce ) . to eq ( true )
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
2016-05-03 05:15:32 +08:00
context " bounces to VERP " do
let ( :bounce_key ) { " 14b08c855160d67f2e0c2f8ef36e251e " }
let ( :bounce_key_2 ) { " b542fb5a9bacda6d28cc061d18e4eb83 " }
2016-05-07 01:34:33 +08:00
let! ( :user ) { Fabricate ( :user , email : " foo@bar.com " ) }
2016-05-03 05:15:32 +08:00
let! ( :email_log ) { Fabricate ( :email_log , user : user , bounce_key : bounce_key ) }
let! ( :email_log_2 ) { Fabricate ( :email_log , user : user , bounce_key : bounce_key_2 ) }
before do
$redis . del ( " bounce_score: #{ user . email } : #{ Date . today } " )
$redis . del ( " bounce_score: #{ user . email } : #{ 2 . days . from_now . to_date } " )
end
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 )
expect ( email_log . user . user_stat . bounce_score ) . to eq ( 1 )
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 )
expect ( email_log . user . user_stat . bounce_score ) . to eq ( 2 )
2017-07-24 21:17:42 +08:00
freeze_time 2 . days . from_now
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
expect ( email_log_2 . user . user_stat . bounce_score ) . to eq ( 4 )
expect ( email_log_2 . bounced ) . to eq ( true )
2016-05-03 05:15:32 +08:00
end
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 " }
2016-06-27 01:25:45 +08:00
let ( :category ) { Fabricate ( :category ) }
2016-01-19 07:57:55 +08:00
let ( :user ) { Fabricate ( :user , email : " discourse@bar.com " ) }
2016-06-27 01:25:45 +08:00
let ( :topic ) { create_topic ( category : category , user : user ) }
2016-01-19 07:57:55 +08:00
let ( :post ) { create_post ( topic : topic , user : user ) }
let! ( :email_log ) { Fabricate ( :email_log , reply_key : reply_key , user : user , topic : topic , post : post ) }
2014-11-26 00:44:59 +08:00
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
expect { process ( :reply_user_not_matching ) } . to raise_error ( Email :: Receiver :: ReplyUserNotMatchingError )
2014-11-26 00:44:59 +08:00
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
2016-01-19 07:57:55 +08:00
it " raises a TopicClosedError when the topic was closed " do
topic . update_columns ( closed : true )
expect { process ( :reply_user_matching ) } . to raise_error ( Email :: Receiver :: TopicClosedError )
2015-12-10 01:44:01 +08:00
end
2016-07-05 23:33:08 +08:00
it " does not raise TopicClosedError when performing a like action " do
topic . update_columns ( closed : true )
expect { process ( :like ) } . to change ( PostAction , :count )
end
2016-01-19 07:57:55 +08:00
it " raises an InvalidPost when there was an error while creating the post " do
expect { process ( :too_small ) } . 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 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 }
expect ( topic . posts . last . raw ) . to eq ( " This is a text reply :) " )
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
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
2016-01-19 07:57:55 +08:00
it " prefers text over html " do
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 }
expect ( topic . posts . last . raw ) . to eq ( " This is a text reply :) " )
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 )
category . save
expect { process ( :staged_reply_restricted ) } . to change { topic . posts . count }
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 }
2016-03-12 00:51:16 +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 ---Original Message--- \n This part should not be included \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 )
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 ---Original Message--- \n This part should not be included \n </details> " )
end
2017-05-04 04:54:26 +08:00
it " supports attached images in TEXT part " do
2017-04-15 12:11:02 +08:00
SiteSetting . queue_jobs = true
2016-01-30 08:29:31 +08:00
expect { process ( :no_body_with_image ) } . to change { topic . posts . count }
2016-01-19 07:57:55 +08:00
expect ( topic . posts . last . raw ) . to match ( / <img / )
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 }
2017-05-04 04:54:26 +08:00
expect ( topic . posts . last . raw ) . to match ( / Before \ s+<img.+> \ s+After / )
end
it " supports attached images in HTML part " do
SiteSetting . queue_jobs = true
SiteSetting . incoming_email_prefer_html = true
expect { process ( :inline_image ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to match ( / \ * \ *Before \ * \ * \ s+<img.+> \ s+ \ *After \ * / )
2014-10-25 22:36:59 +08:00
end
2016-01-30 08:29:31 +08:00
it " supports attachments " do
SiteSetting . authorized_extensions = " txt "
expect { process ( :attached_txt_file ) } . to change { topic . posts . count }
expect ( topic . posts . last . raw ) . to match ( / text \ .txt / )
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
end
2016-01-19 07:57:55 +08:00
context " new message to a group " do
2015-12-22 00:54:02 +08:00
2016-02-25 02:47:58 +08:00
let! ( :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
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
2017-08-01 06:03:04 +08:00
it " associates email replies using both 'In-Reply-To' and 'References' headers when 'find_related_post_with_key' is disabled " do
SiteSetting . find_related_post_with_key = false
2016-01-21 05:52:08 +08:00
expect { process ( :email_reply_1 ) } . to change ( Topic , :count )
topic = Topic . last
expect { process ( :email_reply_2 ) } . to change { topic . posts . count }
expect { process ( :email_reply_3 ) } . to change { topic . posts . count }
2016-01-21 06:08:27 +08:00
# Why 5 when we only processed 3 emails?
2016-01-21 05:52:08 +08:00
# - 3 of them are indeed "regular" posts generated from the emails
2016-01-21 06:08:27 +08:00
# - The 2 others are "small action" posts automatically added because
# we invited 2 users (two@foo.com and three@foo.com)
expect ( topic . posts . count ) . to eq ( 5 )
2016-01-21 05:52:08 +08:00
# trash all but the 1st post
topic . ordered_posts [ 1 .. - 1 ] . each ( & :trash! )
expect { process ( :email_reply_4 ) } . to change { topic . posts . count }
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 )
expect ( Post . last . raw ) . to match ( / discourse \ .rb / )
end
2017-01-10 05:59:30 +08:00
context " with forwarded emails enabled " do
before { SiteSetting . enable_forwarded_emails = true }
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
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
2016-02-25 02:47:58 +08:00
let! ( :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 )
2015-04-10 17:29:45 +08:00
category . save
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
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 )
category . save
Group . refresh_automatic_group! ( :trust_level_4 )
expect { process ( :tl3_user ) } . to_not change ( Topic , :count )
expect { process ( :tl4_user ) } . to change ( Topic , :count )
end
2016-05-19 05:07:01 +08:00
it " ignores by title " do
SiteSetting . ignore_by_title = " foo "
expect { process ( :ignored ) } . to_not change ( Topic , :count )
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
let! ( :category ) { Fabricate ( :category , email_in : " category@bar.com|category@foo.com " , email_in_allow_strangers : true ) }
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
it " is empty by default " do
expect ( Email :: Receiver . reply_by_email_address_regex ) . to eq ( / / )
end
it " uses 'reply_by_email_address' site setting " do
SiteSetting . reply_by_email_address = " foo+%{reply_key}@bar.com "
expect ( Email :: Receiver . reply_by_email_address_regex ) . to eq ( / foo \ +( \ h{32})@bar \ .com / )
end
it " uses 'alternative_reply_by_email_addresses' site setting " do
SiteSetting . alternative_reply_by_email_addresses = " alt.foo+%{reply_key}@bar.com "
expect ( Email :: Receiver . reply_by_email_address_regex ) . to eq ( / alt \ .foo \ +( \ h{32})@bar \ .com / )
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 "
expect ( Email :: Receiver . reply_by_email_address_regex ) . to eq ( / foo \ +( \ h{32})@bar \ .com|alt \ .foo \ +( \ h{32})@bar \ .com / )
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
Fabricate ( :email_log , reply_key : '4f97315cc828096c9cb34c6f1a0d6fe8' )
dest = Email :: Receiver . check_address ( 'foo+4f97315cc828096c9cb34c6f1a0d6fe8@bar.com' )
expect ( dest ) . to be_present
expect ( dest [ :type ] ) . to eq ( :reply )
expect ( dest [ :obj ] ) . to be_present
end
end
end
2017-10-03 16:13:19 +08:00
context " no staged users on error " do
before do
SiteSetting . enable_staged_users = true
end
2017-10-03 23:28:41 +08:00
shared_examples " no staged users " do | email_name , expected_exception |
2017-10-03 16:13:19 +08:00
it " does not create staged users " do
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
2017-10-03 23:28:41 +08:00
include_examples " no staged users " , :screened_email , Email :: Receiver :: ScreenedEmailError
2017-10-03 16:13:19 +08:00
end
context " when the mail is auto generated " do
2017-10-03 23:28:41 +08:00
include_examples " no 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
2017-10-03 23:28:41 +08:00
include_examples " no staged users " , :bounced_email , Email :: Receiver :: BouncedEmailError
2017-10-03 16:13:19 +08:00
end
context " when the body is blank " do
2017-10-03 23:28:41 +08:00
include_examples " no 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
2017-10-03 23:28:41 +08:00
include_examples " no 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
context " when email address is not on whitelist " do
before do
SiteSetting . email_domains_whitelist = " example.com|bar.com "
end
2017-10-03 23:28:41 +08:00
include_examples " no staged users " , :blacklist_whitelist_email , Email :: Receiver :: EmailNotAllowed
2017-10-03 17:23:18 +08:00
end
context " when email address is on blacklist " do
before do
SiteSetting . email_domains_blacklist = " email.com|mail.com "
end
2017-10-03 23:28:41 +08:00
include_examples " no staged users " , :blacklist_whitelist_email , Email :: Receiver :: EmailNotAllowed
end
context " when destinations aren't matching any of the incoming emails " do
include_examples " no staged users " , :bad_destinations , Email :: Receiver :: BadDestinationAddress
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
let! ( :category ) { Fabricate ( :category , email_in : " category@foo.com " , email_in_allow_strangers : false ) }
include_examples " no staged users " , :new_user , Email :: Receiver :: StrangersNotAllowedError
end
context " when email has no date " do
let! ( :category ) { Fabricate ( :category , email_in : " category@foo.com " , email_in_allow_strangers : true ) }
include_examples " no staged users " , :no_date , Email :: Receiver :: InvalidPost
end
end
context " email is a reply " do
let ( :reply_key ) { " 4f97315cc828096c9cb34c6f1a0d6fe8 " }
let ( :category ) { Fabricate ( :category ) }
let ( :user ) { Fabricate ( :user , email : " discourse@bar.com " ) }
let ( :topic ) { create_topic ( category : category , user : user ) }
let ( :post ) { create_post ( topic : topic , user : user ) }
let! ( :email_log ) { Fabricate ( :email_log , reply_key : reply_key , user : user , topic : topic , post : post ) }
context " when the email address isn't matching the one we sent the notification to " do
include_examples " no staged users " , :reply_user_not_matching , Email :: Receiver :: ReplyUserNotMatchingError
end
end
context " replying without key is allowed " do
let! ( :group ) { Fabricate ( :group , incoming_email : " team@bar.com " ) }
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
include_examples " no staged users " , :email_reply_staged , Email :: Receiver :: TopicNotFoundError
end
context " when the topic was closed " do
before do
topic . update_columns ( closed : true )
end
include_examples " no staged users " , :email_reply_staged , Email :: Receiver :: TopicClosedError
end
context " when they aren't allowed to like a post " do
before do
topic . update_columns ( archived : true )
end
include_examples " no staged users " , :email_reply_like , Email :: Receiver :: InvalidPostAction
end
2017-10-03 17:23:18 +08:00
end
2017-10-03 16:13:19 +08:00
end
2013-06-11 04:46:08 +08:00
end