aws-email-check: only report ban-risk mails (suspension/abuse/suspicious activity)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -64,16 +64,11 @@ class ExtractionTests(unittest.TestCase):
|
||||
self.assertEqual(record["action"], check_mail.EMPTY)
|
||||
self.assertEqual(record["deadline"], check_mail.EMPTY)
|
||||
|
||||
def test_identity_verification_footer_does_not_imply_compromise(self):
|
||||
record = synthetic(
|
||||
def test_identity_verification_footer_is_not_ban_alert(self):
|
||||
self.assertIsNone(synthetic(
|
||||
"验证您的身份",
|
||||
"AWS 身份验证通知。为保护您的安全,如果您发现未授权访问,请联系支持团队。",
|
||||
)
|
||||
self.assertEqual(record["type"], "身份验证通知")
|
||||
self.assertEqual(record["warning"], check_mail.EMPTY)
|
||||
self.assertEqual(record["action"], check_mail.EMPTY)
|
||||
self.assertEqual(record["account"], check_mail.EMPTY)
|
||||
self.assertEqual(record["deadline"], check_mail.EMPTY)
|
||||
))
|
||||
|
||||
def test_specific_subject_outweighs_quoted_phishing_report(self):
|
||||
record = synthetic(
|
||||
@@ -83,91 +78,180 @@ class ExtractionTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(record["type"], "账户验证或暂停")
|
||||
|
||||
def test_local_forwarded_login_code_is_filtered(self):
|
||||
self.assertIsNone(sample("*FW__*.eml", "过滤邮件"))
|
||||
|
||||
def test_local_forwarded_access_validated_notice_is_filtered(self):
|
||||
self.assertIsNone(sample("*Resources_Has_Been_Validated.eml", "过滤邮件"))
|
||||
|
||||
def test_access_validated_notices_are_filtered(self):
|
||||
cases = [
|
||||
("您访问 AWS 资源的请求已得到验证", "您的 AWS 资源访问请求已完成核验,现在可以访问资源。", False),
|
||||
("AWS: Your Request For Accessing AWS Resources Has Been Validated",
|
||||
"The request is complete. You may access AWS resources.", False),
|
||||
("Fw: 您访问 AWS 资源的请求已得到验证 / "
|
||||
"Your Request For Accessing AWS Resources Has Been Validated",
|
||||
"AWS 资源访问现已恢复。如果您有任何问题,请联系支持。", False),
|
||||
("Fwd: AWS notification", "Forwarded message:\nSubject: Your Request For Accessing "
|
||||
"AWS Resources Has Been Validated\nYou may access resources again.", False),
|
||||
("FW: AWS notification", "<div>Your Request For Accessing</div><p>AWS Resources "
|
||||
"Has Been Successfully Validated</p><p>You may access AWS resources.</p>", True),
|
||||
("Fw: AWS 通知", "<p>您访问 AWS 资源的请求已得到验证</p><p>现在可以访问资源。</p>", True),
|
||||
]
|
||||
for subject, body, rich in cases:
|
||||
with self.subTest(subject=subject, rich=rich):
|
||||
self.assertIsNone(synthetic(subject, body, rich))
|
||||
|
||||
def test_success_notice_does_not_hide_actual_risk_or_required_documents(self):
|
||||
success = "Your Request For Accessing AWS Resources Has Been Validated"
|
||||
risks = [
|
||||
"Your AWS account has been suspended.",
|
||||
"Your AWS account is restricted.",
|
||||
"Your AWS account is disabled.",
|
||||
"Your AWS account has been terminated.",
|
||||
"Your AWS account is closed.",
|
||||
"Your access key has been compromised.",
|
||||
"Your AWS resource has been implicated in hosting a phishing website.",
|
||||
"We detected potentially unwanted activity in your AWS account.",
|
||||
"Please upload your identity documents.",
|
||||
"If you fail to respond, your account will be suspended.",
|
||||
"您的 AWS 账户已受限。",
|
||||
"您的账户已暂停。请提交身份证明材料。",
|
||||
]
|
||||
for body in risks:
|
||||
with self.subTest(body=body):
|
||||
self.assertIsNotNone(synthetic(success, body))
|
||||
for subject in ("AWS Abuse Report", "AWS Suspicious Activity", "AWS Account Permanent Closure Confirmation"):
|
||||
with self.subTest(subject=subject):
|
||||
self.assertIsNotNone(synthetic(subject, success))
|
||||
|
||||
def test_other_validation_notices_remain_reported(self):
|
||||
cases = [
|
||||
("AWS Identity Validated", "Contact support regarding your identity verification."),
|
||||
("AWS 验证您的身份", "请上传身份证核验材料。"),
|
||||
("Your Request For Accessing AWS Resources Has Not Been Validated",
|
||||
"We could not validate important details. Please upload proof of identity."),
|
||||
("AWS notification", "Your Request For Accessing AWS Resources Has Been Validated? "
|
||||
"Your account has been placed on hold."),
|
||||
]
|
||||
for subject, body in cases:
|
||||
with self.subTest(subject=subject):
|
||||
self.assertIsNotNone(synthetic(subject, body))
|
||||
|
||||
def test_access_success_keeps_explicit_resource_risk_actions(self):
|
||||
subject = "Your Request For Accessing AWS Resources Has Been Validated"
|
||||
cases = [
|
||||
"Please take action immediately to remove phishing content from your AWS resource.",
|
||||
"Please delete malicious content hosted on your AWS resource.",
|
||||
"You must stop abusive traffic from your AWS resource.",
|
||||
"请立即删除您的 AWS 资源上的钓鱼内容。",
|
||||
"必须停止 AWS 资源上的滥用行为。",
|
||||
]
|
||||
for body in cases:
|
||||
with self.subTest(body=body):
|
||||
self.assertIsNotNone(synthetic(subject, body))
|
||||
|
||||
def test_access_success_security_tips_are_still_filtered(self):
|
||||
subject = "Your Request For Accessing AWS Resources Has Been Validated"
|
||||
cases = [
|
||||
"If you find phishing content, please remove phishing content from your AWS resource.",
|
||||
"If you have questions, please take action to contact AWS support.",
|
||||
"如果您发现钓鱼内容,请立即删除 AWS 资源上的钓鱼内容。",
|
||||
"如果您有任何问题,请联系支持团队。",
|
||||
"Please contact AWS support if you need help accessing resources.",
|
||||
]
|
||||
for body in cases:
|
||||
with self.subTest(body=body):
|
||||
self.assertIsNone(synthetic(subject, body))
|
||||
def test_local_forwarded_login_code_is_filtered(self):
|
||||
self.assertIsNone(sample("*FW__*.eml", "过滤邮件"))
|
||||
|
||||
def test_local_forwarded_access_validated_notice_is_filtered(self):
|
||||
self.assertIsNone(sample("*Resources_Has_Been_Validated.eml", "过滤邮件"))
|
||||
|
||||
def test_local_forwarded_domain_expiration_notice_is_filtered(self):
|
||||
self.assertIsNone(sample("*Domain_expiring*.eml", "过滤邮件"))
|
||||
|
||||
def test_domain_expiration_notices_are_filtered(self):
|
||||
cases = [
|
||||
("Fw:[Domain expiring] Registration for example.net expires on 2027-02-11",
|
||||
"Dear AWS customer, you have disabled automatic annual renewal for this domain.", False),
|
||||
("FWD: [DOMAIN EXPIRING] Registration for other.org expires on 2028-04-09",
|
||||
"AWS domain registration verification: automatic renewal is disabled.", False),
|
||||
("AWS notification", "Forwarded message:\nSubject: Registration for example.net "
|
||||
"expires on 2027-02-11\nAutomatic renewal is disabled.", False),
|
||||
("FW: AWS notification", "<div>Domain Expiring Soon</div><p>Your domain is "
|
||||
"scheduled to expire. Automatic annual renewal is disabled.</p>", True),
|
||||
("转发:AWS 域名到期提醒", "您的域名即将到期,自动续费已停用。", False),
|
||||
("AWS 通知", "<p>域名注册将于 2027-02-11 到期</p><p>自动续费已停用。</p>", True),
|
||||
]
|
||||
for subject, body, rich in cases:
|
||||
with self.subTest(subject=subject, rich=rich):
|
||||
self.assertIsNone(synthetic(subject, body, rich))
|
||||
|
||||
def test_domain_renewal_business_states_are_filtered(self):
|
||||
cases = [
|
||||
("AWS domain renewal failed", "Automatic renewal is disabled. "
|
||||
"The domain has been suspended because its registration expired."),
|
||||
("AWS domain renewal reminder", "Your domain is disabled after expiration. "
|
||||
"Payment verification failed; please renew its registration."),
|
||||
("AWS 域名续费失败", "域名已暂停解析,域名注册已关闭。请重新验证续费付款信息。"),
|
||||
("AWS domain renewal failed", "We could not charge your AWS account "
|
||||
"before the domain was suspended due to registration expiry."),
|
||||
("AWS 域名到期提醒", "您的 AWS 账户未扣款而域名已暂停。"),
|
||||
("[Domain expiring] AWS registration notice", "If your AWS account is suspended, "
|
||||
"please contact support. Automatic annual renewal is disabled."),
|
||||
]
|
||||
for subject, body in cases:
|
||||
with self.subTest(subject=subject):
|
||||
self.assertIsNone(synthetic(subject, body))
|
||||
|
||||
def test_domain_expiration_does_not_hide_actual_account_or_resource_risk(self):
|
||||
subject = "[Domain expiring] Registration for example.net expires on 2027-02-11"
|
||||
risks = [
|
||||
"Your AWS account has been suspended.",
|
||||
"Your AWS account has been suspended and your domain is disabled.",
|
||||
"Your AWS account associated with this domain is suspended.",
|
||||
"Your AWS account for this domain is suspended.",
|
||||
"Your AWS account is restricted.",
|
||||
"Your AWS account is disabled.",
|
||||
"Your AWS account has been terminated.",
|
||||
"Your AWS account is closed.",
|
||||
"Your access key has been compromised. AWS security notification.",
|
||||
"Your AWS resource has been implicated in hosting a phishing website.",
|
||||
"We detected potentially unwanted activity in your AWS account.",
|
||||
"AWS verification: Please upload your identity documents.",
|
||||
"AWS: If you fail to respond, your account will be suspended.",
|
||||
"您的 AWS 账户已受限。",
|
||||
"您的 AWS 账户已暂停。请提交身份证明材料。",
|
||||
"AWS: Please delete malicious content hosted on your resource.",
|
||||
]
|
||||
for body in risks:
|
||||
with self.subTest(body=body):
|
||||
self.assertIsNotNone(synthetic(subject, body))
|
||||
for risk_subject in ("AWS Abuse Report", "AWS Suspicious Activity",
|
||||
"AWS Account Permanent Closure Confirmation"):
|
||||
with self.subTest(subject=risk_subject):
|
||||
self.assertIsNotNone(synthetic(risk_subject, subject))
|
||||
|
||||
def test_generic_verification_and_expiry_notices_are_not_ban_alerts(self):
|
||||
cases = [
|
||||
("AWS identity verification", "Your verification session expires on 2027-02-11."),
|
||||
("AWS domain security verification", "Verify your domain ownership."),
|
||||
("AWS renewal verification", "Please verify your billing information."),
|
||||
("AWS 域名验证", "请验证域名所有权。"),
|
||||
("AWS certificate verification required", "Your SSL certificate for domain example.com "
|
||||
"expires on 2026-10-17. Please renew the certificate."),
|
||||
("AWS credentials verification required", "Your credentials for domain example.com "
|
||||
"expire on 2026-10-17. Please rotate credentials."),
|
||||
("AWS certificate verification required", "Your domain certificate expires on "
|
||||
"2026-10-17. Please renew the certificate."),
|
||||
("AWS certificate verification required", "Your certificate for your domain "
|
||||
"example.com expires on 2026-10-17. Please renew the certificate."),
|
||||
("AWS certificate verification", "Registration for certificate expires on "
|
||||
"2026-10-17. Please renew the certificate."),
|
||||
("AWS certificate verification", "Your certificate registration for example.com "
|
||||
"expires on 2026-10-17. Please renew the certificate."),
|
||||
("AWS 证书风险通知", "域名 example.com 的 SSL 证书将于 2026-10-17 到期,请更新证书。"),
|
||||
("AWS 凭据风险通知", "域名 example.com 的登录凭据将于 2026-10-17 到期,请更新凭据。"),
|
||||
]
|
||||
for subject, body in cases:
|
||||
with self.subTest(subject=subject):
|
||||
self.assertIsNone(synthetic(subject, body))
|
||||
|
||||
def test_access_validated_notices_are_filtered(self):
|
||||
cases = [
|
||||
("您访问 AWS 资源的请求已得到验证", "您的 AWS 资源访问请求已完成核验,现在可以访问资源。", False),
|
||||
("AWS: Your Request For Accessing AWS Resources Has Been Validated",
|
||||
"The request is complete. You may access AWS resources.", False),
|
||||
("Fw: 您访问 AWS 资源的请求已得到验证 / "
|
||||
"Your Request For Accessing AWS Resources Has Been Validated",
|
||||
"AWS 资源访问现已恢复。如果您有任何问题,请联系支持。", False),
|
||||
("Fwd: AWS notification", "Forwarded message:\nSubject: Your Request For Accessing "
|
||||
"AWS Resources Has Been Validated\nYou may access resources again.", False),
|
||||
("FW: AWS notification", "<div>Your Request For Accessing</div><p>AWS Resources "
|
||||
"Has Been Successfully Validated</p><p>You may access AWS resources.</p>", True),
|
||||
("Fw: AWS 通知", "<p>您访问 AWS 资源的请求已得到验证</p><p>现在可以访问资源。</p>", True),
|
||||
]
|
||||
for subject, body, rich in cases:
|
||||
with self.subTest(subject=subject, rich=rich):
|
||||
self.assertIsNone(synthetic(subject, body, rich))
|
||||
|
||||
def test_success_notice_does_not_hide_actual_risk_or_required_documents(self):
|
||||
success = "Your Request For Accessing AWS Resources Has Been Validated"
|
||||
risks = [
|
||||
"Your AWS account has been suspended.",
|
||||
"Your AWS account is restricted.",
|
||||
"Your AWS account is disabled.",
|
||||
"Your AWS account has been terminated.",
|
||||
"Your AWS account is closed.",
|
||||
"Your access key has been compromised.",
|
||||
"Your AWS resource has been implicated in hosting a phishing website.",
|
||||
"We detected potentially unwanted activity in your AWS account.",
|
||||
"Please upload your identity documents.",
|
||||
"If you fail to respond, your account will be suspended.",
|
||||
"您的 AWS 账户已受限。",
|
||||
"您的账户已暂停。请提交身份证明材料。",
|
||||
]
|
||||
for body in risks:
|
||||
with self.subTest(body=body):
|
||||
self.assertIsNotNone(synthetic(success, body))
|
||||
for subject in ("AWS Abuse Report", "AWS Suspicious Activity", "AWS Account Permanent Closure Confirmation"):
|
||||
with self.subTest(subject=subject):
|
||||
self.assertIsNotNone(synthetic(subject, success))
|
||||
|
||||
def test_other_validation_notices_remain_reported(self):
|
||||
cases = [
|
||||
("AWS 验证您的身份", "请上传身份证核验材料。"),
|
||||
("Your Request For Accessing AWS Resources Has Not Been Validated",
|
||||
"We could not validate important details. Please upload proof of identity."),
|
||||
("AWS notification", "Your Request For Accessing AWS Resources Has Been Validated? "
|
||||
"Your account has been placed on hold."),
|
||||
]
|
||||
for subject, body in cases:
|
||||
with self.subTest(subject=subject):
|
||||
self.assertIsNotNone(synthetic(subject, body))
|
||||
|
||||
def test_access_success_keeps_explicit_resource_risk_actions(self):
|
||||
subject = "Your Request For Accessing AWS Resources Has Been Validated"
|
||||
cases = [
|
||||
"Please take action immediately to remove phishing content from your AWS resource.",
|
||||
"Please delete malicious content hosted on your AWS resource.",
|
||||
"You must stop abusive traffic from your AWS resource.",
|
||||
"请立即删除您的 AWS 资源上的钓鱼内容。",
|
||||
"必须停止 AWS 资源上的滥用行为。",
|
||||
]
|
||||
for body in cases:
|
||||
with self.subTest(body=body):
|
||||
self.assertIsNotNone(synthetic(subject, body))
|
||||
|
||||
def test_access_success_security_tips_are_still_filtered(self):
|
||||
subject = "Your Request For Accessing AWS Resources Has Been Validated"
|
||||
cases = [
|
||||
"If you find phishing content, please remove phishing content from your AWS resource.",
|
||||
"If you have questions, please take action to contact AWS support.",
|
||||
"如果您发现钓鱼内容,请立即删除 AWS 资源上的钓鱼内容。",
|
||||
"如果您有任何问题,请联系支持团队。",
|
||||
"Please contact AWS support if you need help accessing resources.",
|
||||
]
|
||||
for body in cases:
|
||||
with self.subTest(body=body):
|
||||
self.assertIsNone(synthetic(subject, body))
|
||||
|
||||
def test_login_codes_with_security_boilerplate_are_filtered(self):
|
||||
cases = [
|
||||
@@ -212,12 +296,12 @@ class ExtractionTests(unittest.TestCase):
|
||||
cases = [
|
||||
("AWS verification code", "Your verification code is 987654. Use this code to sign in.\n"
|
||||
"If you think your access key has been compromised, change your password and enable MFA."),
|
||||
("AWS 验证码", "您的验证码是 987654,用于登录。\n如果您的账户已暂停,请联系支持。"),
|
||||
("AWS verification code", "Your verification code is 987654. Use this code to sign in. "
|
||||
"If your account is suspended, please submit identity documents to support."),
|
||||
("AWS verification code", "Your verification code is 987654. Use this code to sign in. "
|
||||
"If you need help, please provide identity documents to support."),
|
||||
("AWS 验证码", "验证码 987654,用于登录。如果您需要帮助,请提交身份证材料给支持团队。"),
|
||||
("AWS 验证码", "您的验证码是 987654,用于登录。\n如果您的账户已暂停,请联系支持。"),
|
||||
("AWS verification code", "Your verification code is 987654. Use this code to sign in. "
|
||||
"If your account is suspended, please submit identity documents to support."),
|
||||
("AWS verification code", "Your verification code is 987654. Use this code to sign in. "
|
||||
"If you need help, please provide identity documents to support."),
|
||||
("AWS 验证码", "验证码 987654,用于登录。如果您需要帮助,请提交身份证材料给支持团队。"),
|
||||
]
|
||||
for subject, body in cases:
|
||||
with self.subTest(subject=subject):
|
||||
@@ -239,12 +323,12 @@ class ExtractionTests(unittest.TestCase):
|
||||
("AWS verification code", english_code +
|
||||
"If you do not upload documents by 2026-10-10, your account will be suspended."),
|
||||
("AWS 验证码", "验证码 987654,用于登录。如果您未能在截止日期回复您的账号将被暂停。"),
|
||||
("AWS verification code", english_code +
|
||||
"Your access key has been compromised. If your account is suspended, contact support."),
|
||||
("AWS verification code", english_code +
|
||||
"If you need help, please provide identity documents to support, your account has been suspended."),
|
||||
("AWS verification code", english_code +
|
||||
"If you need help, please provide identity documents to support. Please upload proof of identity."),
|
||||
("AWS verification code", english_code +
|
||||
"Your access key has been compromised. If your account is suspended, contact support."),
|
||||
("AWS verification code", english_code +
|
||||
"If you need help, please provide identity documents to support, your account has been suspended."),
|
||||
("AWS verification code", english_code +
|
||||
"If you need help, please provide identity documents to support. Please upload proof of identity."),
|
||||
]
|
||||
for subject, body in cases:
|
||||
with self.subTest(subject=subject, body=body):
|
||||
@@ -266,13 +350,13 @@ class ExtractionTests(unittest.TestCase):
|
||||
self.assertEqual(report.splitlines(), ["【AWS账号风控邮件】", "风险类型:账户验证或暂停",
|
||||
"截止时间:2026-10-10"])
|
||||
|
||||
def test_complete_report_keeps_field_order(self):
|
||||
def test_complete_report_keeps_field_order(self):
|
||||
record = synthetic("AWS Account on Hold: Response Required",
|
||||
"AWS Account ID: 123456789012\nYour account has been placed on hold.\n"
|
||||
"Resource i-12345678\nPlease reply before 2026-10-10.")
|
||||
self.assertEqual(record["account"], "123456789012")
|
||||
self.assertEqual(record["resources"], "i-12345678")
|
||||
report = check_mail.format_report(record, ZoneInfo("Asia/Shanghai"))
|
||||
"Resource i-12345678\nPlease reply before 2026-10-10.")
|
||||
self.assertEqual(record["account"], "123456789012")
|
||||
self.assertEqual(record["resources"], "i-12345678")
|
||||
report = check_mail.format_report(record, ZoneInfo("Asia/Shanghai"))
|
||||
self.assertEqual([line.split(":", 1)[0] for line in report.splitlines()],
|
||||
["【AWS账号风控邮件】", "收件时间", "邮件主题", "AWS账号ID", "风险类型",
|
||||
"警告信息", "涉及资源", "要求操作", "截止时间"])
|
||||
|
||||
Reference in New Issue
Block a user