Browse Source

0.9 almost done

master
Eddie 2 years ago
parent
commit
4ae44923fc
  1. 8
      .env.example
  2. 1
      .gitignore
  3. 49
      README.md
  4. 44
      autoResponder.py
  5. 7
      chatbot.py
  6. 24
      config.py
  7. 97
      mail_util.py
  8. 1
      requirements.txt
  9. 10
      sender.sh
  10. 7
      sender2.sh

8
.env.example

@ -0,0 +1,8 @@
EMAIL_SERVER=dein.server.com
EMAIL_ADDRESS=email@server.com
EMAIL_USERNAME=username
EMAIL_PASSWORD=password
BOT_API=https://deine.nextcloud.de/ocs/v1.php/apps/spreed/api/v1/chat/
BOT_USERNAME=botusername
BOT_PASSWORD=botpassword
BOT_ROOMTOKEN=28fu49fg

1
.gitignore vendored

@ -153,3 +153,4 @@ cython_debug/
#.idea/
contacts.json
executionDate.json

49
README.md

@ -1,3 +1,48 @@
# email_util
# Maily
## Inhaltsverzeichnis
- [Einleitung](#einleitung)
- [Installation](#installation)
- [Code Rundown](#codeRundown)
---
## Einleitung <a name="einleitung"></a>
Maily wurde entwickelt um auf unseren Email Postfächern automatisch zu antworten und uns darüber zu informieren wer uns geschrieben hat.
Wichtig war auch das Maily neuen Kontakten nur ein mal schreibt. Beim eingebauten Autoresponder unseres Email-Servers konnte man nur eine 'Sperrstunde' einstellen in der automatisch geantwortet wird. Auf alles. Und jeden. Immer. Sogar in einem aktiven Email-Verlauf hätte dieser Autoresponder einfach geantwortet.
Irgendwie sollte Maily uns wissen lassen wann und was sie macht damit wir im Bilde sind. Hier habe ich mich dazu entschieden dass Maily ein kleines 'Chatbot' modul bekommt und uns in Nextcloud-Talk schreibt. Der Vorteil dabei ist das man Maily direkt in den richtigen Channel schreiben lassen kann, so das alle Leute informiert werden die mit dem Postfach arbeiten.
Keiner hat zeit alle 2 Tage Logdaten auf einem Server nachzuschauen.
## Installation <a name="installation"></a>
Die installation einer Dev-Umgebung ist relativ straight forward, allerdings sollte beachtet werden das man Maily auf einer `UNIX` Maschine entwickeln sollte. Das interface zwischen Maily und Nextcloud wird mit einem `.sh` Skript ausgeführt der auf Windows nur schwer zum Laufen gebracht werden kann.
### Step 1
Als erstes muss das Repository heruntergeladen werden
```
$ git clone https://git.sommerschein.de/Sommerschein/email_util.git
```
### Step 2
Es muss eine `Virtuelle Umgebung` erstellt und die benötigten Module installiert werden.
```
$ python3 -m venv .venv
```
Mit diesem befehl wird eine sperierte version von `Python` im `Projekt` abgelegt, so dass keine Probleme mit neuen Versionen in den Modulen auftreten.
Dann noch aktivieren:
```
$ source .venv/bin/activate
```
Als nächstes muss die `requirements.txt` Datei installiert werden, damit wir alle Module bereit haben.
```
$ pip install -r requirements.txt
```
### Step 3
Die `.env.example` Datei in `.env` umbenennen und anpassen.
Das `BOT_PASSWORD` wird in der Cloud als `APP-Passwort` eingerichtet. So muss nicht der ganze User übergeben werden. Ausserdem kann der zugriff auf die Dateien begrenzt werden.
Der `BOT_ROOMTOKEN` ist der `Token` zu dem Raum in dem Maily schreibt. Man findet ihn am Ende der `URL` wen man den gewünschten Raum im Browser öffnet.
Die `BOT_API` ist immer gleich, hier muss nur die `URL` am anfang auf die gewünschte Cloud angepasst werden
Die `EMAIL` Variablen sind im grunde standart Login daten zu einem Email Server.
### Step 4
Im grunde sind wir fertig, ab jetzt kann an Maily entwickelt werden. Wenn man den `autoResponder.py` skript ausführt wird Maily angewendet und versucht seinen Job zu machen.
## Code Rundown <a name="codeRundown"></a>
Wird angepasst wen 1.0 fertig ist.
Kleies Utility programm für unsere Email verwaltung

44
autoResponder.py

@ -1,29 +1,43 @@
import codecs
from mail_util import checkFor_unkownContacts, sendEmails, jsonAddContacts
"""
This file will run Maily.
It will try to scan for new Contacts and if it found any it will write them an email.
Also Maily will inform us about any written emails via Nextcloud-Talk
"""
import os
from mail_util import checkFor_unkownContacts, sendEmails, jsonAddContacts, lastExecutionDate_Load, jsonCreateContacts, lastExecutionDate_Safe
from chatbot import sendMessage
from config import today, yesterday
#! This function reads the response text-file
def getResponseText():
with open('responses/bookingResponse.txt', 'r') as file:
data = file.read()
return data
contacts = checkFor_unkownContacts()
#contacts.append('e.neug@icloud.com')
responseText = getResponseText()
print(responseText)
sendEmails(responseText, contacts)
jsonAddContacts(contacts)
lastExecutionDate = lastExecutionDate_Load()
chatTextIntro = f"Hey! ich wurde Heute ({today}) ausgeführt und suche für Gestern({yesterday}) nach neuen Kontakten auf der booking@"
chatTextAmmount = f"Ich habe {len(contacts)} neue Kontakte gefunden und automatisch geschrieben"
chatTextNone = f"Ich habe keine neuen Kontakte gefunden"
chatTextNew = f"Hey! Ich wurde Heute ({today}) ausgeführt. Ich suche nach nicht beantworteten Emails, seit meiner letzten ausführung ({lastExecutionDate})"
if os.path.isfile('./contacts.json'):
contacts = checkFor_unkownContacts()
sendMessage(chatTextNew)
if len(contacts) > 0:
chatTextAmmount = f"Ich habe {len(contacts)} unbeantwortete Emails gefunden und automatisch geantwortet"
sendMessage(chatTextAmmount)
for c in contacts:
sendMessage(c)
sendEmails(responseText, contacts)
jsonAddContacts(contacts)
lastExecutionDate_Safe(str(today))
sendMessage(chatTextIntro)
if len(contacts) > 0:
sendMessage(chatTextAmmount)
for c in contacts:
sendMessage(c)
else:
sendMessage(chatTextNone)
else:
sendMessage(chatTextNone)
jsonCreateContacts()
print("I created the Contacts, run me again.")

7
chatbot.py

@ -1,5 +1,10 @@
"""
This File will use the 'sender.sh' shell script to send messages to Nextcloud-Talk
"""
import subprocess
from config import botAPI, botUsername, botPassword, botRoomToken
def sendMessage(message):
subprocess.call(['sh','./sender2.sh', message])
subprocess.call(['sh','./sender.sh', botAPI, botUsername, botPassword, botRoomToken, message])

24
config.py

@ -1,20 +1,34 @@
"""
This file holds all the important variables used accross this programm
"""
import os
from dotenv import load_dotenv
from datetime import date, timedelta
load_dotenv()
pw = os.getenv('PASSWORD')
server ="w00e1ce2.kasserver.com"
username ="booking@sommerschein.de"
# Setup Email Credentials
server = os.getenv('EMAIL_SERVER')
address = os.getenv('EMAIL_ADDRESS')
username = os.getenv('EMAIL_USERNAME')
password = os.getenv('EMAIL_PASSWORD')
# Setup Chatbot Credentials
botAPI = os.getenv('BOT_API')
botUsername = os.getenv('BOT_USERNAME')
botPassword = os.getenv('BOT_PASSWORD')
botRoomToken = os.getenv('BOT_ROOMTOKEN')
# Setup important Times and Formatting them
today = date.today()
yesterday = today - timedelta(days=1)
dateStringToday = today.strftime("%d-%b-%Y")
dateStringYesterday = yesterday.strftime("%d-%b-%Y")
searchUnawnsered = "UNANSWERED SENTSINCE 01-Sep-2022"
# Setup Search parameter
searchUnawnsered = "UNANSWERED SENTSINCE "
searchAll = 'ALL'
searchSentsince = 'SENTSINCE 01-Sep-2022'
searchSentsince = 'SENTSINCE '
searchToday = 'SENTON ' + dateStringToday
searchYesterday = 'SENTON ' + dateStringYesterday

97
mail_util.py

@ -1,42 +1,51 @@
import imaplib, email, os, json
from config import server, username, pw, searchAll, searchYesterday
"""
This File handles all the email and contact shenanigans,
its kind of convoluted at the Moment and needs a bit of cleanup.
I tried to keep everything in functions so it stays readable.
Some handle emails and the smtp & imap server-side,
the others Json stuff to extract email addresses and save them as contacts for future use.
"""
import imaplib, email, os, json
from smtplib import SMTP_SSL, SMTP_SSL_PORT
from config import server, username, password, address, searchAll, searchYesterday, searchUnawnsered, today, searchSentsince
from datetime import datetime
#! This function takes a list of Email-Addresses and sends them emails
def sendEmails(text, reciever):
# Credential Setup
SMTP_HOST = server
SMTP_USER = username
SMTP_PASS = pw
# Craft the email by hand
from_email = 'Maily-Sommerschein <bookin@sommerschein.de>' # or simply the email address
to_emails = reciever
body = text
headers = f"From: {from_email}\r\n"
headers += f"To: {', '.join(to_emails)}\r\n"
headers += f"Subject: Autoresponse\r\n"
email_message = headers + "\r\n" + body # Blank line needed between headers and body
# Connect, authenticate, and send mail
SMTP_USER = address
SMTP_PASS = password
# Connect to Server
smtp_server = SMTP_SSL(SMTP_HOST, port=SMTP_SSL_PORT)
smtp_server.set_debuglevel(1) # Show SMTP server interactions
smtp_server.login(SMTP_USER, SMTP_PASS)
smtp_server.sendmail(from_email, to_emails, email_message)
# Disconnect
for r in reciever:
# Craft the email
from_email = f'{username} <{address}>'
headers = f"From: {from_email}\r\n"
headers += f"To: {', '.join(r)}\r\n"
headers += f"Subject: Autoresponse\r\n"
email_message = headers + "\r\n" + text
# Send mail
smtp_server.sendmail(from_email, r, email_message)
# Disconnect from Server
smtp_server.quit()
#! This function loads all known contacts from the Json file
def loadKnownContacts():
f = open('contacts.json')
contacts = json.load(f)
return contacts
#! This function returns all Contacts from the Inbox
def getContacts(search):
# Connect to inbox
imap_server = imaplib.IMAP4_SSL(host=server)
imap_server.login(username, pw)
imap_server.login(address, password)
imap_server.select() # Default is `INBOX`
contacts = []
@ -58,17 +67,14 @@ def getContacts(search):
contact = c.split('<')
if len(contact) == 2:
contact = contact[1].split('>')
#contact = contact[0].split('(')
newContacts.append(contact[0])
#print(contact[0])
else:
contact = contact[0].split('(')
#print(contact[0])
newContacts.append(contact[0])
return newContacts
#! This function adds new contacts to the json file for later use
def jsonAddContacts(contacts):
knowContacts = loadKnownContacts()
for c in contacts:
@ -81,10 +87,11 @@ def jsonAddContacts(contacts):
with open('contacts.json', 'w', encoding='utf-8') as f:
json.dump(knowContacts, f, ensure_ascii=False, indent=4)
#! This function creates the initial Json file with all already known contacts from the inbox
def jsonCreateContacts():
# Connect to inbox
imap_server = imaplib.IMAP4_SSL(host=server)
imap_server.login(username, pw)
imap_server.login(address, password)
imap_server.select() # Default is `INBOX`
contacts = []
@ -101,43 +108,45 @@ def jsonCreateContacts():
contacts.append(contact)
newContacts = []
rawContacts = []
for c in contacts:
rawContacts.append(c)
contact = c.split('<')
if len(contact) == 2:
contact = contact[1].split('>')
#contact = contact[0].split('(')
newContacts.append(contact[0])
#print(contact[0])
else:
contact = contact[0].split('(')
#print(contact[0])
newContacts.append(contact[0])
if os.path.isfile('./contacts.json'):
print('Deleting Contacts')
os.remove('contacts.json')
if os.path.isfile('./rawContacts.json'):
print('Deleting Contacts')
os.remove('rawContacts.json')
with open('contacts.json', 'w', encoding='utf-8') as f:
json.dump(newContacts, f, ensure_ascii=False, indent=4)
with open('rawContacts.json', 'w', encoding='utf-8') as f:
json.dump(rawContacts, f, ensure_ascii=False, indent=4)
#! This function will safe the last execution date in a json-file
def lastExecutionDate_Safe (executionDate):
if os.path.isfile('./executionDate.json'):
os.remove('executionDate.json')
with open('executionDate.json', 'w', encoding='utf-8') as f:
json.dump(executionDate, f, ensure_ascii=False, indent=4)
#! This function will load the last execution date
def lastExecutionDate_Load():
f = open('executionDate.json')
date = json.load(f)
return date
#! This function returns all unkown contacts
def checkFor_unkownContacts():
contacts = getContacts(searchYesterday)
lastExecution = lastExecutionDate_Load()
date = datetime.strptime(lastExecution, "%Y-%m-%d")
contacts = getContacts(searchUnawnsered + date.strftime("%d-%b-%Y"))
knownContacts = loadKnownContacts()
unknownContacts = []
for c in contacts:
if c not in knownContacts:
# TODO: send Email
#print(c)
unknownContacts.append(c)
return unknownContacts

1
requirements.txt

@ -0,0 +1 @@
python-dotenv==0.21.0

10
sender.sh

@ -1,7 +1,9 @@
#!/bin/bash
API=https://cloud1.sommerschein.de/ocs/v1.php/apps/spreed/api/v1/chat/xzntzmuh
LOGIN="Maily:Gtjik-qP48b-y62bC-r8yos-qJT9Y"
MESSAGE=$1
API=$1
USERNAME=$2
PASSWORD=$3
TOKEN=$4
MESSAGE=$5
curl -d '{"token":"xzntzmuh", "message":"'"$MESSAGE"'"}' -H "Content-Type: application/json" -H "Accept:application/json" -H "OCS-APIRequest:true" -u "$LOGIN" $API 2> /dev/null | > /dev/null
curl -d '{"token":"'"$TOKEN"'", "message":"'"$MESSAGE"'"}' -H "Content-Type: application/json" -H "Accept:application/json" -H "OCS-APIRequest:true" -u "$USERNAME:$PASSWORD" $API$TOKEN 2> /dev/null | > /dev/null

7
sender2.sh

@ -1,7 +0,0 @@
#!/bin/bash
API=https://cloud1.sommerschein.de/ocs/v1.php/apps/spreed/api/v1/chat/onxr79pz
LOGIN="Maily:Gtjik-qP48b-y62bC-r8yos-qJT9Y"
MESSAGE=$1
curl -d '{"token":"onxr79pz", "message":"'"$MESSAGE"'"}' -H "Content-Type: application/json" -H "Accept:application/json" -H "OCS-APIRequest:true" -u "$LOGIN" $API 2> /dev/null | > /dev/null
Loading…
Cancel
Save