DEV Community

qing
qing

Posted on

Build an Automated Newsletter with Python

Build an Automated Newsletter with Python

Build an Automated Newsletter with Python

You wake up, open your inbox, and there it is: a polished, AI-summarized newsletter about the latest tech trends, ready to send to your subscribers. You didn’t write a single word. You didn’t even open your editor. That’s the power of automation—and it’s entirely possible to build yourself with Python today.

Automated newsletters aren’t just for tech giants or marketing teams with six-figure budgets. They’re for developers, bloggers, and creators who want to stay consistent without burning hours every week. With a few Python scripts, you can scrape content, summarize it, format it, and send it—all while you sleep.

Let’s build one together.

Why Automate Your Newsletter?

Before we dive into code, let’s be clear: automation isn’t about replacing your voice. It’s about amplifying your reach.

  • Consistency: Send weekly digests without the mental load of “what should I write?”
  • Efficiency: Spend 10 minutes reviewing summaries instead of 3 hours writing from scratch.
  • Scalability: Grow your audience without growing your workload.

The best part? You can start small. A simple script that fetches headlines and sends them via email is enough to get your first automated newsletter out.

The Core Workflow

A fully automated newsletter follows a predictable pipeline:

  1. Data Ingestion: Pull articles, posts, or tweets from defined sources (blogs, RSS feeds, APIs).
  2. Filtering & Scoring: Use simple heuristics or AI to filter for relevance.
  3. Summarization: Generate concise, engaging summaries tailored to your audience.
  4. Formatting: Compile content into a brand-consistent HTML or plain-text newsletter.
  5. Delivery: Send via email using SMTP or a service like Mailgun, SendGrid, or Mailchimp.

We’ll implement each step in Python, using free or low-cost tools.

Step 1: Fetching Content

Let’s start by grabbing recent posts from a set of tech blogs. We’ll use the requests library to fetch RSS feeds and BeautifulSoup to parse them.

import requests
from bs4 import BeautifulSoup
from datetime import datetime

def fetch_rss_feed(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'xml')
    articles = []

    for item in soup.find_all('item'):
        title = item.find('title').text
        link = item.find('link').text
        pub_date = item.find('pubDate').text

        # Parse date and filter for last 7 days
        try:
            date_obj = datetime.strptime(pub_date, '%a, %d %b %Y %H:%M:%S %z')
            if date_obj >= datetime.now().replace(tzinfo=date_obj.tzinfo) - datetime.timedelta(days=7):
                articles.append({'title': title, 'link': link, 'date': pub_date})
        except:
            continue

    return articles

# Example: Fetch from a sample RSS feed
rss_url = "https://example-tech-blog.com/rss.xml"
articles = fetch_rss_feed(rss_url)
print(f"Found {len(articles)} recent articles")
Enter fullscreen mode Exit fullscreen mode

💡 Tip: Replace rss_url with real RSS feeds from sites like Hacker News, Dev.to, or Medium.

Step 2: Summarize with AI (Optional but Powerful)

If you want to go beyond raw headlines, integrate an AI summarizer. You can use the free transformers library from Hugging Face or a paid API like OpenAI.

Here’s a simple example using Hugging Face’s summarization pipeline:

from transformers import pipeline

summarizer = pipeline("summarization", model="facebook/bart-large-cnn")

def summarize_text(text, max_length=100):
    summary = summarizer(text, max_length=max_length, min_length=30, do_sample=False)
    return summary[0]['summary_text']

# Example usage
sample_text = "Python is a high-level, general-purpose programming language. Its design philosophy emphasizes code readability with the use of significant indentation."
summary = summarize_text(sample_text)
print(summary)
Enter fullscreen mode Exit fullscreen mode

For each article, you can fetch the full text (via requests.get(article['link'])) and pass it to summarize_text().

Step 3: Format the Newsletter

Now, compile everything into a clean, readable format. We’ll build a simple HTML template with your brand colors and structure.

def format_newsletter(articles):
    html = """
    <html>
    <head>
        <style>
            body { font-family: Arial; background: #f4f4f4; color: #333; }
            .container { max-width: 600px; margin: 20px auto; background: #fff; padding: 20px; border-radius: 8px; }
            h1 { color: #1A2B4A; }
            .article { margin-bottom: 20px; border-bottom: 1px solid #ddd; padding-bottom: 10px; }
            .title { font-size: 18px; color: #1A2B4A; }
            .summary { font-size: 14px; color: #666; }
            .link { font-size: 13px; color: #007bff; }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>🚀 Weekly Tech Digest</h1>
            <p>Here are the top stories from the past week:</p>
    """

    for article in articles:
        html += f"""
        <div class="article">
            <div class="title">{article['title']}</div>
            <div class="summary">{article.get('summary', 'No summary available')}</div>
            <div class="link">Read more: <a href="{article['link']}">{article['link']}</a></div>
        </div>
        """

    html += """
        </div>
    </body>
    </html>
    """
    return html

newsletter_html = format_newsletter(articles)
Enter fullscreen mode Exit fullscreen mode

Step 4: Send via Email

Now, let’s send the newsletter using Python’s built-in smtplib. We’ll use Gmail as an example, but this works with any SMTP provider.

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

def send_newsletter(html_content, recipient_email, sender_email, password):
    msg = MIMEMultipart()
    msg['From'] = sender_email
    msg['To'] = recipient_email
    msg['Subject'] = "🚀 Weekly Tech Digest"

    msg.attach(MIMEText(html_content, 'html'))

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login(sender_email, password)
    server.sendmail(sender_email, recipient_email, msg.as_string())
    server.quit()

    print("✅ Newsletter sent!")

# Example usage
send_newsletter(
    html_content=newsletter_html,
    recipient_email="subscriber@example.com",
    sender_email="your-email@gmail.com",
    password="your-app-password"  # Use an app password, not your main password
)
Enter fullscreen mode Exit fullscreen mode

⚠️ Security Note: Never hardcode passwords. Use environment variables or a secrets manager. For Gmail, generate an App Password if you have 2FA enabled.

Step 5: Automate Execution

To make this fully automated, schedule your script to run daily or weekly.

Option A: GitHub Actions (Free & Cloud-Based)

  1. Create a .github/workflows/newsletter.yml file in your repo.
  2. Add a cron-triggered workflow:
name: Send Newsletter
on:
  schedule:
    - cron: '0 8 * * 1'  # Every Monday at 8 AM UTC
jobs:
  send:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
      - name: Install dependencies
        run: pip install requests bs4 transformers
      - name: Run newsletter script
        env:
          GMAIL_USER: ${{ secrets.GMAIL_USER }}
          GMAIL_PASS: ${{ secrets.GMAIL_PASS }}
          SUBSCRIBER_EMAIL: ${{ secrets.SUBSCRIBER_EMAIL }}
        run: python newsletter.py
Enter fullscreen mode Exit fullscreen mode
  1. Store your credentials in GitHub Secrets (GMAIL_USER, GMAIL_PASS, etc.).
  2. Push to GitHub—your newsletter will send automatically every Monday.

Option


If you found this helpful, consider buying me a coffee ☕ — it keeps these articles coming!

Also check out my AI tools collection: AI 次元世界 — free AI tools for developers.


💡 Related: **Content Creator Ultimate Bundle (Save 33%)* — $29.99*

Top comments (0)