How likely would you be to block a company from asking you to rate everything they do?

Very, it turns out...

It feels like you can’t even buy a coffee these days without being asked if you would recommend the coffee shop to a friend or colleague.

  • “How likely would you be to recommend us to a friend or colleague?”
  • “Rate our service from 1-10”
  • “How did we do?”
  • “How was your experience?”

It’s a simple question, and it’s a simple score.

It’s also a simple way to annoy your customers and end up in their spam folder.


NPS stands for Net Promoter Score.

The idea is that you ask your customers to rate your product, service or experience from 0-10, and then you subtract the percentage of detractors (0-6) from the percentage of promoters (9-10) to get your NPS score. For example, if 50% of your customers are promoters and 10% are detractors, your NPS is 40.

Companies like to use (abuse?) this to measure customer satisfaction and make their customers feel like they listened to and that their opinion matters.

There are many problems with this highly reductive and impersonal MBE style approach but the one that annoys me the most is that it’s essentially created a new form of corporate spam.


I’ve had a crack at writing some advanced email rules to filter these out to a folder - it’s far from perfect but it’s a start.

The following Sieve script (rather unintelligently) filters out NPS surveys from a combination of keywords in the body and headers and moves them from your inbox to a folder of your choice.

This script should work with any mail service / server that supports standard Sieve scripts, I use this with Fastmail (or if you feel like it you can optionally use my referral link ).

Fastmail offers a Sieve testing tool you can use to test your script before you apply it to your account.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# uncomment if testing with Fastmail's test page or similar
# require ["variables", "body", "fileinto"];

######### Sam's Sieve rules for Customer Satisfaction Spam #########
# The current logic is:
# 1. If the sender is in the allowlist, skip the rest of the rules
# 2. If the message subject matches any of the immediate match phrases, move it immediately
# 3. If the message subject matches any of the subject / header phrases AND any of the body phrases, move it
###################################################################

# :contains = substring match
# :matches = regex glob matching
# :comparator "i;ascii-casemap" = case insensitive

if not anyof(
    # If the sender matches any of these conditions, skip the rest of the rules

    # Check if From address is in the allowlist # TODO - see below
    #address :matches "From" ["*${allowlist_emails}*"],
    #address :matches "From" ["*${allowlist_domains}*"],
    #header :matches "Subject" ["*${allowlist_words}*"]

    address :matches "From" ["*@alloweddomain1.com", "*@alloweddomain2.com"]

) {
  if anyof(
    # If the message matches ANY of the following header subjects, move it immediately

    #header :contains :comparator "i;ascii-casemap" "Subject" ["*${immediateMatch}*"],
    header :contains :comparator "i;ascii-casemap" "Subject" [
      "How would you rate the support you received",
      "What do you think about your store experience",
      "What do you think about your purchase products",
      "Take a few minutes to share your feedback",
      "We value your feedback",
      "Your feedback is important",
      "We would love your feedback",
      "Rate your purchases",
      "Rate your other purchases",
      "How likely are you to recommend"
      ],
    header :matches :comparator "i;ascii-casemap" "Subject" [
      "*We?d love to hear how your*",
      "*Help us*improve by rating*"
      ],

    allof(
        # or, if the message matches any these header and subject conditions - AND - any of the body conditions in the next section
        anyof(
            header :contains "Precedence" "bulk",
            header :contains "Auto-Submitted" "auto-replied",
            header :contains "X-Auto-Response-Suppress" "OOF",
            header :contains "X-Autogenerated" "yes",
            header :contains "X-Autorespond" "yes",
            header :contains "X-ME-CMCategory" "promotion",
            header :contains "X-ME-VSCategory" "commercial:mce",
            header :contains "X-Mailer" [
              "survey",
              "feedback"
              ],
            header :contains :comparator "i;ascii-casemap" "From" [
              "survey",
              "feedback"
              ],
            header :contains :comparator "i;ascii-casemap" "List-Unsubscribe" [
              "mailto:",
              "unsubscribe",
              "opt-out",
              "click here",
              "manage preferences",
              "update preferences"
              ]
        ),
        # and again - this time in the body body
        anyof(
            # Check if the subject matches any of these conditions
            header :contains :comparator "i;ascii-casemap" "Subject" [
              "Are you happy with the response you",
              "Are you happy with the service you",
              "Are you happy with the support you",
              "Click below to rate",
              "Complete our survey",
              "customer feedback",
              "customer survey",
              "Did I solve your problem",
              "Did your recent purchase go well?",
              "give us 5 stars",
              "give us your feedback",
              "how are we doing",
              "How did we do",
              "How likely are you to recommend",
              "How likely would you be to recommend",
              "how satisfied were you",
              "how was the support",
              "How would you rate",
              "If you do not wish to participate in",
              "Please rate our support",
              "provide feedback",
              "Rate your experience",
              "share your feedback",
              "tell us how we did",
              "We want your opinion",
              "We'd love your feedback",
              "What do you think of your purchase",
              "your feedback is important",
              "We value your feedback",
              "Rate your other purchases",
              "Rate your purchases",
              "bazaarvoice.com"
              ],
            header :matches :comparator "i;ascii-casemap" "Subject" [
              "*Are you happy with the * you * \?*",
              "*rate ??? support*",
              "*Help us*improve by rating*",
              "*Did * solve your problem*"
            ]
        ),
        # and again - this time in the body body
        anyof(
            body :contains :comparator "i;ascii-casemap" [
              "Click below to rate",
              "Complete our survey",
              "customer feedback",
              "customer survey",
              "give us 5 stars",
              "give us your feedback",
              "how are we doing",
              "How did we do",
              "How likely are you to recommend",
              "How likely would you be to recommend",
              "how satisfied were you",
              "how was the support",
              "How would you rate",
              "If you do not wish to participate in",
              "Please rate our support",
              "provide feedback",
              "Rate your experience",
              "share your feedback",
              "tell us how we did",
              "We want your opinion",
              "We'd love your feedback",
              "We would love your feedback",
              "What do you think of your purchase",
              "Did your recent purchase go well?",
              "your feedback is important",
              "We value your feedback",
              "Rate your other purchases",
              "Rate your purchases",
              "bazaarvoice.com"
            ],
            body :matches :comparator "i;ascii-casemap" [
              "*Are you happy with the * you * \?*",
              "*rate ??? support*",
              "*Help us*improve by rating*",
              "*Did * solve your problem*",
              "*We would love your feedback*"
            ]
        )
      )
    )
      {
        # Move the message to "Customer Satisfaction Spam" folder
        fileinto "Customer Satisfaction Spam";
    }
}


###TODO: These variables weren't working as expected.  Need to figure out why.
# Define any allowlist items (email addresses, domains, words) here
# set "allowlist_emails" "[email protected],[email protected]";
# Define any phrases that should be considered likely to be customer satisfaction surveys
# set "bodyPatterns" "TODO!"
# This time for the subject
# set "subjectPatterns" "TODO!"
# set "allowlist_domains" "@alloweddomain.com";
# set "allowlist_words" "allowedword";
# Define any phrases that should trigger immediate filing into the "Customer Satisfaction Spam" folder
# set "immediateMatch" "[How likely are you to recommend us to a friend or colleague,How would you rate the support you received,What do you think about your store experience,What do you think about your purchase products,Take a few minutes to share your feedback]";
### end TODO ###

Click here to find the latest version of this script and please do raise PRs to improve it!

There’s plenty of room for improvement here, e.g.:

  • Additional matching keywords / phrases.
  • Check if sender is in your address book (Not currently possible with Fastmail’s Sieve extensions).
  • Use an upstream list of keywords, phrases and domains rather than hardcoding them (Not sure if this is possible with Sieve?).
  • Automate updating the ruleset.