How to Automate Internal Announcements Across Channels
Push announcements to Slack, email, and intranet simultaneously.
Jay Banlasan
The AI Systems Guy
Internal announcements that only go to one channel get missed. I built a system to automate internal announcements across multiple channels simultaneously. Write it once, and it goes to Slack, email, and your intranet at the same time with proper formatting for each platform.
One input. Multiple outputs. Nobody misses the message.
What You Need Before Starting
- Python 3.8+
- Slack bot token
- Email SMTP credentials
- A content management system or shared drive for the intranet
Step 1: Define the Announcement Structure
from datetime import datetime
class Announcement:
def __init__(self, title, body, priority="normal", departments=None, author=""):
self.title = title
self.body = body
self.priority = priority
self.departments = departments or ["all"]
self.author = author
self.created_at = datetime.now()
self.id = f"ann-{self.created_at.strftime('%Y%m%d%H%M%S')}"
Step 2: Format for Each Channel
def format_for_slack(announcement):
emoji = {"urgent": ":rotating_light:", "normal": ":mega:", "info": ":information_source:"}
icon = emoji.get(announcement.priority, ":mega:")
return {
"blocks": [
{"type": "header", "text": {"type": "plain_text", "text": f"{icon} {announcement.title}"}},
{"type": "section", "text": {"type": "mrkdwn", "text": announcement.body}},
{"type": "context", "elements": [
{"type": "mrkdwn", "text": f"Posted by {announcement.author} | {announcement.created_at.strftime('%B %d, %Y %I:%M %p')}"}
]}
]
}
def format_for_email(announcement):
subject_prefix = "[URGENT] " if announcement.priority == "urgent" else ""
return {
"subject": f"{subject_prefix}{announcement.title}",
"body": f"{announcement.body}\n\n---\nPosted by {announcement.author} on {announcement.created_at.strftime('%B %d, %Y')}"
}
def format_for_intranet(announcement):
return {
"title": announcement.title,
"content": announcement.body,
"author": announcement.author,
"date": announcement.created_at.isoformat(),
"priority": announcement.priority,
"departments": announcement.departments
}
Step 3: Send to All Channels
import requests
import smtplib
from email.mime.text import MIMEText
import json
from pathlib import Path
def send_to_slack(formatted, channel, slack_token):
requests.post(
"https://slack.com/api/chat.postMessage",
headers={"Authorization": f"Bearer {slack_token}"},
json={"channel": channel, "blocks": formatted["blocks"]}
)
def send_to_email(formatted, recipients, smtp_config):
msg = MIMEText(formatted["body"])
msg["Subject"] = formatted["subject"]
msg["To"] = ", ".join(recipients)
with smtplib.SMTP(smtp_config["host"], smtp_config["port"]) as server:
server.starttls()
server.login(smtp_config["user"], smtp_config["password"])
server.send_message(msg)
def save_to_intranet(formatted, intranet_dir="announcements"):
Path(intranet_dir).mkdir(exist_ok=True)
filename = f"{formatted['date'][:10]}-{formatted['title'][:50].replace(' ', '-').lower()}.json"
Path(intranet_dir, filename).write_text(json.dumps(formatted, indent=2))
Step 4: Route by Department
DEPARTMENT_CHANNELS = {
"all": {"slack": "#general", "email_list": "[email protected]"},
"engineering": {"slack": "#engineering", "email_list": "[email protected]"},
"marketing": {"slack": "#marketing", "email_list": "[email protected]"},
"sales": {"slack": "#sales", "email_list": "[email protected]"}
}
def distribute_announcement(announcement, slack_token, smtp_config):
slack_formatted = format_for_slack(announcement)
email_formatted = format_for_email(announcement)
intranet_formatted = format_for_intranet(announcement)
for dept in announcement.departments:
config = DEPARTMENT_CHANNELS.get(dept, DEPARTMENT_CHANNELS["all"])
send_to_slack(slack_formatted, config["slack"], slack_token)
send_to_email(email_formatted, [config["email_list"]], smtp_config)
save_to_intranet(intranet_formatted)
print(f"Announcement distributed to {len(announcement.departments)} department(s)")
Step 5: Track Read Receipts
import sqlite3
def init_tracking_db(db_path="announcements.db"):
conn = sqlite3.connect(db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS announcement_reads (
announcement_id TEXT,
reader TEXT,
channel TEXT,
read_at TEXT
)
""")
conn.commit()
return conn
def read_rate(conn, announcement_id):
reads = conn.execute(
"SELECT COUNT(DISTINCT reader) FROM announcement_reads WHERE announcement_id=?",
(announcement_id,)
).fetchone()[0]
return reads
What to Build Next
Add scheduled announcements that queue up and send at a specific time. Monday morning announcements should not land at 2am. Add read receipts tracking to know which announcements actually reach people.
Related Reading
- Building Your First Automation: A Complete Guide - automation fundamentals
- AI-Powered Reporting That Actually Gets Read - making communications people read
- The Feedback Loop That Powers Everything - communication feedback loops
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment