SESWatcher : how to prevent Amazon SES account from being suspended

Introdution

At this moment, AWS SES service is the best affordable price and high-quality service to sending (and receiving) programmatic emails. But, one day your account could be suspended without notice, and that takes a big effort of requesting support to get it back to work.

So it’s good to prevent that siatuation happens by watching your Bounces Rate and Complaints Rate. One way to resolve problem when your rates being too-high than allowance, is send a big amount of dummy emails to your blackhole email address.

Example

These is your send statistics :

  • Deliveries : 2000
  • Bounces : 180 ==> Bounces Rate : 180 / 2000 = 9%
  • Complaints : 30 ==> Complaints Rate : 30 / 2000 = 1.5%

Meaning :

  • Bounces : when your email didn’t send to existed email address (maybe your user type wrong or input fake one), we can pre-validate email before sending by using some email validator library or services like fast-email-validator
  • Complaints : when your receiver mark your email as SPAM :( Poor you !!!

Solution

AWS SES rules :

  • Bounces Rate : 5% => So you have to send more (180 / 4%) - 2000 = 2500 emails to reduce Bounces Rate to 4%
  • Complaints Rate : 0.1% => So you have to send more (30 / 0.07%) - 2000 = 40857 emails to reduce Complaints Rate to 0.07%

==> Number emails send = max(2500, 40857) = 40857 emails

SPAM YOURSELF 40857 EMAILS !!! 😂

SESWatcher - Your SES watchman

It’s open source software at https://github.com/khanhicetea/seswatcher (My first PyPi package :D)

Installation

1
$ pip install seswatcher

Usage

  1. Step 1 : Get AWS Credential User within AmazonSESFullAccess policy
  2. Step 2 : Verify sender email in AWS SES
  3. Step 3 : Get a blackhole email address which receives un-important emails.
  4. Step 4 : Create a hourly cronjob that runs seswatcher
1
$ seswatcher [OPTIONS] ACCESS_KEY SECRET_KEY FROM_EMAIL TO_EMAIL

Get help :

1
2
3
4
5
6
7
$ seswatcher --help
Usage: seswatcher [OPTIONS] ACCESS_KEY SECRET_KEY FROM_EMAIL TO_EMAIL

Options:
--region TEXT AWS SES Region (default is us-east-1)
--interval INTEGER Timer interval
--help Show this message and exit.

Reading NFC Card ID on Ubuntu

Prerequisites

Install driver

My device is ACS122U : http://www.acs.com.hk/en/products/3/acr122u-usb-nfc-reader/#tab_downloads

Kernel modules

1
2
3
# echo "uinput" >> /etc/modules
# echo "install nfc /bin/false" >> /etc/modprobe.d/blacklist.conf
# echo "install pn533 /bin/false" >> /etc/modprobe.d/blacklist.conf

Install packages

1
sudo apt-get install swig libccid pcscd libpcsclite-dev libpcsclite1 python-dev python-pip gcc linux-headers-$(uname -r)

Run service

1
sudo service pcscd restart

Install python packages

1
sudo pip install pyscard python-uinput evdev

Source code

This is source code that read the card ID and simulate keystrokes to type card ID by text then pressing ENTER key.

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
#! /usr/bin/env python

from __future__ import print_function
from time import sleep

from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
from smartcard.CardMonitoring import CardMonitor, CardObserver
from smartcard.util import toHexString
from evdev import UInput, ecodes
import uinput


device = uinput.Device([uinput.KEY_0, uinput.KEY_1, uinput.KEY_2, uinput.KEY_3, uinput.KEY_4, uinput.KEY_5, uinput.KEY_6, uinput.KEY_7, uinput.KEY_8, uinput.KEY_9, uinput.KEY_A, uinput.KEY_B, uinput.KEY_C, uinput.KEY_D, uinput.KEY_E, uinput.KEY_F, uinput.KEY_G, uinput.KEY_H, uinput.KEY_I, uinput.KEY_J, uinput.KEY_K, uinput.KEY_L, uinput.KEY_M, uinput.KEY_N, uinput.KEY_O, uinput.KEY_P, uinput.KEY_Q, uinput.KEY_R, uinput.KEY_S, uinput.KEY_T, uinput.KEY_U, uinput.KEY_V, uinput.KEY_W, uinput.KEY_X, uinput.KEY_Y, uinput.KEY_Z, uinput.KEY_TAB])


def card_id_to_keyboards(card_id):
id = card_id.replace(' ', '')

return [getattr(uinput, 'KEY_'+x.upper()) for x in id]


# a simple card observer that tries to select DF_TELECOM on an inserted card
class selectDFTELECOMObserver(CardObserver):
"""A simple card observer that is notified
when cards are inserted/removed from the system and
prints the list of cards
"""

def __init__(self):
self.observer = ConsoleCardConnectionObserver()

def update(self, observable, actions):
try:
(addedcards, removedcards) = actions
for card in addedcards:
print("+Inserted: ", toHexString(card.atr))
card.connection = card.createConnection()
card.connection.connect()
card.connection.addObserver(self.observer)
apdu = [0xFF, 0xCA, 0x00, 0x00, 0x00]
response, sw1, sw2 = card.connection.transmit(apdu)
keys = card_id_to_keyboards(toHexString(response))
for key in keys:
device.emit_click(key)
ui = UInput()
ui.write(ecodes.EV_KEY, ecodes.KEY_ENTER, 0)
ui.write(ecodes.EV_KEY, ecodes.KEY_ENTER, 1)
ui.syn()
ui.close()
for card in removedcards:
print("-Removed: ", toHexString(card.atr))
except:
pass

if __name__ == '__main__':
print("Insert or remove a SIM card in the system.")
print("This program will exit in 60 seconds")
print("")
cardmonitor = CardMonitor()
selectobserver = selectDFTELECOMObserver()
cardmonitor.addObserver(selectobserver)

sleep(86400)

# don't forget to remove observer, or the
# monitor will poll forever...
cardmonitor.deleteObserver(selectobserver)

import sys
if 'win32' == sys.platform:
print('press Enter to continue')
sys.stdin.read(1)

Run

1
$ sudo python main.py

Demo

This is my demo application that using card ID like a user password, so I can unlock my computer or enter sudo mode :D

It Just Works

If you want a “just-work” solution, checkout this repo. It is built on Java smartcardio.

1
$ java -jar rfid-reader2keyboard.jar

Good luck ! ;)

Read Input Data From USB Devices in Linux

Introduction

You just bought a new input device like barcode scanner, proximity card reader with USB port. And you want expose only its data to a file or send to server for processing ? But it acts like a keyboard, type the characters then trigger Enter key.

This tutorial can help you make a program can exclusive receive input data from the device and don’t affect to another program.

The program is written in Python and can run on almost Linux system (Ubuntu desktop, Raspberry Pi, Arduino, etc..)

Instruction

Install dependencies

On a Debian compatible OS:

1
2
$ apt-get install python-dev python-pip gcc
$ apt-get install linux-headers-$(uname -r)

On a Redhat compatible OS:

1
2
$ yum install python-devel python-pip gcc
$ yum install kernel-headers-$(uname -r)

On Arch Linux and derivatives:

1
$ pacman -S core/linux-api-headers python-pip gcc

Then, install evdev package via pip

1
$ sudo pip install evdev

Download program sourcecode

Copy this file and save as main.py

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
#!/usr/bin/python

import sys
from evdev import InputDevice, list_devices, ecodes, categorize

CODE_MAP_CHAR = {
'KEY_MINUS': "-",
'KEY_SPACE': " ",
'KEY_U': "U",
'KEY_W': "W",
'KEY_BACKSLASH': "\\",
'KEY_GRAVE': "`",
'KEY_NUMERIC_STAR': "*",
'KEY_NUMERIC_3': "3",
'KEY_NUMERIC_2': "2",
'KEY_NUMERIC_5': "5",
'KEY_NUMERIC_4': "4",
'KEY_NUMERIC_7': "7",
'KEY_NUMERIC_6': "6",
'KEY_NUMERIC_9': "9",
'KEY_NUMERIC_8': "8",
'KEY_NUMERIC_1': "1",
'KEY_NUMERIC_0': "0",
'KEY_E': "E",
'KEY_D': "D",
'KEY_G': "G",
'KEY_F': "F",
'KEY_A': "A",
'KEY_C': "C",
'KEY_B': "B",
'KEY_M': "M",
'KEY_L': "L",
'KEY_O': "O",
'KEY_N': "N",
'KEY_I': "I",
'KEY_H': "H",
'KEY_K': "K",
'KEY_J': "J",
'KEY_Q': "Q",
'KEY_P': "P",
'KEY_S': "S",
'KEY_X': "X",
'KEY_Z': "Z",
'KEY_KP4': "4",
'KEY_KP5': "5",
'KEY_KP6': "6",
'KEY_KP7': "7",
'KEY_KP0': "0",
'KEY_KP1': "1",
'KEY_KP2': "2",
'KEY_KP3': "3",
'KEY_KP8': "8",
'KEY_KP9': "9",
'KEY_5': "5",
'KEY_4': "4",
'KEY_7': "7",
'KEY_6': "6",
'KEY_1': "1",
'KEY_0': "0",
'KEY_3': "3",
'KEY_2': "2",
'KEY_9': "9",
'KEY_8': "8",
'KEY_LEFTBRACE': "[",
'KEY_RIGHTBRACE': "]",
'KEY_COMMA': ",",
'KEY_EQUAL': "=",
'KEY_SEMICOLON': ";",
'KEY_APOSTROPHE': "'",
'KEY_T': "T",
'KEY_V': "V",
'KEY_R': "R",
'KEY_Y': "Y",
'KEY_TAB': "\t",
'KEY_DOT': ".",
'KEY_SLASH': "/",
}

def parse_key_to_char(val):
return CODE_MAP_CHAR[val] if val in CODE_MAP_CHAR else ""

if __name__ == "__main__":
print "List of your devices :"
devices = [InputDevice(fn) for fn in list_devices()]
for device in devices:
print "\t{}\t{}".format(device.fn, device.name)

print "Choose event ID :",
event_id = raw_input()

print "Exclusive access to device ? [1 or 0] : ",
exclusive_access = raw_input()

device = InputDevice('/dev/input/event{}'.format(event_id))
if int(exclusive_access) == 1:
device.grab()

for event in device.read_loop():
if event.type == ecodes.EV_KEY:
e = categorize(event)
if e.keystate == e.key_up:
sys.stdout.write(parse_key_to_char(e.keycode))
sys.stdout.flush()

Run program with root permission

1
$ sudo python main.py

Then enter your event id of device based on device name in devices list. If you want exclusive access to that device (means no application can’t access and read the input data), press 1 or 0 to accept or deny.

This is my result, I opened the gedit and typed a paragragh but no character appears in Editor, but they’re shown in the terminal.

Read device input on Linux

Customize output data

You can rewrite the code to send data to web server

1
$ sudo pip install requests
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
#!/usr/bin/python

import sys
import requests
from evdev import InputDevice, list_devices, ecodes, categorize

CODE_MAP_CHAR = {
'KEY_MINUS': "-",
'KEY_SPACE': " ",
'KEY_U': "U",
'KEY_W': "W",
'KEY_BACKSLASH': "\\",
'KEY_GRAVE': "`",
'KEY_NUMERIC_STAR': "*",
'KEY_NUMERIC_3': "3",
'KEY_NUMERIC_2': "2",
'KEY_NUMERIC_5': "5",
'KEY_NUMERIC_4': "4",
'KEY_NUMERIC_7': "7",
'KEY_NUMERIC_6': "6",
'KEY_NUMERIC_9': "9",
'KEY_NUMERIC_8': "8",
'KEY_NUMERIC_1': "1",
'KEY_NUMERIC_0': "0",
'KEY_E': "E",
'KEY_D': "D",
'KEY_G': "G",
'KEY_F': "F",
'KEY_A': "A",
'KEY_C': "C",
'KEY_B': "B",
'KEY_M': "M",
'KEY_L': "L",
'KEY_O': "O",
'KEY_N': "N",
'KEY_I': "I",
'KEY_H': "H",
'KEY_K': "K",
'KEY_J': "J",
'KEY_Q': "Q",
'KEY_P': "P",
'KEY_S': "S",
'KEY_X': "X",
'KEY_Z': "Z",
'KEY_KP4': "4",
'KEY_KP5': "5",
'KEY_KP6': "6",
'KEY_KP7': "7",
'KEY_KP0': "0",
'KEY_KP1': "1",
'KEY_KP2': "2",
'KEY_KP3': "3",
'KEY_KP8': "8",
'KEY_KP9': "9",
'KEY_5': "5",
'KEY_4': "4",
'KEY_7': "7",
'KEY_6': "6",
'KEY_1': "1",
'KEY_0': "0",
'KEY_3': "3",
'KEY_2': "2",
'KEY_9': "9",
'KEY_8': "8",
'KEY_LEFTBRACE': "[",
'KEY_RIGHTBRACE': "]",
'KEY_COMMA': ",",
'KEY_EQUAL': "=",
'KEY_SEMICOLON': ";",
'KEY_APOSTROPHE': "'",
'KEY_T': "T",
'KEY_V': "V",
'KEY_R': "R",
'KEY_Y': "Y",
'KEY_TAB': "\t",
'KEY_DOT': ".",
'KEY_SLASH': "/",
}

def parse_key_to_char(val):
return CODE_MAP_CHAR[val] if val in CODE_MAP_CHAR else ""

if __name__ == "__main__":
print "List of your devices :"
devices = [InputDevice(fn) for fn in list_devices()]
for device in devices:
print "\t{}\t{}".format(device.fn, device.name)

print "Choose event ID :",
event_id = raw_input()

print "Exclusive access to device ? [1 or 0] : ",
exclusive_access = raw_input()

device = InputDevice('/dev/input/event{}'.format(event_id))
if int(exclusive_access) == 1:
device.grab()

data = ""
for event in device.read_loop():
if event.type == ecodes.EV_KEY:
e = categorize(event)
if e.keystate == e.key_up:
if e.keycode == "KEY_ENTER":
requests.post("https://somewhere/code/belongs", {
code: data
})
data = ""
else:
data += parse_key_to_char(e.keycode)

You can read more about evdev API here

Ref :