newsletter kw47
This commit is contained in:
36
infoZettelOrg/2022-11-19-newsletterKw47.md
Normal file
36
infoZettelOrg/2022-11-19-newsletterKw47.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: cwsvjudo Newsletter KW 47
|
||||
---
|
||||
|
||||
# Newsletter KW47
|
||||
|
||||
## Verlegung des Trainingsortes 2022-11-25 *und* am 2022-12-02
|
||||
|
||||
Wie bereits angekündigt werden wir am 25.11.2022 mit den Karateka unseren Trainingsort tauschen. Neu ist, dass wir das am 02.12.2022 noch einmal machen werden.
|
||||
|
||||
Die nächsten beiden *Freitags*-Trainings werden also im [Gymnastikraum der Sachsenhalle][1] (Str. Usti nad Labem 275, 09119 Chemnitz) stattfinden:
|
||||
|
||||
- Datum: 25.11. und 02.12.2022
|
||||
- Zeit:
|
||||
- 16:00-17:45 Uhr die Anfänger/Kinder,
|
||||
- 17:15-19:15 Uhr Fortgeschrittene/Jugend/Erwachsene
|
||||
- bei den Großen bitte Tischtennisschläger mitbringen
|
||||
- Ort: [Gymnastikraum der Sachsenhalle][1]
|
||||
|
||||
Das *Mittwoch*-Training bleibt davon unberührt und findet wie gewohnt in unserem Dojo statt.
|
||||
|
||||
## Restliches Wettkampfjahr
|
||||
|
||||
Zum Schluss noch die übliche Werbung für die restlichen Wettkämpfe im Jahr. Ich möchte auch nochmal darauf hinweisen, dass der [Lions-Cup][wk177] auch die U13 beinhaltet.
|
||||
|
||||
- 2022-12-03 - [40+1 Jahr Nikolausturnier][wk176], Altersklassen: U10 U12
|
||||
- 2022-12-11 - [Lions-Cup][wk177], Altersklassen: U9 U11 U13
|
||||
|
||||
Wie immer wird zur besseren Planung um ein Einschreiben in unserem [Wettkampfplaner][wkPlaner] gebeten.
|
||||
|
||||
MsG marko
|
||||
|
||||
[1]: https://osm.org/go/0MIYhooV9--
|
||||
[wkPlaner]: http://cwsvjudo.bplaced.net/participo/
|
||||
[wk176]: http://cwsvjudo.bplaced.net/participo/events#176
|
||||
[wk177]: http://cwsvjudo.bplaced.net/participo/events#177
|
||||
11
infoZettelOrg/eMailReceiverLists/onlyMe.json
Normal file
11
infoZettelOrg/eMailReceiverLists/onlyMe.json
Normal file
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"loginName": "marko",
|
||||
"eMail": [
|
||||
"cwsvjudo@arcor.de",
|
||||
"marko.bunzel@arcor.de",
|
||||
"cwsvjudo@gmail.com"
|
||||
]
|
||||
}
|
||||
]
|
||||
103
infoZettelOrg/eMailReceiverLists/wkParticipo_Users.json
Normal file
103
infoZettelOrg/eMailReceiverLists/wkParticipo_Users.json
Normal file
@@ -0,0 +1,103 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"loginName": "marko",
|
||||
"eMail": [
|
||||
"cwsvjudo@arcor.de",
|
||||
"marko.bunzel@arcor.de",
|
||||
"cwsvjudo@gmail.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"loginName": "NickW",
|
||||
"eMail": [
|
||||
"nick.weidensager@web.de"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "15",
|
||||
"loginName": "nSchmidl",
|
||||
"eMail": [
|
||||
"post@was7.de"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "20",
|
||||
"loginName": "elternBrittnacher",
|
||||
"eMail": [
|
||||
"stephanie.brittnacher@gmail.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "31",
|
||||
"loginName": "elternFriedrich",
|
||||
"eMail": [
|
||||
"akf21182@aol.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "50",
|
||||
"loginName": "elternCuric",
|
||||
"eMail": [
|
||||
"churicnate@yahoo.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "59",
|
||||
"loginName": "fuchshund",
|
||||
"eMail": [
|
||||
"thomasulbricht@fuchshund.de"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "77",
|
||||
"loginName": "elternHaeuberer",
|
||||
"eMail": [
|
||||
"julia.haeuberer@gmx.de",
|
||||
"norman.haeuberer@gmail.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "81",
|
||||
"loginName": "mohamadZahra",
|
||||
"eMail": [
|
||||
"mohamad.zahra1986@gmail.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "85",
|
||||
"loginName": "elternGerlach",
|
||||
"eMail": [
|
||||
"manja.bunzel@gmx.de"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "91",
|
||||
"loginName": "elternMeier",
|
||||
"eMail": [
|
||||
"meier.andrej@web.de"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "94",
|
||||
"loginName": "elternBritvin",
|
||||
"eMail": [
|
||||
"luidmyla60@gmail.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "96",
|
||||
"loginName": "elternMaiatska",
|
||||
"eMail": [
|
||||
"ice_0605@i.ua"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "101",
|
||||
"loginName": "elternKraft",
|
||||
"eMail": [
|
||||
"a-kraft-@gmx.net"
|
||||
]
|
||||
}
|
||||
]
|
||||
206
infoZettelOrg/tools/sendNewsletter.py
Executable file
206
infoZettelOrg/tools/sendNewsletter.py
Executable file
@@ -0,0 +1,206 @@
|
||||
#! /usr/bin/env python3
|
||||
|
||||
import json
|
||||
import smtplib
|
||||
import ssl
|
||||
from email import utils
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
import pypandoc
|
||||
import yaml
|
||||
import argparse
|
||||
import certifi
|
||||
import os
|
||||
import requests
|
||||
import re
|
||||
import datetime
|
||||
|
||||
# only for developing
|
||||
endDate = (datetime.datetime.now() +
|
||||
datetime.timedelta(days=7)).strftime("%Y-%m-%d")
|
||||
|
||||
participoUrl = "http://cwsvjudo.bplaced.net/participo"
|
||||
|
||||
|
||||
class Email:
|
||||
title = None
|
||||
mdText = None
|
||||
|
||||
def __init__(self, title, mdText):
|
||||
self.title = title
|
||||
self.mdText = mdText
|
||||
|
||||
def addApiKeyToUrls(self, apiKey, url=participoUrl):
|
||||
self.mdText = re.sub(url+"([^#,\n]*)", url + "\\1" +
|
||||
"?apiKey="+apiKey, self.mdText)
|
||||
|
||||
@staticmethod
|
||||
def loadFromMdFile(path):
|
||||
# read markdownfile as header and text
|
||||
mdHeader = None
|
||||
with open(argv.mdFilePath) as f:
|
||||
mdHeader = yaml.safe_load(get_yaml(f))
|
||||
|
||||
title = mdHeader['title'] if checkHeader(
|
||||
mdHeader) else "cwsvJudo newsLetter"
|
||||
|
||||
mdText = None
|
||||
with open(argv.mdFilePath) as f:
|
||||
mdText = f.read()
|
||||
|
||||
return Email(title, mdText)
|
||||
|
||||
|
||||
def get_yaml(f):
|
||||
'''Extracts the yamlHeader from a Markdown file'''
|
||||
pointer = f.tell()
|
||||
if f.readline() != '---\n':
|
||||
f.seek(pointer)
|
||||
return ''
|
||||
readline = iter(f.readline, '')
|
||||
readline = iter(readline.__next__, '---\n')
|
||||
return ''.join(readline)
|
||||
|
||||
|
||||
def checkHeader(header):
|
||||
"""check the header for validity
|
||||
|
||||
useful, if the title was forgotten
|
||||
|
||||
Args:
|
||||
header (dict): yamlHeader of the mdNewsletter
|
||||
|
||||
Returns:
|
||||
bool: true if header is alright, false if an error was detected
|
||||
"""
|
||||
retVal = True
|
||||
if not 'title' in header:
|
||||
print("Header has no 'title' attribute")
|
||||
retVal = False
|
||||
else:
|
||||
if header['title'] is False:
|
||||
print("Empty title!")
|
||||
retVal = False
|
||||
return retVal
|
||||
|
||||
|
||||
def getArguments():
|
||||
argParser = argparse.ArgumentParser(
|
||||
description="Send an Markdown-File as eMail"
|
||||
)
|
||||
argParser.add_argument(
|
||||
"mdFilePath",
|
||||
help="Path to MarkdownFile to send"
|
||||
)
|
||||
argParser.add_argument(
|
||||
"-r", "--receiver", help="json file with the receiver")
|
||||
|
||||
return argParser.parse_args()
|
||||
|
||||
|
||||
def loadFromJson(path):
|
||||
jsonDict = None
|
||||
with open(argv.receiver) as jsonFile:
|
||||
jsonDict = json.load(jsonFile)
|
||||
|
||||
return jsonDict
|
||||
|
||||
|
||||
def loadFromYaml(path):
|
||||
yamlDict = None
|
||||
with open(path, "r") as yamlFile:
|
||||
yamlDict = yaml.safe_load(yamlFile)
|
||||
|
||||
return yamlDict
|
||||
|
||||
|
||||
def createApiKey(allowKey, userId, rights, endDate):
|
||||
"""call the participo api to create a new api key
|
||||
|
||||
Args:
|
||||
allowKey (string): api key that allows the creation apiKey-s
|
||||
userId (int): id of the receiver of the new api key
|
||||
rights (string): comma separated list of strings denoting the rights of the api key
|
||||
endDate (string): 'yyyy-mm-dd' formated string denoting the rights of the api key
|
||||
|
||||
return: new api key or none on failure
|
||||
"""
|
||||
postData = {
|
||||
'apiKey': allowKey,
|
||||
'userId': userId,
|
||||
'rights': rights,
|
||||
'endDate': endDate
|
||||
}
|
||||
response = requests.post(
|
||||
participoUrl+"/api.apiKeys.add", json=postData)
|
||||
|
||||
jsonResponse = response.json()
|
||||
|
||||
return jsonResponse['apiKey'] if 'apiKey' else None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
argv = getArguments()
|
||||
config = loadFromYaml("./config.yaml")
|
||||
receivers = loadFromJson(argv.receiver)
|
||||
|
||||
emailTemplate = Email.loadFromMdFile(argv.mdFilePath)
|
||||
|
||||
# messages are prepared emails ready to send
|
||||
messageQueue = []
|
||||
|
||||
for user in receivers:
|
||||
apiKey = createApiKey(
|
||||
config['apiKey']['createApiKey'], user['id'], "login", endDate)
|
||||
if apiKey is None:
|
||||
print(f"Couldn't get apiKey")
|
||||
continue
|
||||
|
||||
email = emailTemplate
|
||||
email.addApiKeyToUrls(apiKey)
|
||||
|
||||
# Create the plain-text and HTML version of your message
|
||||
text = pypandoc.convert_text(email.mdText, "markdown", format='md', extra_args=[
|
||||
"--self-contained", "--resource-path=../aufgaben"])
|
||||
html = pypandoc.convert_text(email.mdText, "html", format='md', extra_args=[
|
||||
"--self-contained", "--resource-path=../aufgaben"])
|
||||
|
||||
# Turn these into plain/html MIMEText objects
|
||||
txtMimeText = MIMEText(text, "plain")
|
||||
htmlMimeText = MIMEText(html, "html")
|
||||
|
||||
# @todo the message has to be recreated for every email address since it seems to be added by reference to the queue. meaning changing the emailAddress changes it in the previously added also
|
||||
for toAddress in user['eMail']:
|
||||
# create the mail
|
||||
message = MIMEMultipart("alternative")
|
||||
# Setting header data
|
||||
message["Subject"] = email.title
|
||||
message["From"] = config['senderEmailAddress']
|
||||
message["Reply-To"] = config['senderEmailAddress']
|
||||
message["Date"] = str(utils.formatdate(localtime=True))
|
||||
|
||||
# only set the to-header one time: setting it multiple
|
||||
# times results in a multiple to-entries in the header!
|
||||
# Meaning the mail has to be recreated for each to address.
|
||||
# @todo Find a way to reuse the created mail for every recipent
|
||||
message["To"] = toAddress
|
||||
|
||||
# Add HTML/plain-text parts to MIMEMultipart message
|
||||
# The email client will try to render the last part first
|
||||
message.attach(htmlMimeText)
|
||||
message.attach(txtMimeText)
|
||||
|
||||
messageQueue.append(message)
|
||||
|
||||
# Create a secure SSL context
|
||||
context = ssl.create_default_context()
|
||||
# @todo This is a very bad hack, because the cert checking doesn't work anymore
|
||||
context.check_hostname = False
|
||||
context.verify_mode = ssl.CERT_NONE
|
||||
|
||||
with smtplib.SMTP_SSL(config['smtp']['serverAddress'], config['smtp']['serverPort'], context=context) as server:
|
||||
server.login(config['smtp']['login'], config['smtp']['password'])
|
||||
for message in messageQueue:
|
||||
print(f"sending to {message['To']}")
|
||||
server.sendmail(config['senderEmailAddress'],
|
||||
message["To"], message.as_string())
|
||||
Reference in New Issue
Block a user