Description

Detects potential reconnaissance messages with very short, generic content like 'Hi' or 'Hello' from external senders. These messages are often used to validate email addresses and test deliverability before launching larger attacks.

References

No references.

Sublime Security
Created Sep 5th, 2025 • Last updated Jun 17th, 2026
Source
type.inbound
// detect generic greetings
and length(body.current_thread.text) <= 20
and length(subject.base) <= 15
// exclude messages with previous thread context (forwards/replies)
and length(body.previous_threads) == 0
and (
  any(ml.nlu_classifier(body.current_thread.text).entities, .name == "greeting")
  or strings.ilike(body.current_thread.text, "*hi*", "*hello*", "*hey*")
  or length(body.current_thread.text) <= 5
  or regex.match(body.current_thread.text, '\d+')
)
// external freemail sender
and sender.email.domain.root_domain in $free_email_providers
and (
  sender.email.domain.root_domain not in (
    recipients.to[0].email.domain.root_domain
  )
  or (
    (
      all(recipients.to, .email.domain.valid == false)
      and all(recipients.cc, .email.domain.valid == false)
    )
    or length(recipients.to) == 0
  )
)
and (
  length(recipients.cc) == 0
  or (
    length(recipients.cc) > 0
    and all(recipients.cc,
            .email.domain.root_domain != sender.email.domain.root_domain
    )
  )
)
and (
  length(recipients.bcc) == 0
  or (
    length(recipients.bcc) > 0
    and all(recipients.bcc,
            .email.domain.root_domain != sender.email.domain.root_domain
    )
  )
)
// no attachments or links
and length(attachments) == 0
and length(body.current_thread.links) == 0

// not where the sender and mailbox display_anames indicate this might be a personal email --> work email
// impersonation is covered by other core feed rules
and not (
  sum([length(recipients.to), length(recipients.bcc), length(recipients.cc)]) == 1
  // use coalesce to deal with either the sender.display_name or the mailbox element being null
  // if either are null, the function returns false, as it cannot be true if either is null
  and coalesce(strings.icontains(sender.display_name, mailbox.first_name),
               false
  )
  and coalesce(strings.icontains(sender.display_name, mailbox.last_name), false)
)
and (
  // auth failed (or absent) - ignore the profile
  coalesce(headers.auth_summary.dmarc.pass, false) == false
  or coalesce(headers.auth_summary.spf.pass, false) == false
  // auth passed - use the profile
  or (
    // no benign messages
    not profile.by_sender_email().any_messages_benign
    and (
      // not soliticed OR common
      not (
        profile.by_sender_email().solicited
        or profile.by_sender_email().prevalence == "common"
      )
      // or HAS been spam_malicious
      or profile.by_sender_email().any_messages_malicious_or_spam
    )
  )
)
MQL Rule Console
DocsLearning Labs

Playground

Test against your own EMLs or sample data.

Share

Post about this on your socials.

Get Started. Today.

Managed or self-managed. No MX changes.

Deploy and integrate a free Sublime instance in minutes.
Get Started