No description
  • Python 97.5%
  • Dockerfile 2.5%
Find a file
2026-07-29 07:41:35 +00:00
.dockerignore SNDS Slack export 2026-07-29 07:41:35 +00:00
.env.example SNDS Slack export 2026-07-29 07:41:35 +00:00
.gitignore SNDS Slack export 2026-07-29 07:41:35 +00:00
Dockerfile SNDS Slack export 2026-07-29 07:41:35 +00:00
README.md SNDS Slack export 2026-07-29 07:41:35 +00:00
snds_to_slack.py SNDS Slack export 2026-07-29 07:41:35 +00:00

snds-to-slack

Pulls the Microsoft Smart Network Data Services daily data export and posts a digest to Slack.

The container runs once and exits — scheduling belongs to cron, a systemd timer, or a k8s CronJob.

Message

One message per run, one line per IP:

SNDS report 2026-07-28

:large_yellow_circle: zoo  168.119.192.202  YELLOW  (3102,2204,2201,0.1)
:red_circle: smukfest  168.119.192.207  RED  (6014,2261,2944,0.1)

The name before the IP is the first label of its PTR record (frieda.hetzner.venuemanager.net → frieda), falling back to the IP if no PTR resolves. The tuple is (RCPT commands, DATA commands, message recipients, complaint rate). Complaint rate < 0.1% is reported as 0.1.

Routing

The complete message always goes to SLACK_CHANNEL_GREEN. If any IP in the export is YELLOW, RED, or an unrecognised status, the same complete message also goes to SLACK_CHANNEL_RED. If both variables name the same channel, it is posted once.

Configuration

Copy .env.example to .env and fill it in:

Variable Required Purpose
SNDS_KEY yes Automated Data Access key from the SNDS portal
SLACK_WEBHOOK_URI yes Incoming webhook URL
SLACK_CHANNEL_GREEN yes Channel that receives every report
SLACK_CHANNEL_RED yes Channel that additionally receives non-GREEN reports
SLACK_NAME no Bot display name, defaults to SNDS

The channel and username overrides in the payload only take effect on a legacy Incoming Webhook. A webhook created through a modern Slack app is bound to one channel and will ignore both — in that case use two webhooks or a legacy one.

Environment variables take precedence over .env, so docker run --env-file works either way.

Running

docker build -t snds-to-slack .

# print the message and target channels, post nothing
docker run --rm --env-file .env snds-to-slack --dry-run

# post for real
docker run --rm --env-file .env snds-to-slack

Without Docker: python3 snds_to_slack.py --dry-run (Python 3.9+, no dependencies).

Scheduling

The SNDS reporting window closes at 09:00 UTC, so run shortly after:

5 10 * * * docker run --rm --env-file /home/rune/development/snds-to-slack/.env snds-to-slack

Exit codes

Code Meaning
0 Posted, or the export was empty (nothing is posted on an empty export)
1 Could not fetch SNDS data, or a Slack post failed
2 Missing required configuration

As of 2026 SNDS Automated Data Access keys expire after roughly 30 days. A sudden run of exit-code-1 failures usually means an expired SNDS_KEY rather than an outage — regenerate it in the SNDS portal.

Testing

SNDS_TEST_FILE=/path/to/sample.csv reads the export from a local file instead of the network, which makes the all-GREEN and malformed-row paths testable without live data.