diff options
Diffstat (limited to 'test/functional')
14 files changed, 299 insertions, 26 deletions
diff --git a/test/functional/cases/001_merged/350_magic.robot b/test/functional/cases/001_merged/350_magic.robot index 66a18f2af..b2746ce3c 100644 --- a/test/functional/cases/001_merged/350_magic.robot +++ b/test/functional/cases/001_merged/350_magic.robot @@ -65,3 +65,4 @@ Magic detections bundle 1 ... MAGIC_SYM_ICS_55 ... MAGIC_SYM_VCF_56 ... MAGIC_SYM_CSV_57 + ... MAGIC_SYM_HEIC_58 diff --git a/test/functional/cases/270_regexp_maps.robot b/test/functional/cases/270_regexp_maps.robot new file mode 100644 index 000000000..d89143bc8 --- /dev/null +++ b/test/functional/cases/270_regexp_maps.robot @@ -0,0 +1,48 @@ +*** Settings *** +Test Setup Rspamd Setup +Test Teardown Rspamd Teardown +Library ${RSPAMD_TESTDIR}/lib/rspamd.py +Resource ${RSPAMD_TESTDIR}/lib/rspamd.robot +Variables ${RSPAMD_TESTDIR}/lib/vars.py + +*** Variables *** +${CONFIG} ${RSPAMD_TESTDIR}/configs/regexp_maps.conf +${MESSAGE1} ${RSPAMD_TESTDIR}/messages/advance_fee_fraud.eml +${MESSAGE2} ${RSPAMD_TESTDIR}/messages/spam_message.eml +${RSPAMD_SCOPE} Test +${RSPAMD_URL_TLD} ${RSPAMD_TESTDIR}/../lua/unit/test_tld.dat + +*** Test Cases *** +Advance Fee Fraud Detection + [Documentation] Test that advance fee fraud rules match correctly + Scan File ${MESSAGE1} + Expect Symbol ADVANCE_FEE_2 + Expect Symbol ADVANCE_FEE_3 + # Verify filtered options (no __ atoms, max 5 options) + ${symbols} = Get From Dictionary ${SCAN_RESULT}[symbols] ADVANCE_FEE_2 + ${options} = Get From Dictionary ${symbols} options + ${options_count} = Get Length ${options} + Should Be True ${options_count} <= 5 msg=Too many options: ${options_count} + FOR ${option} IN @{options} + Should Not Match Regexp ${option} ^__ msg=Option should not start with __: ${option} + END + +Meta Rule Combination + [Documentation] Test that meta rules correctly combine atom results + Scan File ${MESSAGE1} + Expect Symbol With Score ADVANCE_FEE_2 4.0 + Expect Symbol With Score ADVANCE_FEE_3 5.0 + +No False Positives on Ham + [Documentation] Test that regexp rules don't trigger on legitimate messages + Scan File ${MESSAGE2} + Do Not Expect Symbol ADVANCE_FEE_2 + Do Not Expect Symbol ADVANCE_FEE_3 + +Atom Rules Availability + [Documentation] Test that individual atom rules are available for combination + Scan File ${MESSAGE1} + # These should be available internally but not shown as main results + # We test by ensuring the meta rules work correctly + Expect Symbol ADVANCE_FEE_2 + Expect Symbol ADVANCE_FEE_3 diff --git a/test/functional/cases/400_known_senders.robot b/test/functional/cases/400_known_senders.robot index d827acc0e..a7cde59cb 100644 --- a/test/functional/cases/400_known_senders.robot +++ b/test/functional/cases/400_known_senders.robot @@ -43,33 +43,37 @@ INCOMING MAIL SENDER IS UNKNOWN ... Settings={symbols_enabled [${SYMBOL_GLOBAL}, ${SYMBOL_LOCAL}]} Do Not Expect Symbol ${SYMBOL_GLOBAL} Do Not Expect Symbol ${SYMBOL_LOCAL} - + INCOMING MAIL SENDER IS KNOWN RECIPIENTS ARE UNKNOWN Scan File ${RSPAMD_TESTDIR}/messages/set_replyto_1_1.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 + ... User=xxx@abrakadabra.com + ... From=xxx@abrakadabra.com ... Settings=${SETTINGS_REPLIES} Scan File ${RSPAMD_TESTDIR}/messages/replyto_1_1.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 + ... Settings=${SETTINGS_REPLIES} + ... Rcpt=xxx@abrakadabra.com ... Settings=${SETTINGS_REPLIES} + ... From=user@emailbl.com Scan File ${RSPAMD_TESTDIR}/messages/inc_mail_known_sender.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 ... Settings={symbols_enabled [${SYMBOL_GLOBAL}, ${SYMBOL_LOCAL}]} Expect Symbol ${SYMBOL_GLOBAL} Do Not Expect Symbol ${SYMBOL_LOCAL} INCOMING MAIL SENDER IS KNOWN RECIPIENTS ARE KNOWN Scan File ${RSPAMD_TESTDIR}/messages/set_replyto_1_1.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 User=user@emailbl.com From=user@emailbl.com ... Settings=${SETTINGS_REPLIES} Scan File ${RSPAMD_TESTDIR}/messages/replyto_1_1.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 User=user@emailbl.com Rcpt=user@emailbl.com ... Settings=${SETTINGS_REPLIES} Scan File ${RSPAMD_TESTDIR}/messages/inc_mail_known_sender.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 User=user@emailbl.com Rcpt=user@emailbl.com ... Settings=${SETTINGS_REPLIES} Scan File ${RSPAMD_TESTDIR}/messages/inc_mail_known_sender.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 User=user@emailbl.com Rcpt=user@emailbl.com ... Settings={symbols_enabled [${SYMBOL_GLOBAL}, ${SYMBOL_LOCAL}]} Expect Symbol ${SYMBOL_GLOBAL} Expect Symbol ${SYMBOL_LOCAL} - diff --git a/test/functional/cases/410_replies.robot b/test/functional/cases/410_replies.robot index 23ad9df35..b6710149c 100644 --- a/test/functional/cases/410_replies.robot +++ b/test/functional/cases/410_replies.robot @@ -15,33 +15,36 @@ ${RSPAMD_SCOPE} Suite *** Test Cases *** Reply to 1 sender 1 recipients Scan File ${RSPAMD_TESTDIR}/messages/set_replyto_1_1.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 + ... User=xxx@abrakadabra.com + ... From=xxx@abrakadabra.com ... Settings=${SETTINGS_REPLIES} + ... Rcpt=user@emailbl.com Scan File ${RSPAMD_TESTDIR}/messages/replyto_1_1.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 + ... Rcpt=xxx@abrakadabra.com ... Settings=${SETTINGS_REPLIES} + ... From=user@emailbl.com Expect Symbol ${SYMBOL} -Reply to 1 sender 2 recipients first is set second is not +Reply to 1 sender 2 recipients but SMTP recipient matches Scan File ${RSPAMD_TESTDIR}/messages/set_replyto_1_2_first.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 + ... User=xxxx@emailbl.com ... Settings=${SETTINGS_REPLIES} Scan File ${RSPAMD_TESTDIR}/messages/replyto_1_2.eml - ... IP=8.8.8.8 User=user@emailbl.com + ... IP=8.8.8.8 + ... Rcpt=xxxx@emailbl.com ... Settings=${SETTINGS_REPLIES} Expect Symbol ${SYMBOL} -Reply to 1 sender 2 recipients 1 rcpt is same - Scan File ${RSPAMD_TESTDIR}/messages/replyto_1_2_s.eml - ... IP=8.8.8.8 User=user@emailbl.com +Reply to 1 sender 2 recipients but SMTP recipient NOT matches + Scan File ${RSPAMD_TESTDIR}/messages/set_replyto_1_2_first.eml + ... IP=8.8.8.8 + ... User=user@emailbl.com ... Settings=${SETTINGS_REPLIES} - Expect Symbol ${SYMBOL} - -Reply to another sender 2 recipients - Scan File ${RSPAMD_TESTDIR}/messages/set_replyto_2_2.eml - ... IP=8.8.8.8 User=another@emailbl.com + Scan File ${RSPAMD_TESTDIR}/messages/replyto_1_2.eml + ... IP=8.8.8.8 User=user@emailbl.com + ... Rcpt=another@emailbl.com ... Settings=${SETTINGS_REPLIES} - Scan File ${RSPAMD_TESTDIR}/messages/replyto_2_2.eml - ... IP=8.8.8.8 User=another@emailbl.com - ... Settings=${SETTINGS_REPLIES} - Expect Symbol ${SYMBOL} + Do Not Expect Symbol ${SYMBOL} diff --git a/test/functional/cases/410_logging/000_console/000_systemd_logger.robot b/test/functional/cases/411_logging/000_console/000_systemd_logger.robot index 88178461b..88178461b 100644 --- a/test/functional/cases/410_logging/000_console/000_systemd_logger.robot +++ b/test/functional/cases/411_logging/000_console/000_systemd_logger.robot diff --git a/test/functional/cases/410_logging/000_console/001_timestamps.robot b/test/functional/cases/411_logging/000_console/001_timestamps.robot index bd8e2c349..bd8e2c349 100644 --- a/test/functional/cases/410_logging/000_console/001_timestamps.robot +++ b/test/functional/cases/411_logging/000_console/001_timestamps.robot diff --git a/test/functional/cases/410_logging/001_file/000_json.robot b/test/functional/cases/411_logging/001_file/000_json.robot index a2f04e85c..a2f04e85c 100644 --- a/test/functional/cases/410_logging/001_file/000_json.robot +++ b/test/functional/cases/411_logging/001_file/000_json.robot diff --git a/test/functional/cases/550_milter_headers.robot b/test/functional/cases/550_milter_headers.robot index 80471b83c..c09659714 100644 --- a/test/functional/cases/550_milter_headers.robot +++ b/test/functional/cases/550_milter_headers.robot @@ -37,3 +37,14 @@ CHECK HEADERS WITHOUT TEST SYMBOL # Check X-Spam-Level header Do Not Expect Added Header X-Spam-Level Expect Removed Header X-Spam-Level + +CHECK HEADERS WITH OVERRIDE SETTINGS + # id_milter_headers_override setting enables only authentication-results and x-spam-level routines + Scan File ${MESSAGE} Settings-Id=id_milter_headers_override + # Test the milter_headers override behavior + # Check that Authentication-Results and X-Spam-Level headers are present (exact values are not important) + Expect Header Is Present Authentication-Results + Expect Header Is Present X-Spam-Level + # Verify other headers are not added since only authentication-results and x-spam-level routines run + Do Not Expect Added Header X-Virus + Do Not Expect Added Header My-Spamd-Bar diff --git a/test/functional/configs/maps/advance_fee_rules.map b/test/functional/configs/maps/advance_fee_rules.map new file mode 100644 index 000000000..d07b25c71 --- /dev/null +++ b/test/functional/configs/maps/advance_fee_rules.map @@ -0,0 +1,43 @@ +# SpamAssassin-style rules for advance fee fraud detection (simplified for testing) + +# Individual atom rules (these detect specific patterns) +header __FRAUD_VQE Subject =~ /^(?:Re:|\[.{1,10}\])?\s*(?:very )?urgent\s+(?:(?:and|&)\s+)?(?:confidential|assistance|business|attention|reply|response|help)\b/i + +body __FRAUD_DBI /(?:\bdollars?\b|\busd(?:ollars)?(?:[0-9]|\b)|\bus\$|\$[0-9,.]{6,}|\$[0-9].{0,8}[mb]illion|\$[0-9.,]{2,10} ?m|\beuros?\b|u[.]?s[.]? [0-9.]+ m)/i +body __FRAUD_KJV /(?:claim|concerning) (?:the|this) money/i +body __FRAUD_NEB /(?:government|bank) of nigeria/i +body __FRAUD_XJR /(?:who was a|as a|an? honest|you being a|to any) foreigner/i +body __FRAUD_JBU /\bforeign account\b/i +body __FRAUD_XVW /\bhonest cooperation\b/i +body __FRAUD_LTX /\bmilli?on (?:.{1,25} thousand\s*)?(?:(?:united states|u\.?s\.?) dollars|(?i:U\.?S\.?D?))\b/i +body __FRAUD_PVN /as the beneficiary/i +body __FRAUD_MQO /foreign (?:business partner|customer)/i +body __FRAUD_TCC /foreign (?:offshore )?(?:bank|account)/i +body __FRAUD_GBW /god gives .{1,10}second chance/i +body __FRAUD_NRG /i am contacting you/i +body __FRAUD_YPO /the total sum/i +body __FRAUD_UOQ /vital documents/i +body __FRAUD_BEP /\b(?:bank of nigeria|central bank of|trust bank|apex bank|amalgamated bank)\b/i +body __FRAUD_DPR /\b(?:(?:respond|reply) (?:urgently|immediately)|(?:urgent|immediate|earliest) (?:reply|response))\b/i +body __FRAUD_QXX /\b(?:my name is|i am) (?:mrs?|engr|barrister|dr|prince(?:ss)?)[. ]/i +body __FRAUD_PTS /\b(?:ass?ass?inat(?:ed|ion)|murder(?:e?d)?|kill(?:ed|ing)\b[^.]{0,99}\b(?:war veterans|rebels?))\b/i +body __FRAUD_TDP /\b(?:business partner(?:s|ship)?|silent partner(?:s|ship)?)\b/i +body __FRAUD_AON /\b(?:confidential|private|alternate|alternative) (?:(?:e-? *)?mail)\b/i +body __FRAUD_YWW /\bfurnish you with\b/i +body __FRAUD_ULK /\baffidavits?\b/i +body __FRAUD_IOU /\b(?:no risks?|risk-? *free|free of risks?|100% safe)\b/i +body __FRAUD_IRT /\b(?:compliments? of the|dear friend|dear sir|yours faithfully|season'?s greetings)\b/i +body __FRAUD_ETX /\byour\b[^.]{0,99}\b(?:contact (?:details|information)|private (?:e?[- ]?mail|telephone|tel|phone|fax))\b/i +body __FRAUD_WDR /\bprivate lawyer\b/i + +# Meta rules that combine multiple atoms +meta ADVANCE_FEE_2 (__FRAUD_KJV + __FRAUD_NEB + __FRAUD_XJR + __FRAUD_JBU + __FRAUD_XVW + __FRAUD_LTX + __FRAUD_PVN + __FRAUD_MQO + __FRAUD_TCC + __FRAUD_GBW + __FRAUD_NRG + __FRAUD_YPO + __FRAUD_UOQ + __FRAUD_DBI + __FRAUD_BEP + __FRAUD_DPR + __FRAUD_QXX + __FRAUD_PTS + __FRAUD_TDP + __FRAUD_AON + __FRAUD_YWW + __FRAUD_ULK + __FRAUD_IOU + __FRAUD_IRT + __FRAUD_ETX + __FRAUD_WDR > 2) + +meta ADVANCE_FEE_3 (__FRAUD_KJV + __FRAUD_NEB + __FRAUD_XJR + __FRAUD_JBU + __FRAUD_XVW + __FRAUD_LTX + __FRAUD_PVN + __FRAUD_MQO + __FRAUD_TCC + __FRAUD_GBW + __FRAUD_NRG + __FRAUD_YPO + __FRAUD_UOQ + __FRAUD_DBI + __FRAUD_BEP + __FRAUD_DPR + __FRAUD_QXX + __FRAUD_PTS + __FRAUD_TDP + __FRAUD_AON + __FRAUD_YWW + __FRAUD_ULK + __FRAUD_IOU + __FRAUD_IRT + __FRAUD_ETX + __FRAUD_WDR > 3) + +# Descriptions for the rules +describe ADVANCE_FEE_2 Appears to be advance fee fraud (Nigerian 419) - moderate confidence +describe ADVANCE_FEE_3 Appears to be advance fee fraud (Nigerian 419) - high confidence + +score ADVANCE_FEE_2 4.0 +score ADVANCE_FEE_3 5.0
\ No newline at end of file diff --git a/test/functional/configs/milter_headers.conf b/test/functional/configs/milter_headers.conf index 947bc28dd..502747605 100644 --- a/test/functional/configs/milter_headers.conf +++ b/test/functional/configs/milter_headers.conf @@ -22,3 +22,15 @@ milter_headers { } } + +settings { + id_milter_headers_override { + apply { + plugins { + milter_headers { + routines = [ authentication-results, x-spam-level ]; + } + } + } + } +} diff --git a/test/functional/configs/regexp_maps.conf b/test/functional/configs/regexp_maps.conf new file mode 100644 index 000000000..be4cd047b --- /dev/null +++ b/test/functional/configs/regexp_maps.conf @@ -0,0 +1,51 @@ +.include(duplicate=append,priority=0) "{= env.TESTDIR =}/configs/plugins.conf" + +# Configure multimap for regexp rules testing +multimap { + ADVANCE_FEE_SA_RULES { + type = "regexp_rules"; + map = "{= env.TESTDIR =}/configs/maps/advance_fee_rules.map"; + scope = "advance_fee_scope"; + description = "Advance fee fraud detection rules"; + } +} + +# Override symbol scores for testing +symbols { + ADVANCE_FEE_2 { + score = 4.0; + description = "Advance fee fraud pattern (medium confidence)"; + group = "scam"; + } + ADVANCE_FEE_3 { + score = 5.0; + description = "Advance fee fraud pattern (high confidence)"; + group = "scam"; + } +} + +# Set required score for testing +actions { + reject = 10; + add_header = 6; + greylist = 4; +} + +# Enable necessary modules +dmarc { } +spf { } +dkim { } + +# Module path for multimap +modules { + path = "{= env.TESTDIR =}/../../src/plugins/lua/" +} + +# Disable some modules that might interfere with testing +rbl { + enabled = false; +} + +fuzzy_check { + enabled = false; +} diff --git a/test/functional/lib/rspamd.robot b/test/functional/lib/rspamd.robot index 9c30a97db..5d23e3ceb 100644 --- a/test/functional/lib/rspamd.robot +++ b/test/functional/lib/rspamd.robot @@ -120,6 +120,15 @@ Expect Added Header Should Be Equal ${SCAN_RESULT}[milter][add_headers][${header_name}][value] ${header_value} Should Be Equal as Numbers ${SCAN_RESULT}[milter][add_headers][${header_name}][order] ${pos} +Expect Header Is Present + [Arguments] ${header_name} + Dictionary Should Contain Key ${SCAN_RESULT} milter + ... msg=milter block was not present in protocol response + Dictionary Should Contain Key ${SCAN_RESULT}[milter] add_headers + ... msg=add_headers block was not present in protocol response + Dictionary Should Contain Key ${SCAN_RESULT}[milter][add_headers] ${header_name} + ... msg=${header_name} was not added + Expect Email [Arguments] ${email} List Should Contain Value ${SCAN_RESULT}[emails] ${email} diff --git a/test/functional/messages/advance_fee_fraud.eml b/test/functional/messages/advance_fee_fraud.eml new file mode 100644 index 000000000..d9b468b6a --- /dev/null +++ b/test/functional/messages/advance_fee_fraud.eml @@ -0,0 +1,37 @@ +From: Prince John Doe <prince@nigeria-bank.com> +To: recipient@example.com +Subject: URGENT BUSINESS ASSISTANCE NEEDED +Date: Thu, 26 Oct 2023 10:30:00 +0000 +Message-ID: <advance-fee-test@example.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 + +Dear Friend, + +Compliments of the season. I am contacting you with utmost confidence +regarding this money transfer opportunity that will be of mutual benefit +to both of us. + +My name is Prince John Doe, director of the Central Bank of Nigeria. +I am writing to you concerning the total sum of Twenty-Five Million +United States Dollars ($25,000,000 USD) that belongs to a foreigner +who died in a plane crash. + +As the beneficiary of this vast fortune, I need your honest cooperation +to claim this money. The Government of Nigeria has approved this transfer +to a foreign account, and you have been selected as a business partner +to assist in this confidential transaction. + +This is a risk-free business proposal, and I can furnish you with +all vital documents to prove the legitimacy of this transaction. +Your private email and contact details are needed to proceed immediately. + +Please respond urgently through my private lawyer, as this requires +your immediate attention. God gives everyone a second chance, and this +is yours. + +Yours faithfully, +Prince John Doe +Director, Bank of Nigeria + +Note: This is 100% safe and no risk is involved. diff --git a/test/functional/messages/gargantua.eml b/test/functional/messages/gargantua.eml index c6edc50f3..acb3d367f 100644 --- a/test/functional/messages/gargantua.eml +++ b/test/functional/messages/gargantua.eml @@ -23502,4 +23502,58 @@ X-Real-Type: csv ImZvbyIsImJhciIsImJheiIKIjEiLCIyIiwiMyIK +--XXX +Content-Type: image/heic +Content-Transfer-Encoding: base64 +X-Real-Type: heic + +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 +0YCJBxFcC867msO9wip2vP786vlLeC/fqKwSng== + --XXX-- |