Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Fachrat Informatik
pter
Commits
c830cc47
Commit
c830cc47
authored
Jul 18, 2020
by
Dominik Woiwode
Browse files
Add Email Implementation
parent
4eaa2978
Changes
2
Hide whitespace changes
Inline
Side-by-side
linkToPDF2.py
View file @
c830cc47
import
datetime
import
hashlib
import
os
from
enum
import
Enum
import
smtplib
from
dataclasses
import
dataclass
from
email
import
encoders
from
email.mime.base
import
MIMEBase
from
email.mime.multipart
import
MIMEMultipart
from
email.mime.text
import
MIMEText
from
pathlib
import
Path
from
typing
import
Optional
,
Dict
,
List
...
...
@@ -12,17 +17,79 @@ ATTACHEMENT_SIGN = "+"
FACHGRUPPENVOLLVERSAMMLUNG_SIGN
=
">"
TEMPLATE_FOLDER
=
"templates"
DATA_FOLDER
=
"data"
DEFAULT_GREMIUM
=
None
LDAP_USER
=
None
LDAP_PASSWORD
=
None
LDAP_MAIL
=
None
LDAP_NAME
=
None
class
Template
(
Enum
):
UNDEFINED
=
None
FINF
=
"pandoc.finf.tex"
FSR
=
"pandoc.fsr.tex"
TOPICS
=
"pandoc.topics.tex"
ATTACHEMENT
=
"pandoc.attachement.tex"
def
fullPath
(
self
):
return
str
(
Path
(
os
.
path
.
join
(
TEMPLATE_FOLDER
,
self
.
value
)).
absolute
())
@
dataclass
class
Gremium
:
name
:
str
template
:
str
def
fullTemplate
(
self
):
return
str
(
Path
(
os
.
path
.
join
(
TEMPLATE_FOLDER
,
self
.
template
)).
absolute
())
GREMIUM_FR
=
Gremium
(
"finf"
,
"pandoc.finf.tex"
)
GREMIUM_FSR
=
Gremium
(
"fsr"
,
"pandoc.fsr.tex"
)
@
dataclass
class
MailParticipant
:
mail
:
str
alias
:
str
=
None
def
__post_init__
(
self
):
self
.
alias
=
self
.
mail
def
__str__
(
self
):
return
f
"
{
self
.
alias
}
<
{
self
.
mail
}
>"
@
staticmethod
def
FR_INFO
():
return
MailParticipant
(
"fr-info@finf.uni-hannover.de"
,
"FR-Info"
)
@
staticmethod
def
FR
():
return
MailParticipant
(
"fr@finf.uni-hannover.de"
,
"Fachrat Informatik"
)
# Helper Functions
def
sendFRMail
(
text
:
str
,
subject
:
str
,
sender
:
MailParticipant
,
receivers
:
List
[
MailParticipant
],
attachement
:
"BasePad"
=
None
):
mail
=
MIMEMultipart
()
mail
[
'Content-transfer-encoding'
]
=
'8bit'
mail
[
'From'
]
=
sender
.
alias
mail
[
'Subject'
]
=
subject
receiveralias
=
", "
.
join
([
r
.
alias
for
r
in
receivers
])
mail
[
'To'
]
=
receiveralias
msg
=
MIMEText
(
text
,
"plain"
,
"utf-8"
)
mail
.
attach
(
msg
)
if
attachement
is
not
None
:
payload
=
MIMEBase
(
'application'
,
'octet-stream'
)
with
open
(
attachement
.
compiledPath
,
"rb"
)
as
d
:
payload
.
set_payload
(
d
.
read
())
encoders
.
encode_base64
(
payload
)
payload
.
add_header
(
'Content-Disposition'
,
f
"attachment; filename=
{
attachement
.
displayName
}
"
)
mail
.
attach
(
payload
)
try
:
server
=
smtplib
.
SMTP
(
"mail.finf.uni-hannover.de"
,
587
)
server
.
starttls
()
server
.
login
(
sender
.
mail
,
LDAP_PASSWORD
)
server
.
sendmail
(
sender
.
mail
,
[
r
.
mail
for
r
in
receivers
],
mail
.
as_string
())
server
.
quit
()
print
(
f
"Email
\"
{
subject
}
\"
an
{
receivers
}
erfolgreich versendet"
)
except
smtplib
.
SMTPException
:
print
(
f
"Fehler beim Senden der Email
\"
{
subject
}
\"
von
{
sender
}
an
{
receivers
}
"
)
raise
# === Source Types ===
...
...
@@ -59,48 +126,105 @@ class LocalCache(SourceTypes):
# === Pad Types ===
class
BasePad
:
def
__init__
(
self
,
source
:
SourceTypes
,
*
_
,
rawPath
=
None
,
**
kwargs
):
def
__init__
(
self
,
source
:
SourceTypes
,
*
_
,
displayName
:
str
=
None
,
rawPath
=
None
,
**
kwargs
):
self
.
source
=
source
self
.
metadata
=
kwargs
self
.
rawPath
=
rawPath
or
hashlib
.
md5
(
source
.
url
.
encode
(
"utf-8"
))
self
.
displayName
=
displayName
or
self
.
DEFAULT_DISPLAY_NAME
()
self
.
compiledPath
=
None
def
__repr__
(
self
):
return
f
"
{
self
.
__class__
.
__name__
}
(
{
self
.
source
}
)"
def
download
(
self
,
path
,
override
=
True
):
def
DEFAULT_DISPLAY_NAME
(
self
):
return
self
.
source
.
url
def
DEFAULT_RAW_PATH
(
self
):
return
os
.
path
.
join
(
DATA_FOLDER
,
"raw"
,
f
"
{
self
.
displayName
}
.md"
)
def
DEFAULT_COMPILED_PATH
(
self
):
return
os
.
path
.
join
(
DATA_FOLDER
,
"result"
,
f
"
{
self
.
displayName
}
.pdf"
)
def
download
(
self
,
path
=
None
,
override
=
True
):
if
path
is
None
:
path
=
self
.
DEFAULT_RAW_PATH
()
content
=
self
.
source
.
retrieveContent
()
if
not
override
and
os
.
path
.
exists
(
path
):
raise
FileExistsError
(
f
"
{
path
}
already exists!"
)
with
open
(
path
,
"w"
,
encoding
=
"utf-8"
)
as
d
:
d
.
write
(
content
)
self
.
rawPath
=
path
def
compile
(
self
,
outFilePath
,
template
:
Template
=
None
)
->
int
:
def
compile
(
self
,
outFilePath
:
str
=
None
,
template
:
str
=
None
)
->
int
:
if
outFilePath
is
None
:
outFilePath
=
self
.
DEFAULT_COMPILED_PATH
()
outPath
=
Path
(
outFilePath
)
os
.
makedirs
(
outPath
.
parent
,
exist_ok
=
True
)
metadataStr
=
" "
+
" "
.
join
([
f
'-M
{
key
}
="
{
val
}
"'
for
key
,
val
in
self
.
metadata
.
items
()])
templateStr
=
""
if
template
is
not
None
and
template
!=
Template
.
UNDEFINED
:
templateStr
=
f
' --template="
{
template
.
fullPath
()
}
" '
cmd
=
f
'pandoc "
{
self
.
rawPath
}
"
{
metadataStr
}{
templateStr
}
-o "
{
str
(
outPath
.
absolute
())
}
"'
return
os
.
system
(
cmd
)
if
template
is
None
and
hasattr
(
self
,
"gremium"
):
templateStr
=
f
' --template="
{
getattr
(
self
,
"gremium"
).
fullTemplate
()
}
" '
elif
template
!=
""
:
templateStr
=
f
' --template="
{
template
}
" '
cmd
=
f
'pandoc "
{
self
.
rawPath
}
"
{
metadataStr
}{
templateStr
}
-o "
{
str
(
outPath
.
absolute
())
}
"'
ret
=
os
.
system
(
cmd
)
if
ret
==
0
:
self
.
compiledPath
=
outFilePath
return
ret
class
ProtocolPad
(
BasePad
):
def
__init__
(
self
,
source
:
SourceTypes
,
*
_
,
date
:
datetime
.
datetime
=
None
,
isFachgruppenvollversammlung
:
bool
=
False
,
isApproved
:
bool
=
False
):
s
uper
().
__init__
(
source
)
isFachgruppenvollversammlung
:
bool
=
False
,
isApproved
:
bool
=
False
,
gremium
:
Gremium
=
None
):
s
elf
.
gremium
=
gremium
or
DEFAULT_GREMIUM
self
.
date
=
date
super
().
__init__
(
source
)
self
.
isApproved
=
isApproved
self
.
isFachgruppenvollversammlung
=
isFachgruppenvollversammlung
def
__repr__
(
self
):
return
super
(
ProtocolPad
,
self
).
__repr__
()[:
-
1
]
+
f
",
{
self
.
date
}
)"
def
sendMailAsApproved
(
self
)
->
bool
:
pass
def
DEFAULT_DISPLAY_NAME
(
self
)
:
return
f
"Protokoll
{
self
.
gremium
.
name
}
{
self
.
date
.
strftime
(
'%d.%m.%Y'
)
}
"
def
sendMailAsUnapproved
(
self
)
->
bool
:
pass
sender
=
MailParticipant
(
LDAP_MAIL
,
LDAP_NAME
)
receiver
=
[
MailParticipant
.
FR
()
]
text
=
(
f
"Hallo zusammen,
\n\n
"
f
"anbei das vorläufige Protokoll der Fachrats-Sitzung vom
{
self
.
date
.
strftime
(
'%d.%m.%Y'
)
}
.
\n\n
"
f
"Änderungswünsche bitte direkt an mich, bzw. mir kurz Bescheid geben, wenn ihr was im Pad geändert habt.
\n\n
"
f
"Viele Grüße
\n
"
f
"
{
LDAP_NAME
}
\n
"
)
subject
=
f
"Vorläufiges Protokoll der FR-Sitzung vom
{
self
.
date
.
strftime
(
'%d.%m.%Y'
)
}
"
try
:
sendFRMail
(
text
,
subject
,
sender
,
receiver
,
attachement
=
self
)
except
Exception
:
return
False
return
True
def
sendMailAsApproved
(
self
)
->
bool
:
if
not
self
.
isApproved
:
print
(
"Protocol is not approved yet!"
)
raise
PermissionError
(
"Protocol is not approved yet!"
)
sender
=
MailParticipant
(
LDAP_MAIL
,
LDAP_NAME
)
receiver
=
[
MailParticipant
.
FR_INFO
()
]
text
=
(
f
"Hallo zusammen,
\n\n
"
f
"anbei das Protokoll der Fachrats-Sitzung vom
{
self
.
date
.
strftime
(
'%d.%m.%Y'
)
}
.
\n\n
"
f
"Alle Protokolle sind zu finden unter:
\n
"
f
"https://cloud.finf.uni-hannover.de/index.php/s/Erw9Cbta0PruqZI
\n\n
"
f
"Viele Grüße
\n
"
f
"
{
LDAP_NAME
}
\n
"
)
subject
=
f
"Protokoll der FR-Sitzung vom
{
self
.
date
.
strftime
(
'%d.%m.%Y'
)
}
"
try
:
sendFRMail
(
text
,
subject
,
sender
,
receiver
,
attachement
=
self
)
except
Exception
:
return
False
return
True
def
uploadToCloud
(
self
)
->
bool
:
pass
...
...
@@ -214,9 +338,9 @@ if __name__ == '__main__':
raise
AttributeError
(
"Cannot have --finf AND --fsr"
)
if
parsed
.
finf
:
DEFAULT_
TYPE
=
"finf"
DEFAULT_
GREMIUM
=
GREMIUM_FR
if
parsed
.
fsr
:
DEFAULT_
TYPE
=
"fsr"
DEFAULT_
GREMIUM
=
GREMIUM_FSR
if
parsed
.
override
:
OVERRIDE_ACCEPTED
=
True
...
...
protokollGUI.py
View file @
c830cc47
import
tkinter
as
tk
from
functools
import
wraps
import
linkToPDF2
as
pter
...
...
@@ -38,33 +40,33 @@ class ProtokollGUI(tk.Tk):
def
updatePadFrame
(
self
):
folderName
=
list
(
self
.
folders
.
keys
())[
self
.
folderIndex
]
self
.
folderLabel
.
configure
(
text
=
folderName
)
self
.
currentPads
=
self
.
folders
[
folderName
]
self
.
currentPads
=
[
p
for
p
in
self
.
folders
[
folderName
]
if
isinstance
(
p
,
pter
.
ProtocolPad
)]
for
i
,
pad
in
enumerate
(
self
.
currentPads
):
assert
isinstance
(
pad
,
pter
.
ProtocolPad
)
or
isinstance
(
pad
,
pter
.
AttachementPad
)
assert
isinstance
(
pad
,
pter
.
ProtocolPad
)
tk
.
Label
(
self
.
padFrame
,
text
=
pad
.
source
.
url
,
anchor
=
tk
.
W
,
bg
=
"red"
).
grid
(
row
=
i
,
column
=
0
,
sticky
=
tk
.
W
)
# URL
tk
.
Label
(
self
.
padFrame
,
text
=
pad
.
date
,
anchor
=
tk
.
W
,
bg
=
"blue"
).
grid
(
row
=
i
,
column
=
1
)
# Date
# Button Download
btnDownload
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Download"
)
btnDownload
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Download"
,
command
=
pad
.
download
)
btnDownload
.
grid
(
row
=
i
,
column
=
2
)
# Button Compile
btnCompile
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Compile"
)
btnCompile
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Compile"
,
command
=
pad
.
compile
)
btnCompile
.
grid
(
row
=
i
,
column
=
3
)
# Button Mail FR
btnMailFR
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Vorläufige FR-Mail"
)
btnMailFR
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Vorläufige FR-Mail"
,
command
=
pad
.
sendMailAsUnapproved
)
btnMailFR
.
grid
(
row
=
i
,
column
=
4
)
# Button Mail FR-Info
btnMailFRInfo
=
tk
.
Button
(
self
.
padFrame
,
text
=
"FR-Info Mail"
,
state
=
tk
.
DISABLED
)
btnMailFRInfo
=
tk
.
Button
(
self
.
padFrame
,
text
=
"FR-Info Mail"
,
state
=
tk
.
DISABLED
,
command
=
pad
.
sendMailAsApproved
)
btnMailFRInfo
.
grid
(
row
=
i
,
column
=
5
)
# Button Website
btnWebsite
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Approved Website"
,
state
=
tk
.
DISABLED
)
btnWebsite
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Approved Website"
,
state
=
tk
.
DISABLED
,
command
=
pad
.
uploadToGrav
)
btnWebsite
.
grid
(
row
=
i
,
column
=
6
)
# Button Cloud
btnCloud
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Approved Cloud"
,
state
=
tk
.
DISABLED
)
btnCloud
=
tk
.
Button
(
self
.
padFrame
,
text
=
"Approved Cloud"
,
state
=
tk
.
DISABLED
,
command
=
pad
.
uploadToCloud
)
btnCloud
.
grid
(
row
=
i
,
column
=
7
)
...
...
@@ -72,6 +74,7 @@ class ProtokollGUI(tk.Tk):
if
__name__
==
'__main__'
:
# gui = ProtokollGUI(pter.LocalCache("data/rootPad.md"))
gui
=
ProtokollGUI
(
pter
.
CodiMD
(
"https://pad.finf.uni-hannover.de/protokolllinks_terces"
))
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment