ich versuche ein Programm zu starten und bekomme die Meldung:
Code: Alles auswählen
secmail@dsme01:/tmp/test$ ./getmail-ldap-new.py
Cannot find all required libraries please install them and try again
Code: Alles auswählen
secmail@dsme01:/tmp/test$ pip freeze > requirements.txt
Code: Alles auswählen
secmail@dsme01:/tmp/test$ cat requirements.txt
certifi==2022.12.7
charset-normalizer==2.1.1
docopt==0.6.2
idna==3.4
pipreqs==0.4.11
requests==2.28.1
urllib3==1.26.13
yarg==0.1.9
Code: Alles auswählen
secmail@dsme01:/tmp/test$ pip install -r requirements.txt
Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: certifi==2022.12.7 in /usr/local/lib/python3.10/site-packages (from -r requirements.txt (line 1)) (2022.12.7)
Requirement already satisfied: charset-normalizer==2.1.1 in /usr/local/lib/python3.10/site-packages (from -r requirements.txt (line 2)) (2.1.1)
Requirement already satisfied: docopt==0.6.2 in /usr/local/lib/python3.10/site-packages (from -r requirements.txt (line 3)) (0.6.2)
Requirement already satisfied: idna==3.4 in /usr/local/lib/python3.10/site-packages (from -r requirements.txt (line 4)) (3.4)
Requirement already satisfied: pipreqs==0.4.11 in /usr/local/lib/python3.10/site-packages (from -r requirements.txt (line 5)) (0.4.11)
Requirement already satisfied: requests==2.28.1 in /usr/local/lib/python3.10/site-packages (from -r requirements.txt (line 6)) (2.28.1)
Requirement already satisfied: urllib3==1.26.13 in /usr/local/lib/python3.10/site-packages (from -r requirements.txt (line 7)) (1.26.13)
Requirement already satisfied: yarg==0.1.9 in /usr/local/lib/python3.10/site-packages (from -r requirements.txt (line 8)) (0.1.9)
Code: Alles auswählen
secmail@dsme01:/tmp/test$ ./getmail-ldap-new.py
Cannot find all required libraries please install them and try again
Hier das Skript:
Code: Alles auswählen
secmail@dsme01:/tmp/test$ cat getmail-ldap-new.py
#!/usr/bin/python
# File: getmail-ldap.py
try:
import errno
import string
import logging
import logging.handlers
import ldap
import Configparser
import ldif
import threading
from StringIO import StringIO
from to import StringIO
from os.path import os
from subprocess import Popen,PIPE
except ImportError:
print("""Cannot find all required libraries please install them and try again""")
raise SystemExit
config_file_location = '/home/secmail/getmail-ldap.cfg'
def pid_exists(pid):
"""Is there a process with PID pid?"""
if pid < 0:
return False
exist = False
try:
os.kill(pid, 0)
exist = 1
except OSError as x:
if x.errno != errno.ESRCH:
raise
return exist
def get_search_results(results):
"""Given a set of results, return a list of LDAPSearchResult
objects.
"""
res = []
if type(results) == tuple and len(results) == 2 :
(code, arr) = results
elif type(results) == list:
arr = results
if len(results) == 0:
return res
for item in arr:
res.append( LDAPSearchResult(item) )
return res
class LDAPSearchResult:
"""A class to model LDAP results.
"""
dn = ''
def __init__(self, entry_tuple):
"""Create a new LDAPSearchResult object."""
(dn, attrs) = entry_tuple
if dn:
self.dn = dn
else:
return
self.attrs = cidict(attrs)
def get_attributes(self):
"""Get a dictionary of all attributes.
get_attributes()->{'name1':['value1','value2',...],
'name2: [value1...]}
"""
return self.attrs
def set_attributes(self, attr_dict):
"""Set the list of attributes for this record.
The format of the dictionary should be string key, list of
string alues. e.g. {'cn': ['M Butcher','Matt Butcher']}
set_attributes(attr_dictionary)
"""
self.attrs = cidict(attr_dict)
def has_attribute(self, attr_name):
"""Returns true if there is an attribute by this name in the
record.
has_attribute(string attr_name)->boolean
"""
return attr_name in self.attrs
def get_attr_values(self, key):
"""Get a list of attribute values.
get_attr_values(string key)->['value1','value2']
"""
return self.attrs[key]
def get_attr_names(self):
"""Get a list of attribute names.
get_attr_names()->['name1','name2',...]
"""
return list(self.attrs.keys())
def get_dn(self):
"""Get the DN string for the record.
get_dn()->string dn
"""
return self.dn
def pretty_print(self):
"""Create a nice string representation of this object.
pretty_print()->string
"""
str = "DN: " + self.dn + "\n"
for a, v_list in self.attrs.items():
str = str + "Name: " + a + "\n"
for v in v_list:
str = str + " Value: " + v + "\n"
str = str + "========"
return str
def to_ldif(self):
"""Get an LDIF representation of this record.
to_ldif()->string
"""
out = StringIO()
ldif_out = ldif.LDIFWriter(out)
ldif_out.unparse(self.dn, self.attrs)
return out.getvalue()
class RetrieveMails(threading.Thread):
def __init__(self, getmail_binary, config_filename, config_data_dir):
threading.Thread.__init__(self)
self.getmail_binary, self.config_filename, self.config_data_dir = \
getmail_binary, config_filename, config_data_dir
def run(self):
try:
command = [self.getmail_binary, \
#'--quiet', \
'--rcfile=' + self.config_filename, \
'--getmaildir=' + self.config_data_dir]
self.pid_filename = self.config_filename + '.pid'
# Check for a pidfile to see if the daemon already runs
try:
pid_file = file(self.pid_filename,'r')
pid_number = pid = int(pid_file.read().strip())
pid_file.close()
except IOError:
pid = None
# Check whether process is really running
if pid:
pid = pid_exists(pid)
if not pid:
getmail_process = Popen(command, shell=False,stdout=PIPE,stderr=PIPE)
try:
file(self.pid_filename,'w+').write("%s\n" % getmail_process.pid)
getmail_process.wait()
finally:
os.remove(self.pid_filename)
# Zur Sicherheit die erstellte Konfigurationsdatei loeschen (Login-Daten!)
os.remove(self.config_filename)
stderr_output=string.join(getmail_process.stderr.readlines())
if getmail_process.returncode != 0 or len(stderr_output.strip())>0 :
raise Exception("Getmail command failed for " + " ".join(command) \
+"\nStdErr: \n" + string.join(stderr_output.strip()) \
+"\nStdOut: \n" + string.join(getmail_process.stdout.readlines()))
else:
log_object.info("Command " + " ".join(command) +\
" not executed, existing pid " + str(pid_number) + " found")
except:
log_object.exception("An error occured!")
class RetrieveAccount:
account_name = None
account_type = None
login = None
password = None
server = None
def __init__(self, account_name=None, account_type=None, server=None, login=None, password=None):
self.account_name, self.account_type, self.login, self.password, self.server = \
account_name, account_type, login, password, server
class GetmailConfigFile(Configparser.SafeConfigParser):
output_filename = None
def __init__(self, defaults, default_config_filename=None, output_filename=None):
configParser.SafeConfigParser.__init__(self, defaults)
if default_config_filename is not None:
self.read(default_config_filename)
self.output_filename = output_filename
def set_pop3_account(self, newRetrieveAccount):
self.set('retriever','server',newRetrieveAccount.server)
self.set('retriever','type',newRetrieveAccount.account_type)
self.set('retriever','username',newRetrieveAccount.login)
self.set('retriever','password',newRetrieveAccount.password)
self.set('destination','arguments','("-i", "stefan.harbich@harnet.de",)')
def write(self):
if self.output_filename is not None:
"""try:
output_file = open(self.output_filename, 'wb')
except:
raise Exception, "Unable to open " + \
self.output_filename + "for writing"
finally:
output_file.close()
"""
os.umask(0o077)
output_file = open(self.output_filename, 'wb')
configParser.SafeConfigParser.write(self, output_file)
else:
raise Exception("No output file for configuration defined")
# Konfigurationsdatei lesen
config_object = Configparser.SafeConfigParser()
config_object.read(config_file_location)
# Set-up Logging
log_object = logging.getLogger("getmail-ldap")
## log_object.setLevel(logging.DEBUG)
log_object.setLevel(logging.ERROR)
# This handler writes everything to a log file.
log_file_handler = logging.FileHandler(config_object.get('Logging','LogFile'))
log_file_formatter = logging.Formatter("%(levelname)s %(asctime)s %(funcName)s %(lineno)d %(message)s")
log_file_handler.setFormatter(log_file_formatter)
## log_file_handler.setLevel(logging.DEBUG)
log_file_handler.setLevel(logging.ERROR)
log_object.addHandler(log_file_handler)
# This handler emails anything that is an error or worse.
log_smtp_handler = logging.handlers.SMTPHandler(\
config_object.get('Logging','MailServer'),\
config_object.get('Logging','MailFrom'),\
config_object.get('Logging','MailTo').split(','),\
config_object.get('Logging','MailSubject'))
log_smtp_handler.setLevel(logging.ERROR)
log_smtp_handler.setFormatter(log_file_formatter)
log_object.addHandler(log_smtp_handler)
def main_call():
## first you must open a connection to the LDAP server
ldap_object = ldap.initialize(config_object.get('LDAP','LDAPServer'))
ldap_object.simple_bind_s(\
config_object.get('LDAP','BindDN'),\
config_object.get('LDAP','BindPassword'))
# searching doesn't require a bind in LDAP V3.
# If you're using LDAP v2, set the next line appropriately
# and do a bind as shown in the above example.
# you can also set this to ldap.VERSION2 if you're using a v2 directory
# you should set the next option to ldap.VERSION2 if you're using a v2 directory
ldap_object.protocol_version = ldap.VERSION3
## The next lines will also need to be changed to support your search requirements and directory
## retrieve all attributes - again adjust to your needs - see documentation for more options
if config_object.get('LDAP','SearchScope').upper() == "SUB":
search_scope = ldap.SCOPE_SUBTREE
elif config_object.get('LDAP','SearchScope').upper() == "ONE":
search_scope = ldap.SCOPE_ONELEVEL
else:
search_scope = ldap.SCOPE_BASE
ldap_result_id = ldap_object.search( \
config_object.get('LDAP','SearchDN'), \
search_scope,
config_object.get('LDAP','SearchFilter'), \
None)
ldap_results = []
while 1:
result_type, result_data = ldap_object.result(ldap_result_id, 0)
if (result_data == []):
break
else:
## here you don't have to append to a list
## you could do whatever you want with the individual entry
## The appending to list is just for illustration.
if result_type == ldap.RES_SEARCH_ENTRY:
ldap_results += get_search_results(result_data)
for ldap_result in ldap_results:
account = RetrieveAccount( \
# Account Name \
ldap_result.get_attr_values(\
config_object.get('LDAP','RelevantAttributes').split(',')[0])[0] ,\
# Account Type \
ldap_result.get_attr_values(\
config_object.get('LDAP','RelevantAttributes').split(',')[1])[0],\
# Server \
ldap_result.get_attr_values(\
config_object.get('LDAP','RelevantAttributes').split(',')[2])[0],\
# Login \
ldap_result.get_attr_values(\
config_object.get('LDAP','RelevantAttributes').split(',')[3])[0],\
# Password \
ldap_result.get_attr_values(\
config_object.get('LDAP','RelevantAttributes').split(',')[4])[0]\
)
config_output_filename = os.path.join(\
config_object.get('Main','ConfigFileOutputDir'), \
"getmail_" + \
account.account_name + \
".cfg")
config_file = GetmailConfigFile(None, \
config_object.get('Main','DefaultGetmailConfigFile'), config_output_filename)
config_file.set_pop3_account(account)
log_object.info("Writing Account Configuration for " + account.account_name + \
" to file " + config_output_filename)
config_file.write()
RetrieveMails(\
config_object.get('Main','GetmailBinary'), \
config_output_filename, \
config_object.get('Main','GetmailDir')\
).start()
#print config_output_filename
#print "Name " + account.account_name
#print "Type " + account.account_type
#print "Server " + account.server
#print "Login " + account.login
#print "Password " + account.password
#print "-----------------"
#print ldap_result.pretty_print()
if __name__ == "__main__":
try:
main_call();
except:
log_object.exception("An error occured!")