home
erste Version am 19.12.2019
letzte Änderung am 22.12.2019

Abfuhr-Mailer

Vor ein paar Tagen gab es wieder mal Post vom lokalen Müll-Entsorger: die Abfuhrtermine für 2020 auf einem DIN-A4-Blatt.
Dieses Kalender-Blatt ist bei uns in der Küche an die Wand gepinnt. Und damit klappt es auch fast immer, die jeweiligen Mülltonnen am Abholtag vor der Gartenpforte stehen zu haben. Momentan besteht allerdings gerade ein kleines Problemchen mit dem Papiermüll. Der wird nur alle vier Wochen abgeholt....und den letzten Termin haben wir vertrödelt. Echt ungünstig. So kurz vor dem Fest zur Wintersonnenwende. Gerade jetzt sind besonders viele sperrige Kartons zu entsorgen.

Es könnte also nicht schaden, irgendeine zusätzliche Methode zu haben, um die Vertrödelungs-Wahrscheinlichkeit zu minimieren.

Zwar bietet der Entsorger eine sog. Abfallmanager-App für Smartphones an, jedoch sind deren Bewertungen überwiegend vernichtend. Will heißen: das Ding ist unzuverlässig und damit praktisch wertlos.

Erfreulicherweise werden die Termine auch in maschinenlesbarer Form angeboten (ics-Format).
Somit wird es ohne [fehleranfälliges] Abtippen möglich, sich z.B. per EMail an Abfuhr-Termine erinnern zu lassen.



Das folgende Script liest eine (jährlich auszutauschende) Termin-Datei und verschickt Erinnerungs-EMails an eine Liste von Empfängern. Wenn mehrere Tonnen an einem Tag geleert werden, fasst das Script diese Information in einer EMail zusammen.
EMails werden am Vortag und dem Tag der Abfuhr verschickt. Letztes jedoch nur, wenn das Script mit dem Parameter "0" aufgerufen wurde. Auf diese Weise wird erreicht, dass man am Abfuhrtag keine EMail mehr erhält, wenn es dann ohnehin schon zu spät zum Müll rausstellen wäre.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# ----------------------------------------------------------------------
# abfuhrtermine_per_email.py
#
# Dieses Script ist täglich via crontab zu starten. Es sendet
# Erinnerungs-EMails, sofern Mülltonnen am aktuellen oder am
# Folge-Tag an der Straße stehen müssen.
#
# Also etwa so:
# 30 6 * * * /usr/bin/python3 /home/dede/bin/abfuhrtermine_per_email.py 0
# 0 17 * * * /usr/bin/python3 /home/dede/bin/abfuhrtermine_per_email.py
#
# Detlev Ahlgrimm, 18.12.2019
#
# 22.12.2019 dem EMail-Body Wochentag und Datum zugefügt

import sys
import datetime
import locale
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# https://www.asf-online.de/abfuhrtermine/
# https://www.asf-online.de/api_v2/collection_dates/1/ort/176/strasse/200/hausnummern/10a/abfallarten/R02-B02-P04-D02/kalender.ics
FN="/home/dede/daten/Abfuhrtermine.ics"

LONG_NAME={ "R":"der Restmüll", "G":"der GelbeSack", "P":"die Papiertonne", "B":"die Biotonne" }

# ----------------------------------------------------------------------
# Senden einer EMail.
class SendEmail():
def __init__(self):
self.SERVER ="...blabla....webpack.hosteurope.de"
self.PORT =25
self.ACCOUNT ="...username..."
self.PASSWORD ="...password..."
self.FROM ="abfuhrbot@dahlgrimm.de"

def send(self, to_addr_lst, subject, message):
msg=MIMEMultipart()
msg["From"]=self.FROM
msg["To"]=", ".join(to_addr_lst)
msg["Subject"]=subject
msg.attach(MIMEText(message))

mailserver=smtplib.SMTP(self.SERVER, self.PORT)
mailserver.ehlo()
mailserver.starttls()
mailserver.ehlo()
mailserver.login(self.ACCOUNT, self.PASSWORD)
mailserver.sendmail(self.FROM, to_addr_lst, msg.as_string())
mailserver.quit()


# ----------------------------------------------------------------------
# Liefert für die Kalender-Datei "fn" ein Dictionary im Format:
# { <Tage bis Termin> : [(<Tonnen-Typ>, <Datum>), ...], ... }
def parse_ics_file(fn=FN):
KEYWORD_DATE="DTSTART;VALUE=DATE:" # z.B. DTSTART;VALUE=DATE:20200612
KEYWORD_TYPE="SUMMARY:" # z.B. SUMMARY:Restabfalltonne (60-240l)(14tgl.)
dates=dict()
today=datetime.date.today()
#today=datetime.date(2019, 12, 28)

with open(fn, "r") as fo:
dt=tp=""
for ln in fo: # über alle Zeilen der Kalender-Datei
if ln.startswith(KEYWORD_DATE): # wenn Datums-Zeile...
dt=ln[len(KEYWORD_DATE):].strip() # ...Datum holen
elif ln.startswith(KEYWORD_TYPE): # wenn TonnenTyp-Zeile...
tp=ln[len(KEYWORD_TYPE)].strip() # ersten Buchstaben des TonnenTyps holen
if dt!="" and tp!="": # wenn ein Wertepaar gefunden wurde...
at=datetime.datetime.strptime(dt, "%Y%m%d").date() # Datum umwandeln
dd=(at-today).days # Abstand des Datums zu heute in Tagen
if dd in dates: # wenn es bereits einen Eintrag zu diesem Abstand gibt...
dates[dd].append((tp, at)) # ...Liste verlängern
else:
dates.update({dd:[(tp, at)]}) # ...ansonsten neu einfügen
dt=tp="" # Wertepaar auf ungültig setzen
return dates

# ----------------------------------------------------------------------
# main
if __name__=='__main__':
locale.setlocale(locale.LC_TIME, "de_DE.utf8")
if len(sys.argv)>1: # wenn das Script mit einem Parameter aufgerufen wurde...
check_days=(0, 1) # ...EMails auch für heutige Abfuhrtermine verschicken
else:
check_days=(1,) # ...ansonsten nur für welche am Folgetag
email=None
dates=parse_ics_file()
for days_until, type_date_list in sorted(dates.items()):
#print(days_until, type_date_list)
if days_until in check_days:
date_str=type_date_list[0][1].strftime("(%A, %d.%m.)")
zfix=[("Heute", "heute"), ("Morgen", "morgen")]
if len(type_date_list)>1: sfix="müssen"
else: sfix="muss"

type_str_short="+".join([e[0] for e in type_date_list])
type_str_long=" und ".join([LONG_NAME[e[0]] for e in type_date_list])

subject="%s wird %s abgeholt!"%(zfix[days_until][0], type_str_short)
message="Dies ist eine Erinnerung, dass %s %s %s an der Straße stehen %s!"%(zfix[days_until][1], date_str, type_str_long, sfix)
#print(subject)
#print(message)
if email is None:
email=SendEmail()
email.send(["dede@dahlgrimm.de", "foobar@gmx.de"], subject, message)



Das Script wird per crontab zweimal täglich aufgerufen:
30 6 * * * /usr/bin/python3 /home/dede/bin/abfuhrtermine_per_email.py 0
0 17 * * * /usr/bin/python3 /home/dede/bin/abfuhrtermine_per_email.py

Durch die erste Zeile werden um 06:30 Uhr EMails für heutige und morgige Abfuhrtermine verschickt.
Durch die zweite Zeile werden um 17:00 Uhr EMails für Abfuhrtermine am Folgetag verschickt.

Dementsprechend wird jeder Termin dreimal per EMail gemeldet.

Eine EMail sieht etwa so aus:
Von:       abfuhrbot@dahlgrimm.de
Betreff:   Morgen wird G abgeholt!
Inhalt:

Dies ist eine Erinnerung, dass morgen (Montag, 23.12.) der GelbeSack an der Straße stehen muss!

Oder so, wenn zwei Tonnen abgeholt werden:
Von:       abfuhrbot@dahlgrimm.de
Betreff:   Heute wird R+B abgeholt!
Inhalt:

Dies ist eine Erinnerung, dass heute (Samstag, 28.12.) der Restmüll und die Biotonne an der Straße stehen müssen!