Jump to content
Fi8sVrs

feed2email - Send RSS/Atom feeds to e-mail

Recommended Posts

  • Active Members
Posted

feed2email

Send RSS/Atom feeds to e-mail

 

requirements.txt

feedparser==5.2.1

feed2email.py

#!/usr/bin/env python3

# vim: set ai et ts=4 sw=4:

# feed2email.py
# (c) Aleksander Alekseev 2016-2017
# http://eax.me/

import feedparser

from smtplib import SMTP
# from smtplib import SMTP_SSL as SMTP
from email.mime.text import MIMEText
from contextlib import contextmanager
import signal
import getpass
import hashlib
import time
import sys
import re

server = 'smtp.yandex.ru'
port = 587 # 25
login = "YOUR_SENDER_LOGIN"
from_addr = "NEWS <YOUR_SENDER_LOGIN@yandex.ru>"
receiver = "YOUR_EMAIL"
processed_urls_fname = "processed-urls.txt"
feed_list_fname = "feed-list.txt"
# change to True before first run or you will receive A LOT of emails
# then change back to False
fake_send = False
sleep_time = 60*5 # seconds
net_timeout = 20 # seconds
smtp_retry_time = 30 # seconds
smtp_retries_num = 5

# >>> import hashlib
# >>> hashlib.sha1(b"qwerty").hexdigest()
# 'b1b3773a05c0ed0176787a4f1574ff0075f7521e'
pwhash = 'YOUR_PASSWORD_SHA1_HASH'

# FUNCS

class TimeoutException(Exception): pass

@contextmanager
def timeout_sec(seconds):
  def signal_handler(signum, frame):
    raise TimeoutException(Exception("Timed out!"))
  signal.signal(signal.SIGALRM, signal_handler)
  signal.alarm(seconds)
  try:
    yield
  finally:
    signal.alarm(0)

def file_to_list(fname):
  rslt = []
  with open(fname, "r") as f:
    rslt = [x for x in f.read().split("\n") if x.strip() != "" ]
  return rslt

# MAIN

password = getpass.getpass("SMTP Password: ")

if hashlib.sha1(bytearray(password, 'utf-8')).hexdigest() != pwhash:
  print("Invalid password", file = sys.stderr)
  sys.exit(1)

while True:
  feed_list = file_to_list(feed_list_fname)
  # filter comments
  feed_list = [ x for x in feed_list if not re.match("(?i)\s*#", x) ]
  keep_urls = 1000*len(feed_list)
  processed_urls = []

  try:
    processed_urls = file_to_list(processed_urls_fname)
  except FileNotFoundError:
    pass

  print("Processing {} feeds...".format(len(feed_list)))

  for feed in feed_list:
    print(feed)
    f = None
    try:
      with timeout_sec(net_timeout):
        f = feedparser.parse(feed)
    except TimeoutException:
      print("ERROR: Timeout!")
      continue

    feed_title = f['feed'].get('title', '(NO TITLE)')
    feed_link = f['feed'].get('link', '(NO LINK)')

    for entry in f['entries']:
      if entry['link'] in processed_urls:
        continue

      subject = "{title} | {feed_title} ({feed_link})".format(
          title = entry.get('title', '(NO TITLE'),
          feed_title = feed_title,
          feed_link = feed_link
        )
      print(subject)
      summary = entry.get('summary', '(NO SUMMARY)')
      body = "{summary}\n\n{link}\n\nSource feed: {feed}".format(
          summary = summary[:256],
          link = entry['link'],
          feed = feed
        )
      print(body)
      print("-------")

      msg = MIMEText(body, 'plain')
      msg['Subject'] = subject
      msg['From'] = from_addr
      msg['To'] = receiver

      if not fake_send:
        for attempt in range(1, smtp_retries_num+1):
          try:
            with timeout_sec(net_timeout), SMTP(server, port) as conn:
              conn.starttls()
              conn.login(login, password)
              conn.sendmail(from_addr, [receiver], msg.as_string())
            break
          except Exception as exc:
            print(("Failed to send email {}/{} - {}, " +
                  "retrying in {} seconds").format(
                    attempt, smtp_retries_num, exc,
                    smtp_retry_time
                  )
            )
            time.sleep(smtp_retry_time)

      processed_urls = [ entry['link'] ] + processed_urls

  with open(processed_urls_fname, "w") as urls_file:
    urls_file.write("\n".join(processed_urls[:keep_urls]))

  print("Sleeping {} seconds...".format(sleep_time))
time.sleep(sleep_time)

 

Download: feed2email-master.zip

Source: https://github.com/afiskon/feed2email

  • Upvote 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...