Nachdem wir in den drei ersten Teilen zunächst OpenLDAP, Dovecot und Exim eingerichtet haben, geht es nun daran, getmail so einzurichten, dass Mails von einem externen Server via POP3 oder IMAP abgerufen werden und dann dem entsprechenden lokalen Benutzer zugestellt werden. Obwohl fast alles im Blog detailliert beschrieben ist, empfehle ich, die Konfigurationsdateien für das Mailsystem herunterzuladen.
Installation
Wir installieren getmail und das benötigte python-Modul durch den Befehl
sudo apt-get install getmail4 python-ldap |
Konfiguration zum Mailabruf von externen Servern
Der Benutzer secmail wird für uns alle Mails abholen und an den jeweiligen Nutzer zustellen. Für diesen Zweck habe ich das Python-Skript getmail-ldap.py geschrieben. Es liest zunächst die Login-Daten aller externen Mail-Accounts aus dem LDAP-Verzeichnis und erzeugt für jeden Mailaccount eine entsprechende Konfigurationsdatei zur Verwendung mit getmail. Anschließend ruft es getmail auf und benachrichtigt im Falle einer Fehlermeldung den Administrator per E-Mail. Die folgenden Schritte führen wir unter dem Benutzer secmail durch, damit die Dateien mit der entsprechenden Berechtigung erzeugt werden. Dazu rufen wir sudo auf:
sudo -u secmail -s |
Den folgenden Inhalt
#!/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 ldap.cidict import cidict 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, 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 self.attrs.has_key( attr_name ) 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 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.iteritems(): 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','("'+newRetrieveAccount.account_name+'",)') 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(0077) 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) # 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_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.open(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!") |
speichern wir als /home/secmail/getmail-ldap.py und machen die Datei durch ein
chmod 750 getmail-ldap.py |
ausführbar. Das Skript besitzt eine Konfigurationsdatei unter /home/secmail/getmail-ldap.cfg mit dem Inhalt
[Main] # Path to getmail GetmailBinary=/usr/bin/getmail # Directory that should be used as a storage by getmail GetmailDir=/home/secmail/getmail_data # Read default values for getmail from this file DefaultGetmailConfigFile=/home/secmail/getmailrc_template.cfg # Save the final configuration files which include the LDAP details to this directory ConfigFileOutputDir=/home/secmail/getmail_config [Logging] # Write messages to the following log file LogFile=/var/log/getmail-ldap.log # If a severe error occures a mail goes to the admin # SMTP-Server to use for sending this error notification MailServer=localhost # Mail address of the sender of this error notification MailFrom=secmail@myserver # Recipients of this error notification # separate multiple recipients by comma MailTo=root@myserver # Subject of the error notification MailSubject=Getmail-LDAP Error [LDAP] # Read LDAP information from this server LDAPServer=myserver # Authenticate with the following DN BindDN=uid=secmail, ou=users, o=effinger # Authenticate with the following password BindPassword=mysecmailpassword # Restrict search of external mail accounts to this DN SearchDN=ou=users, o=effinger # Scope of search for external mail accounts # Possible values include SUB, ONE and BASE SearchScope=SUB # Identify external mail accounts with the following filter SearchFilter=(&(dcSubMailAddress=*)(objectClass=dcExternalMailAccount)(dcAccountStatus=active)(dcRetrieveType=*)(dcRetrieveLogin=*)(dcRetrievePassword=*)) # List of LDAP-Attributes used to determine the following variables # 1. Name for resulting getmail configuration file (must be unique) # 2. Type for mail collection e.g. BrokenUIDLPOP3Retriever # 3. Mail server to collect mails from # 4. Login for mail server # 5. Password for mail server # separate by comma RelevantAttributes=dcSubMailAddress,dcRetrieveType,dcRetrieveServer,dcRetrieveLogin,dcRetrievePassword |
Die Konfigurationsoptionen habe ich durch Kommentare dokumentiert. In jedem Fall muss in dieser Datei im Abschnitt [LDAP] der LDAPServer von myserver auf den jeweiligen DNS-Eintrag des OpenLDAP-Servers angepasst werden. Auch die Zeile mit BindPassword müssen wir ändern, so dass sie das secmail Passwort enthält. Da diese Datei mit dem Passwort sensible Informationen enthält, die es einem Angreifer erlauben würden, aus dem LDAP-Verzeichnis alle Login-Informationen der externen Mail-Accounts zu lesen, setzen wir die Berechtigung für die Datei so, dass nur secmail darauf zugreifen kann:
chmod 640 getmail-ldap.cfg |
Anschließend erzeugen wir die referenzierte Datei /home/secmail/getmailrc_template.cfg mit dem Inhalt
[retriever] type = server = username = password = [destination] type = MDA_external path = /usr/sbin/exim4 arguments = ("user@mailhost.tld",) [options] # for testing do not delete mails #delete = false delete = true message_log = /var/log/getmail.log read_all = true # do not manipulate the header delivered_to = false received = false |
Die einzelnen Konfigurationsoptionen werden in der Dokumentation von getmail detailliert erläutert. Wichtig ist hier zu wissen, dass das Python-Skript diese Datei als Vorlage nimmt und dann in der Sektion [retriever] die Werte für type, server, username und password aus dem LDAP-Verzeichnis einträgt. In der Sektion [destination] wird der Wert arguments so abgeändert, dass die Mail an den lokalen Benutzer geht. Das Zusammenspiel von getmail und exim wird in einem Forumsbeitrag näher erläutert.
Empfehlung: Zu Beginn ist es sicherlich sinnvoll, im Abschnitt [options] den Wert von delete auf false zu setzen. So werden die Mails vom externen Server zwar heruntergeladen, aber nicht gelöscht. Wenn alles einwandfrei funktioniert, kann man hier den Wert wieder auf true setzen.
Auch hier setzen wir die Berechtigungen für die Datei entsprechend:
chmod 640 getmailrc_template.cfg |
Nun erzeugen wir noch ein Verzeichnis, welches getmail benötigt und eines zum Ablegen der finalen Konfigurationsdateien mit den Berechtigungen, so dass nur secmail darauf zugreifen kann.
mkdir -m 750 /home/secmail/getmail_data /home/secmail/getmail_config |
Dann erzeugen wir die Logdateien im Verzeichnis /var/log und setzen die Berechtigung so, dass auch secmail in diese Dateien schreiben kann.
sudo touch /var/log/getmail{-ldap,}.log sudo chown root.secmail /var/log/getmail{-ldap,}.log sudo chmod 660 /var/log/getmail{-ldap,}.log |
Testen des Mailabrufs
Mit dem Aufruf des Pythonskripts durch ein
sudo -u secmail -s /home/secmail/getmail-ldap.py |
und das anschließende Inspizieren der Log-Dateien /var/log/getmail-ldap.log und /var/log/getmail.log können wir testen, ob die Mails heruntergeladen werden. Ob die Zustellung an den lokalen Benutzer geklappt hat, sieht man an neuen Dateien im jeweiligen maildir (hier: /home/paul/mail/paulpanzer@gmx.de/maildir/INBOX/new) bzw. durch Abruf der Mails mit einem Client z.B. per IMAP.
Regelmäßiges Zustellen externer Mails
Damit die Mails regelmäßig von dem externen Server abgerufen werden, richten wir einen Cron-Job ein, der alle fünf Minuten prüft, ob neue Mails vorhanden sind. Dazu führen wir als secmail User
crontab -e |
aus und tragen dort die Zeile
*/5 * * * * /home/secmail/getmail-ldap.py |
ein. Bei Adam Kane kann man nachlesen, was ein Cron-Job ist.
Feintuning – Logdateien mit Logrotate verwalten
Nachdem nun alles soweit eingerichtet ist, kümmern wir uns noch darum, dass die Logdateien ordentlich aufgeräumt werden. Wir erzeugen deshalb im Verzeichnis /etc/logrotate.d/ die Datei dovecot mit dem Inhalt
# Logrotate Konfiguration für dovecot /var/log/dovecot.log { daily missingok rotate 14 compress delaycompress notifempty create 600 root root } /var/log/dovecot-deliver.log { daily missingok rotate 14 compress delaycompress notifempty create 600 root secmail } |
und ebenso die Datei getmail mit diesem Inhalt
# Logrotate Konfiguration für getmail und getmail-ldap # siehe /home/secmail/getmail-ldap.py /var/log/getmail.log { daily missingok rotate 14 compress delaycompress notifempty create 660 root secmail } /var/log/getmail-ldap.log { daily missingok rotate 14 compress delaycompress notifempty create 660 root secmail } |
Wir korrigieren außerdem noch einen kleinen Bug im exim-Paket, indem wir die Zeile
create 640 Debian-exim adm |
in den beiden Dateien exim-base und exim-paniclog im selben Verzeichnis durch folgende Zeile ersetzen
create 640 Debian-exim root |
Tip zum Logging des OpenLDAP-Servers von der OpenLDAP-Mailingliste: Standardmäßig wird alles in die syslog geschrieben. Wenn man der Übersichtlichkeit halber eine eigene Logdatei für OpenLDAP haben möchte, muss man OpenLDAP mitteilen, dass es beim Loggen einen eigenen Selektor (hier:local4) verwenden soll. Dazu muss die Datei /etc/default/slapd die folgende Zeile enthalten:
SLAPD_OPTIONS="-l local4" |
Nun konfigurieren wir syslog so, dass es alle Informationen mit diesem Selektor in eine eigene Datei schreibt. Bei Verwendung von sysklogd ergänzen wir in der Datei /etc/syslog.conf folgende Zeile
# Log openldap to separate file local4.* -/var/log/slapd.log |
Bei Verwendung von rsyslog erzeugen wir die Datei /etc/rsyslog.d/40-slapd.conf mit folgendem Inhalt
# Log openldap to separate file local4.* -/var/log/slapd.log & ~ |
Außerdem legen wir eine entsprechende Datei namens /etc/logrotate.d/slapd mit dem folgenden Inhalt an.
/var/log/slapd.log { daily missingok rotate 14 compress delaycompress notifempty create 660 root openldap } |
Damit die Änderungen Wirkung zeigen, müssen wir anfangs eine Logdatei erzeugen und anschließend Syslog und OpenLDAP neu starten bzw. die Konfiguration neu laden.
sudo touch /var/log/slapd.log sudo chown root.openldap /var/log/slapd.log sudo chmod 660 /var/log/slapd.log sudo /etc/init.d/sysklogd reload sudo /etc/init.d/slapd restart |
Links zum getmail-ldap Python-Skript
Bei der Erstellung des Python-Skripts waren einige Webseiten sehr hilfreich, die deshalb hier aufgeführt werden, obowhl sie für die Einrichtung des Mailservers ohne Bedeutung sind.
- Einführung in Python – An Introduction to Python
- Eine weitere Einführung – Dive into Python
- Guter Stil bei der Python-Programmierung – Style Guide for Python Code
- Offizielle Dokumentation zum Logging-Modul von Python
- Beispielcode, welcher das Logging-Modul verwendet
- Offizielle Dokumenation zum LDAP-Modul von Python
- Beispiel zur Verwendung des LDAP-Moduls von Python
- Die LDAP-Helper Klasse, welche das Verarbeiten von LDAP-Resultaten wesentlich vereinfacht
- Grundlagen von Threading in Python
- Offizielle Dokumentation zum Subprozess-Modul von Python
- Beispielcode zur Verwendung von Unterprozessen in Doug Hellmanns Blog
- Verwendung von Unterprozessen ohne den Parameter Shell=True
Weitere Konfigurationsschritte
Die Schritte zur Einrichtung der im ersten Teil angesprochenen Komponenten Roundcube als Webmaildienst, LDAP zur Verwaltung von Addressen und Spamassassin zum Filtern von Spam-Mails sowie eine Anleitung zum Einrichten eins Mail-Clients werden aufgrund von Zeitmangel leider erst in einigen Wochen verfügbar sein.
Sehr gutes und ausführliches Tutorial. Danke dafür. 🙂
Danke für diese ausführliche Anleitung. Bin schon gespannt auf Teil 5 mit den Komponenten Roundcube und Spamassassin 🙂
Leider warte ich schon länger auf Teil 5…. 🙁
Ein sehr gutes Tutorial, welches unbedingt fortgesetzt werden müsste.
Teil 5 wird aller Voraussicht nach erst im November folgen, da ich bis Ende Oktober in Singapur bin und mein Ubuntu-Server in Deutschland solange down ist. Eigentlich wollte ich mir in Singapur einen neuen Rechner als Server zusammenstellen, aber da das teurer ist als in Deutschland übers Internet zu bestellen habe ich davon wieder Abstand genommen. Sorry für die Wartezeit!
Soeben habe ich mein System auf Karmic Koala aktualisiert mit der Folge, dass mein Python-Skript immer eine Fehler-Mail zustellte mit der Fehlermeldung
Der Bug ist bekannt, allerdings scheint sich niemand diesem anzunehmen. Mittlerweile ist aber in dem PPA Repository von Matthias Rosenkranz eine fehlerfreie Version vorhanden. Mit einem
kann man diese installieren. Bei mir funktioniert sie einwandfrei.
[…] Dovecot, Exim, OpenLDAP und getmail unter Ubuntu – (4) getmail Dovecot, Exim, OpenLDAP und getmail unter Ubuntu – (2) Dovecot […]
Hallo Markus,
vielen Dank für das Tutorial, wirklich sehr hilfreich.
Allerdings funktioniert bei mir das Versenden an remote hosts nicht, wobei ich mir nicht wirklich sicher bin ob das so überhaupt vorgesehen ist. Nach deinem Schema liefert exim ja entweder über den dovecot LDA, einen relay smtp oder eben „direct delivery via smtp“.
Das funktioniert bei mir allerdings nicht, wenn ich eine email an einen remote host senden will erfolgt eine Abfrage im ldap, natürlich ohne Ergebnis, dann wird der Vorgang beendet: „Unrouteable address“.
Soweit ich in /etc/exim4/conf.d/router/ sehen konnte, ist auch kein handling vorgesehen. Oder hab ich was überlesen?
Wie funktioniert bei dir der Versand von mails?
ich hatte auch noch ein paar kleinere Probleme mit dem Abrufen von mails mit getmail. auch bei gmx, vorallem das initiale downloaden von ca 4k mails:
Ich verwende SimplePOP3SSLRetriever, was mir erlaubt in getmailrc_template.cfg
read_all = false
delete = false
zu setzen – sonst werden jedes mal alle mails abgerufen. Außerdem bleibt getmail bei mir nach ca 1.6k mails hängen, wenn ich das python script verwende, ein manueller Aufruf des gleichen commandos hingegen funktioniert, warum auch immer. Die logs geben leider auch nichts aufschlussreiches her, aber die Option
max_messages_per_session = 512
schafft Abhilfe.
Hallo Philipp,
das Versenden von E-Mails wird je nach Account unterschiedlich gehandhabt:
1) Versenden von einem lokalen Mail-Account (user@localhost)
Der Versand klappt nur, wenn der Empfänger auch auf dem lokalen Mailserver ist (z.B. user2@localhost) oder aber für die Empfängeraddresse Mails von einem externen Account abgerufen werden. Der Versand an alle anderen Adressen klappt nicht. Beispiel: Du rufst die E-Mailaddresse user2@gmx.de ab und folglich kann user@localhost auch an user2@gmx.de Mails senden. Dabei laufen die Mails nicht über den GMX-Mailserver sondern werden direkt lokal zugestellt. Dagegen kann der lokale Benutzer keine Mails an beliebig@somedomain.net senden.
2) Versenden von externen Accounts (im Beispiel zuvor user2@gmx.de)
Zunächst werden die Mails falls möglich lokal zugestellt (also entweder an eine lokale Mailadresse oder eine, für die Mails abgerufen werden). Ist das nicht möglich, dann wird im LDAP-Verzeichnis der SMTP-Login und der SMTP-Server ausgelesen und die Mail via authentifiziertem SMTP versendet. Beispiel: user2@gmx.de schickt eine Mail an user@localhost, user2@gmx.de und beliebig@somedomain.net. Für die beiden ersten Adressen erfolgt die Zustellung lokal. Bei der letzten Adresse authentifiziert sich Exim als user2@gmx.de bei mail.gmx.net (dem GMX SMTP-Server) und schickt die Mail über diesen ab.
Die Konfiguration die hier vorgestellt wurde, dient mehr als Heimserver, der eigentlich keine Mails selbst handeln muss. Mittlerweile habe ich auch einen VServer am Laufen und handle die Mails an meine Domain selbst, daher musste ich meine Exim-Konfiguration etwas verändert. Bei Gelegenheit werde ich die neue Konfiguration mal hochladen.
Zu deinen Anmerkungen mit getmail:
Ich selbst habe noch keine Probleme festgestellt, wobei ich auch keine derartig großen Mengen an Mails abrufen musste. Für GMX nutze ich bislang den BrokenUIDLPOP3SSLRetriever. Evt. hängt es auch damit zusammen.
Viele Grüße und weiterhin viel Spaß mit exim und getmail
Markus
Hallo Markus,
zunächst einmal ein riesen Dankeschön für die Veröffentlichung deiner Kenntnisse. Ich hatte bereits einen Dovecot Server mit Getmail, Postfix und ssmtp am laufen, jedoch find ich deine Lösung mit ldap und exim um einiges eleganter. Also nochmals danke. Ich habe jedoch ebenfalls seit 2 Wochen einen vServer am laufen und würde gerne meine Konfiguration auf diesen Übertragen. Zusätzlich soll natürlich auch die eigene Domain damit verwaltet werden. Wäre also auch brennend an deiner erweiterten Exim Config interessiert und hoffe, das sich deine „Gelegenheit“ sehr bald findet 😉
Viele Grüße,
Philipp
Dieses Wochenende werde ich wohl dazu kommen. Also noch ein paar Tage Geduld 😉
Hallo Markus,
entweder bin ich blind oder du bist doch noch nicht dazu gekommen 🙁 Naja, ich gedulde mich einfach weiter und hoffe, das es irgendwann so weit ist 😉
Hat leider etwas länger gedauert, aber hier nun meine letzte exim.conf. Im Gegensatz zu der ursprünglich vorgestellten Konfiguration wird nun im LDAP-Directory auch bei lokalen Mailadressen immer die Domain mitangegeben. Außerdem sind einige kleine Veränderungen im Routing hinzugekommen sowie Spamprüfungen mit SPF.
Hi,
ich hab versucht deine Anleitung an mein System anzupassen. Das Auslesen der Accounts (bisher ein Testaccount) aus dem LDAP scheint zu klappen. Ich bekomme allerdings einen Fehler in der getmail-ldap.conf
INFO 2010-06-28 09:35:23,713 main_call 314 Writing Account Configuration for fetchtest@host-consultants.de to file /home/secmail/getmail_config/getmail_fetchtest@host-consultants.de.cfg
ERROR 2010-06-28 09:35:23,952 run 179 An error occured!
Traceback (most recent call last):
File „./getmail-ldap.py“, line 174, in run
+“\nStdOut: \n“ + string.join(getmail_process.stdout.readlines())
Exception: Getmail command failed for /usr/bin/getmail –rcfile=/home/secmail/getmail_config/getmail_fetchtest@host-consultants.de.cfg –getmaildir=/home/secmail/getmail_data
StdErr:
StdOut:
Leider bin ich in Phyton noch nicht so bewandert, hat jemand eine Ahnung woran es liegen könte?
Gruß Felix
Hat sich erledigt. Hatte einen falschen Wert für dcRetrieveServer gesetzt.
Hi Markus.
Schöne Anleitung. An sich genau das, was ich suchte. NUR: ich kriege ums verrecken den Exim nicht dazu eine externe Post auszuliefern.
Ich versuche von dem externen Test-Account (frank@franksaccount@web.de) auf eine andere externe Adresse zu senden. Alles was ich bekomme ist:
2011-01-04 13:52:07 H=franks.rechners.home [192.168.199.206] F= rejected RCPT : Unrouteable address
Lokale Post klappt (sowohl an frank@franks.rechners.home als auch an franksaccount.web.de).
Gibt es Ansätze, wo ich zu suchen anfangen sollte?
Gruß Frank.
Problem erkannt: exim darf auf dem ldap nicht dcSMTP* nicht lesen. Also liegts am slapd und nicht am exim. Nur verstehe ich das jetzt wiederum auch nicht…
Falls sich das Problem zwischenzeitlich nicht erledigt hat, bitte nochmal prüfen, ob der Schritt 7 weiter unten beim Punkt „OpenLDAP installieren“ von Teil 1 der Anleitung korrekt durchgeführt wurde.