{"id":647,"date":"2018-07-18T22:18:30","date_gmt":"2018-07-18T22:18:30","guid":{"rendered":"http:\/\/blog3.canny.io\/wordpress\/?p=647"},"modified":"2026-06-02T21:32:56","modified_gmt":"2026-06-03T01:32:56","slug":"defending-your-startup-against-email-spammers","status":"publish","type":"post","link":"https:\/\/canny.io\/blog\/defending-your-startup-against-email-spammers\/","title":{"rendered":"Defending your early-stage SaaS startup against email spam"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Last week seemed like an ordinary week. As ordinary as it gets while traveling the world and bootstrapping a startup. Until the email spammers showed up.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We started getting some strange emails in our inbox:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1273\" height=\"510\" src=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/first-spam-email.avif\" alt=\"\" class=\"wp-image-662\" srcset=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/first-spam-email.avif 1273w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/first-spam-email-300x120.avif 300w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/first-spam-email-768x308.avif 768w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/first-spam-email-210x84.avif 210w\" sizes=\"auto, (max-width: 1273px) 100vw, 1273px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What\u2019s this about? I plugged it into Google translate out of curiosity. It\u2019s an automated response. The recipient is on vacation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cool, someone in China is trying Canny out! They invited a teammate to their team, and they\u2019re on vacation. No big deal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But then the next day I woke up to a dozen more emails like this:<\/p>\n\n\n<div class=\"wp-block-image wp-image-658 size-full\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"2308\" height=\"1246\" src=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-inbox.avif\" alt=\"\" class=\"wp-image-658\" srcset=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-inbox.avif 2308w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-inbox-300x162.avif 300w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-inbox-768x415.avif 768w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-inbox-1800x972.avif 1800w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-inbox-210x113.avif 210w\" sizes=\"auto, (max-width: 2308px) 100vw, 2308px\" \/><figcaption class=\"wp-element-caption\">This snazzy email client is <a href=\"https:\/\/missiveapp.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Missive<\/a><\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Okay, what\u2019s going on? If this many people are sending automated responses, how many emails are they sending?!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I did a quick database query to count teammate invites. My heart sank. They had sent 80k over the past week. Holy heck. We\u2019re under attack. They\u2019re programmatically sending thousands of HTTP requests which are resulting in us sending emails.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But why? Why would someone want to invite random people to their team on Canny? What\u2019s in it for them? Are they just having fun? Ugh.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That\u2019s what I thought at first. Then I took a look at one of the emails they sent:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1376\" height=\"1058\" src=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-email-example.avif\" alt=\"\" class=\"wp-image-653\" srcset=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-email-example.avif 1376w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-email-example-300x231.avif 300w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-email-example-768x591.avif 768w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-email-example-1332x1024.avif 1332w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/spam-email-example-156x120.avif 156w\" sizes=\"auto, (max-width: 1376px) 100vw, 1376px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That\u2019s a weird company name. That doesn\u2019t look legit at all.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I shared it with a teammate who can read Chinese. He instantly identified it as spam. They\u2019re telling people to join a QQ group to get discounts on online gambling.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They\u2019re using Canny to send people email spam. We pay to send their emails. We take the deliverability hit when people mark our emails as spam. Oh hell no, I don\u2019t think so!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Stopping the Attack<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We took a few immediate steps to stop the attack.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, we deleted their Canny account. This way their requests would fail instead of triggering emails. We found a small handful of user and company accounts associated with this bad behavior. We removed them all.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, we blacklisted their IP address. They were sending every HTTP request from the same IP address. We simply added it to our blacklist in AWS WAF (Web Application Firewall). Their requests could no longer hit our servers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At this point, they would have to create a new account, and use a different IP address to start the attack again. This isn\u2019t too hard, but buys us time to think about how to avoid this attack in the long term.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Finding an 80\/20 Solution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We\u2019re an early-stage startup. We don\u2019t have a team of security engineers to devote weeks to this. Every minute spent protecting ourselves is a minute that could have been spent on growth.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That\u2019s why it was important that we find an 80\/20 solution. Something good enough to make Canny an undesirable target, but nothing more. No over-engineering.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We put ourselves in the shoes of the attacker. We realized that picking which SaaS you want to send your email spam is a lot like picking which bike to steal.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1800\" height=\"837\" src=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/steal-bike.avif\" alt=\"\" class=\"wp-image-654\" srcset=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/steal-bike.avif 1800w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/steal-bike-300x140.avif 300w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/steal-bike-768x357.avif 768w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/steal-bike-210x98.avif 210w\" sizes=\"auto, (max-width: 1800px) 100vw, 1800px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nicer bikes are more valuable, but have more protection. The thief must optimize for the nicest bike with the least amount of protection.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As long as your bike has at least as much protection as other similarly valued bikes, it won\u2019t get stolen. This is because there are easier targets \u2013 the thief can make more money with less effort.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This makes it clear why early-stage SaaS apps are a target for email spammers: they\u2019re an easier target. They have fewer resources to invest into security than big companies.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So how do we make our SaaS harder to attack?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Block Obvious Attacks From Email Spammers<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Some behavior is obviously malicious. For example, someone sending requests faster than humanly possible. This can easily be blocked using rate-based rules in AWS WAF.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But you have to be careful. You don\u2019t want to block a paying customer from doing something legitimate. You have to be thoughtful about what you can and can\u2019t block.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We made a list of obviously bad behavior and blocked it all via either AWS WAF or our server application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Better Awareness<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The attack went on for several days before we even realized we were under attack. In that time they significantly ramped up volume. They probably thought we hadn\u2019t noticed, so they could send more. They were right.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we can immediately realize when we\u2019re under attack, and act, this minimizes attacks. It also shows attackers we\u2019re on to them. They\u2019ll probably move on to another target then and there.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We created a new #fraud thread in Twist. We made a list of suspicious events, like a user sending more than 10 team invites in a day. Whenever this happens, the server pings our #fraud thread.<\/p>\n\n\n<div class=\"wp-block-image wp-image-670 size-full\">\n<figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"2462\" height=\"1279\" src=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/twist-fraud-detection.avif\" alt=\"\" class=\"wp-image-670\" srcset=\"https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/twist-fraud-detection.avif 2462w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/twist-fraud-detection-300x156.avif 300w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/twist-fraud-detection-768x399.avif 768w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/twist-fraud-detection-1800x935.avif 1800w, https:\/\/canny.io\/blog\/wp-content\/uploads\/2018\/07\/twist-fraud-detection-210x109.avif 210w\" sizes=\"auto, (max-width: 2462px) 100vw, 2462px\" \/><figcaption class=\"wp-element-caption\">Our team uses <a href=\"https:\/\/twist.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Twist<\/a> for team communication<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">This behavior could be legit: maybe someone is inviting their entire team. That\u2019s why we chose to send notifications for these events instead of outright blocking them. They warrant a quick manual review, but aren\u2019t necessarily bad.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"hs-cta-embed hs-cta-embed-127905612377\" style=\"max-width:100%; max-height:100%; width:650px;height:313.4505275px; display:block; margin: 0 auto;\" data-hubspot-wrapper-cta-id=\"127905612377\"> <link rel=\"stylesheet\" href=\"https:\/\/js.hscta.com\/embeddable_cta_placeholder_v1.css\"> <div class=\"hs-cta-loading-dot__container\"> <div class=\"hs-cta-loading-dot\"><\/div> <div class=\"hs-cta-loading-dot\"><\/div> <div class=\"hs-cta-loading-dot\"><\/div> <\/div> <div class=\"hs-cta-embed__skeleton\"><\/div> <picture> <source srcset=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" media=\"(max-width: 480px)\"> <img decoding=\"async\" alt=\"Form CTA\" loading=\"lazy\" src=\"https:\/\/no-cache.hubspot.com\/cta\/default\/5705808\/interactive-127905612377.png\" style=\"height: 100%; width: 100%; object-fit: fill\" onerror=\"this.style.display='none'\"> <\/picture> <\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Lessons Learned<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I hope you enjoyed our story. It was definitely unexpected and stressful, but we came out of it smarter and stronger.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you work at an early-stage SaaS company, or someday want to, here\u2019s a quick list of the most important takeaways:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>As an early-stage SaaS company, you are a target. You have less security than your larger peers. Think especially hard if you have a free tier\/trial and send emails that contain user generated content.<\/li>\n\n\n\n<li>Awareness is crucial \u2013 know when you\u2019re being attacked. Think about how people might attack you, and what would make you aware that it\u2019s happening. It\u2019ll probably only take a few minutes.<\/li>\n\n\n\n<li>Don\u2019t over-engineer. It\u2019s easy to dream up the perfect solution to every fraud problem you\u2019ll ever have. Don\u2019t. Your time is valuable. Find a solution that delivers 80% of the value in 20% of the time.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Thanks for reading. If you\u2019d like to share some security best practices, leave a comment below!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last week seemed like an ordinary week until we started getting some strange emails in our inbox.<\/p>\n","protected":false},"author":3,"featured_media":666,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"content-type":"","_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[2],"tags":[],"class_list":["post-647","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-building-saas"],"aioseo_notices":[],"modified_by":"Eric Hoppe","_links":{"self":[{"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/posts\/647","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/comments?post=647"}],"version-history":[{"count":24,"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/posts\/647\/revisions"}],"predecessor-version":[{"id":11379,"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/posts\/647\/revisions\/11379"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/media\/666"}],"wp:attachment":[{"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/media?parent=647"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/categories?post=647"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/canny.io\/blog\/wp-json\/wp\/v2\/tags?post=647"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}