C# – Combobox Anzeige von mehreren kombinierten Datenfeldern (DisplayMemeber)

Vor kurzem wurde im Zuge eines Projektes  (Unterstützung eines Entwickler Teams für eine Winform Anwendung im Logistikumfeld) unter anderem die Anforderung an mich heran getragen, dass der Kunde die Ansprechpartner für eine bestimmte Logistische Aktivität aus einer Combobox auswählen möchte.

Hierbei sollte in der Combobox, nicht nur ein Feld aus der Datenbank angezeigt werden, sondern die Anzeige sollte aus insgesamt 2 Feldern zusammengebaut werden.

Das Format sollte so aussehen: Nachname, Vorname

Hier ein Beispiel:

Mustermann, Hans

Dabei sollte die Lösung vollkommen im Client implementiert sein und nicht durch eine geänderte Abfrage der Datenbank realisiert werden.

Nun ist es aber so, dass man dem DisplayMember nur ein Feld der Datengebundenen Tabelle (Objekt) zuweisen kann und nicht mehrere oder sogar wie hier gewünscht diese Felder auch noch in einem bestimmten Format.

Sicherlich könnte man sich ein eigenen Objekt (List Objekt) erzeugen welches man dann als Datenquelle für die Bindung verwendet, aber es geht auch (viel) einfacher.

Hierzu verwenden wir dem Format Event der Combobox.

Dieser Event bekommt zwei Parameter mit übergeben:

object sender

ListControlConvertEventArgs e

Wobei wir für die hier beschriebene Lösung lediglich den ListControlConvertEventArgs Parameter benötigen und auch verwenden.

in e.ListItem wird das Datengebundene Objekt übergeben und in e.Value kann man den gewünschten Wert zurückgeben.

Hier ein zusammenhängendes Beispiel:

private void cmbSpediteurKontakt_Format(object sender, ListControlConvertEventArgs e)
{
	// Hier caste ich mir den übergeben Wert in das original Objekt
	var spediteurKontakt = ((SpediteureKontakte) e.ListItem);  
	// Und nun bastele ich mir die gewünschet Anzeige zusammen
	e.Value = String.Format("{0}, {1}", spediteurKontakt.Nachname, spediteurKontakt.Vorname);
}

Und das Ergebnis sieht dann so aus:

image

Thunderbird 3.0 RC1 verfügbar

Seit Heute Morgen ist der erste Release Kandidat der neuen 3.0 Version von Thunderbird verfügbar.

Einen direkten Link zum herunterladen konnte ich zwar nicht finden, aber wer die Beta 4 auf einem Rechner hat, kann mit dem “Auf Update prüfen” seine Version aktualisieren.

Auf dieser Seite finden man die Links zu den Downloads.

Logitech MX 3200 Laser – Zoom Funktion abschalten

Seit ein paar Wochen habe ich eine Logitech MX 3200 Laser Tastatur / Maus Kombination im Einsatz.

Außer der störenden Zoomfunktion am linken Rand bin ich auch sehr zufrieden.

Verzweifelt habe ich nach einer Lösung gesucht diese Zoom Funktion zu deaktivieren und habe nichts gefunden.

Heute bin ich dann durch Zufall auf die Lösung gestoßen.

Hier der Link zur Web Seite mit der Lösung

Besten Dank an Cord-Heinrich Pahlmann

C# – DateTimePicker – UpDown – fehlende Eigenschaft Increment nachgebildet

In einer Windows Anwendung wird in einer Form unter anderem ein (eigentlich sind es zwei, aber dazu später mehr) DateTimePicker verwendet um Termine einzugeben.

Da der DateTimePicker nicht gerade komfortabel ist um sowohl Datum als auch Uhrzeiten einzugeben, wird ein DateTimePicker in der Option DropDownCalender (das ist deaktivierte Eigenschaft ShowUpDown) eingesetzt um das Datum elegant aus dem DropDownCalender auszuwählen und ein zweites DateTimePicker Control mit der gesetzen Eigenschaft ShowUpDown und dem entsprechenden Custom Format HH:mm um nur die Uhrzeit mit den Pfeilen hoch und runter einstellen zu können.

image

Nun ist es aber so, dass man im DateTimePicker keinen Inkrement Wert eingeben kann, um den die Minuten erhöht bzw vermindert werden wenn man einmal auf den Pfeil hoch oder runter klickt. Somit wird jeweils um eine Minute hoch oder runter gezählt.

In meinem Fall nun wollte der Kunde aber das Termine nicht Minutengenau sondern immer auf 15 Minuten (Viertelstunde) Basis, also 00, 15, 30 und 45 erfasst werden können.

Da ich nicht gleich ein eigenen Control entwickeln wollte, habe ich einfach eine kleine Routine in den Change Event des DateTimePicker eingebaut.

Nachfolgend der Code Ich denke die Routine ist selbsterklärend

private void startzeitTimePicker_ValueChanged(object sender, EventArgs e)
{
    DateTimePicker dtp = (DateTimePicker)sender;
    // Wenn nicht Minute nicht 0,15,45 oder 60 dann müssen wir was tun
    if ((((dtp.Value.Minute != 0) && (dtp.Value.Minute != 15)) && (dtp.Value.Minute != 30)) &&
        (dtp.Value.Minute != 45))
    {
        // Auch noch einfach, nur 14 Minuten drauf und gut ist
        if ((dtp.Value.Minute == 1) || (dtp.Value.Minute == 16) || (dtp.Value.Minute == 31) || (dtp.Value.Minute == 46))
        {
            dtp.Value = dtp.Value.AddMinutes(14);
        }
        else
        {
            // Zeit wurde heruntergezählt.
            if ((dtp.Value.Minute == 14) || (dtp.Value.Minute == 29) || (dtp.Value.Minute == 44) || (dtp.Value.Minute == 59))
            {
                int x = 14;     // Deshalb auf jeden Fall mal 14 Minuten abziehen,
                if (dtp.Value.Minute == 59)  // und wenn die Minuten auf 59 stehen, dann muss noch eine Stunde (60 minuten) mehr abgezogen werden
                {
                    x += 60;
                }
                dtp.Value = dtp.Value.AddMinutes(-x);
            }
            else // Wert muss manuell eingegeben worden sein, dann runden wir auf die nächst höhere Viertelstunde
            {
                for (int i = 0; i < 15; i++)
                {
                    int x = dtp.Value.Minute + i;
                    if ((x == 15) || (x == 30) || (x == 45) || (x == 60))
                    {
                        dtp.Value = dtp.Value.AddMinutes(i);
                        break;
                    }
                }
            }
        }
    }
}

Hoffe das hilft dem einen oder anderen (Oder mir selbst beim nächsten mal wenn ich vor dem gleichen Problem stehen Wink)

C# – ArrayList.Sort mit Komplexen Klassen (IComparer Implementierung)

In einer Anwendung verwende ich eine Klasse um die Appointmens eines Kalenders abzubilden. Diese Klasse ist relativ Komplex und um diesen Beitrag nicht ebenfalls zu komplex werden zu lassen, verwende ich hier eine (sehr) abgespeckte Version dieser Klasse um das Thema Sortierung einer ArrayListe von Komplexen Objekten zu veranschaulichen.
Die Verwendung einer ArrayList war hier zwingend vorgeschrieben (typisierte Listen List<Type> kamen nicht in Frage)

Zuerst einmal die Aufgabenstellung:

In einer ArrayListe (nennen wir Sie AppointmentList) befinden sich Termine in Form von Objekten (nennen wir sie Appointment). Diese Objekte haben unter anderem eine Eigenschaft (Property) Startdatum (vom Type DateTime).

Da die Appointment in der AppointmentList unsortiert vorliegen und eine Sortierung (eigentlich zwei Sortierungen Auf und Absteigend) nach dem Startdatum des Termins benötigt wird, bestand die Aufgabe die AppointmentList zu sortieren.

Die ArrayLIst verfügt über eine Methode Sort. Da es sich bei den zu sortierenden Objekten aber um ein Komplexe Klasse handelt, muss man der Sort Methode einen Comparer an die Hand geben, damit die Methode Sort Ihre Aufgabe durchführen kann.

Hier nun die Umsetzung:

Zuerst einmal die (komplexe) Klasse Appointment (eine abgespeckte Variante)

public class Appointment
{

    public Appointment()
    {
        appointmentGUID = Guid.NewGuid();
    }


    private readonly Guid appointmentGUID = new Guid("00000000000000000000000000000000");

    public Guid AppointmentGUID
    {
        get { return appointmentGUID; }
    }

    private DateTime startDate;

    public DateTime StartDate
    {
        get { return startDate; }
        set
        {
            startDate = value;
            OnStartDateChanged();
        }
    }

    protected virtual void OnStartDateChanged()
    {
    }


    private DateTime endDate;

    public DateTime EndDate
    {
        get { return endDate; }
        set
        {
            endDate = value;
            OnEndDateChanged();
        }
    }

    protected virtual void OnEndDateChanged()
    {
    }



    private string title = "";

    [DefaultValue("")]
    public string Title
    {
        get { return title; }
        set
        {
            title = value;
            OnTitleChanged();
        }
    }

    protected virtual void OnTitleChanged()
    {
    }


    public override string ToString()
    {
        return Title;
    }

}

Der Comparer für diese Aufgabe sieht dann so aus (Methode zum Sortieren mit Implementierung der IComparer Schnittstelle:

public class AppointmentComparer : IComparer
{
    private bool descendSorting;
    public AppointmentComparer(bool descend)
    {
        descendSorting = descend;
    }

    int IComparer.Compare(object a, object b)
    {
        var b1 = (Appointment)a;
        var b2 = (Appointment)b;

        if (descendSorting)
        {
            return DateTime.Compare(b2.StartDate, b1.StartDate);
        }
        else
        {
            return DateTime.Compare(b1.StartDate, b2.StartDate);
        }
    }

}

Und verwenden kann man diesen Comparer wie folgt:

al.Sort(new AppointmentComparer(false));
            al.Sort(new AppointmentComparer(true));

al wurde dabei wie folgt deklariert:

ArrayList al = new ArrayList();

SQL – Größe aller Tabellen einer Datenbank

Beim stöbern in meinen SQL Skripten bin ich gerade wieder auf das hier nachfolgend aufgeführte Skript zur Ausgabe der “Größe aller Tabellen einer Datenbank” gestoßen.

Da ich sicherlich nicht der einzige bin, der diese Informationen einer Datenbank hin und wieder benötigt, veröffentliche ich hier das Skript mit der Hoffnung dass es jemand gebrauchen kann.

SET NOCOUNT ON
CREATE TABLE #TableSpace 
(
	Rows int, 
	DataSpaceUsed int, 
	IndexSpaceUsed int
)
DECLARE @TableSpace table
(
	TableName varchar(255),
	Rows int, 
	DataSpaceUsed int, 
	IndexSpaceUsed int
)
DECLARE @Rows int, @DataSpaceUsed int, @IndexSpaceUsed int
DECLARE @TableName varchar(255)
DECLARE Table_Cursor CURSOR FOR
SELECT	user_name(o.uid) + '.' + o.name AS table_name
FROM	dbo.sysobjects o, dbo.sysindexes i 
WHERE	OBJECTPROPERTY(o.id, N'IsTable') = 1 
	AND i.id = o.id 
	AND i.indid < 2 
	AND o.name NOT LIKE N'#%' 
	AND xtype = 'U'
ORDER BY 1
OPEN Table_Cursor
---------------------------------
--Set Data
FETCH NEXT FROM Table_Cursor INTO @TableName
INSERT INTO #TableSpace (Rows, DataSpaceUsed, IndexSpaceUsed)
EXEC sp_MStablespace @TableName
SELECT	@Rows = Rows, 
	@DataSpaceUsed = DataSpaceUsed,
	@IndexSpaceUsed = IndexSpaceUsed
FROM	#TableSpace
INSERT INTO @TableSpace (TableName, Rows, DataSpaceUsed, IndexSpaceUsed)
VALUES (@TableName, @Rows, @DataSpaceUsed, @IndexSpaceUsed)
DELETE FROM #TableSpace
--------------------------------
WHILE @@FETCH_STATUS = 0


    BEGIN
    	---------------------------------
    	--Set Data
    	FETCH NEXT FROM Table_Cursor INTO @TableName
    	
    	INSERT INTO #TableSpace (Rows, DataSpaceUsed, IndexSpaceUsed)
    	EXEC sp_MStablespace @TableName
    	
    	SELECT	@Rows = Rows, 
    		@DataSpaceUsed = DataSpaceUsed,
    		@IndexSpaceUsed = IndexSpaceUsed
    	FROM	#TableSpace
    	
    	INSERT INTO @TableSpace (TableName, Rows, DataSpaceUsed, IndexSpaceUsed)
    	VALUES (@TableName, @Rows, @DataSpaceUsed, @IndexSpaceUsed)
    	
    	DELETE FROM #TableSpace
    	--------------------------------
END

CLOSE Table_Cursor
DEALLOCATE Table_Cursor
DROP TABLE #TableSpace
SELECT * 
FROM @TableSpace
ORDER BY Rows DESC

Über die Herkunft dieses Skripts (ich weiß dass ich zumindest die Idee von irgendwoher hatte) bin ich mir nicht mehr sicher. Eine gerade durchgeführte Recherche im Internet hat mir auch keinen direkten Aufschluss gegeben woher ich das Skript oder die Idee dazu hatte.

Sollte also jemand die Herkunft kennen, bitte einfach per Kommentar posten.

DotNetNuke 4.09.04 Source Version und IE 8

Wenn man die Source Version von DotNetNuke Version 4.09.04 in Visual Studio ausführt und als Browser den Internet Explorer 8 einsetzt, kommt es beim überfahren der Menüs (Admin und Systemmenü) mit der Maus zu folgendem Fehler:

image

Dieser Fehler tritt in der Datei dnn.dom.positioning.js auf.

Die Zeile in welcher der Fehler auftritt lautet:

oIFR.style.zIndex=iIndex-1

Was geschieht ist, dass in der Variablen iIndex anstelle eines Wertes, das Wort “Auto” enthalten ist. Wenn nun versucht wird von dem String “Auto” den Wert 1 abzuziehen, kommt es natürlich zu einem Fehler.

Ich habe eine Lösung gefunden, die für mich funktioniert und nicht die Zeile einfach auskommentiert.

Die Lösung sieht wie folgt aus:

Ich füge am Ende der Datei dnn.dom.positioning.js die Funktion IsNumeric ein:

function IsNumeric(sText)

{
   var ValidChars = "0123456789.";
   var IsNumber=true;
   var Char;

 
   for (i = 0; i < sText.length && IsNumber == true; i++) 
      { 
      Char = sText.charAt(i); 
      if (ValidChars.indexOf(Char) == -1) 
         {
         IsNumber = false;
         }
      }
   return IsNumber;
   
   }

Und verwende diese Funktion wie folgt um den Inhalt der Variable iIndex zu prüfen und im Falle das darin kein numerischer Wert enthalten ist, führe ich die Subtraktion nicht aus.

Anstelle der Zeile (250) mit dem Inhalt oIFR.style.zIndex=iIndex-1;

füge ich nachfolgende 4 Zeilen ein, das sieht dann so aus:

if (IsNumeric(iIndex))
    oIFR.style.zIndex = iIndex - 1;
else
    oCont.style.zIndex = 1;

Nun einfach die Datei dnn.dom.positioning.js speichern und auch Fehlerfrei mit dem IE 8 und der Source Version von DotNetNuke arbeiten.

DotNetNuke 4.09.04 Source Version übersetzen

Wenn man versucht die Source Version von DotNetNuke 4.09.04 in Visual Studio 2008 zu öffnen und anschließend zu übersetzen, kommt es zu folgender Fehlermeldung:

Fehler	1	Datei "Controls\AJAX\bin\System.Web.Extensions.dll" kann nicht in "..\Website\bin\System.Web.Extensions.dll" kopiert werden. Ein Teil des Pfades "Controls\AJAX\bin\System.Web.Extensions.dll" konnte nicht gefunden werden.	C:\dnn494\Library\DotNetNuke.Library.vbproj	987	5	DotNetNuke.Library

Das Problem entsteht dadurch, dass versucht wird nach dem Übersetzungslauf die Datei System.Web.Extensions.dll aus dem Verzeichnis Controls\AJAX\bin\ in das BIN Verzeichnis von DotNetNuke zu  kopieren.

Dies ist aber gar nicht notwendig, da sich die Datei System.Web.Extensions.dll im GAC befindet.

Um den Fehler zu beheben, kann man die Datei DotNetNuke.Library.vbproj im Library Verzeichnis von DotNetNuke mit einem Texteditor öffnen, und nach dem Eintrag

<Copy SourceFiles=”Controls\AJAX\bin\System.Web.Extensions.dll” DestinationFolder=”..\Website\bin\” />

suchen, der Steht normal in der Zeile 987.

Diese Eintrag entfernt man und speichert anschließend die Datei ab.

Wenn man nun das Source Projekt mit Visual Studio öffnet und übersetzt sollte das Problem gelöst sein.

hMailServer – AntiVirus Optionen

Nachdem ich mich Gestern über das Thema Ziemlich Sicheres erkennen von SPAM” ausgelassen habe, möchte ich mich Heute, einem mindestens genau so wichtigen Thema, der Virus Erkennung und Abwehr in E-Mails unter Verwendung der hMailServer Bordmittel und lizenzfreien Zusatzprodukten widmen.

Wer den hMailServer einsetzt, wird die Optionen der AntiVirus Einstellungen kennen und sicherlich werden die meisten die einfache Clamwin Integration wählen.

hMailServer - Clamwin Integration

  • Clamwin installieren
  • Use Clamwin aktivieren
  • Auto-detect anklicken

Fertig !

Das ist sicherlich eine gute und einfache Lösung (vor allem ist es eine akzeptable Lösung) wenn auf dem Mail Server wenige Mails (einige Mails pro Stunde) verarbeitet werden. Für Installationen mit höherem Traffic (> 100 Mails/Stunde) stellt diese Installation aber ein echtes Performance Problem dar.

Clamwin benötigt wenn es durch den hMailServer aufgerufen wird um die Mails nach Viren zu untersuchen enorm viel Ressourcen des Computers. Wenn gleichzeitig mehrere Mails im hMailServer eintreffen, werden je nach Einstellungen mehrere Instanzen von Clamwin aufgerufen um die Mails einer Virenprüfung zu unterziehen. Dies führt unweigerlich dazu dass der Server mit nahezu 100% CPU Last nicht mehr viel Luft für andere Aufgaben hat.

Es gibt aber auch hierfür eine Lizenzkostenfreie Lösung und diese arbeitet mit der gleichen Scan Engine wie Clamwin.

image

ClamAV für Windows in der Variante von SOSDG.

Stand Heute ist die aktuelle Version der SOSDG Variante die 0.95-1, diese Version können wir aber für die Integration mit dem hMailServer “leider” nicht nehmen. Ich hoffe aber, dass bald eine fehlerbereinigte Version folgt, die dann die aktuellste ClamAV Engine einsetzen kann.

Um die Integration mit dem hMailServer zu realisieren müssen wir die Version clamav-0.94-2-1a.exe herunterladen und installieren.

Nachfolgend werde ich den Installationsprozess sowie die notwendigen Einstellungen im Detail erläutern.

Diese Anleitung basiert auf dem englischen Forumbeitrag von “rodolfor” im hMailServer Forum.

Schritt für Schritt Anleitung, oder in 9 Schritten zu einer performanten kostengünstige AntiVirus Lösung für hMailServer)

1. Herunterladen der clamav-0.94-2-1a Version

2. Installieren der clamav-0.94.2-1a Version

a) Setup ausführen

b) Als Installationstyp “Full auswählen (sonst werden benötigte Komponenten nicht installiert)

image

c) Dann den Setup mit den Standard Werten (am besten auch im Standard Verzeichnis) ausführen.

Zum Ende der Installation startet automatisch die Aktualisierung der Viren Signatur Datenbank.

image

d) Installation abschließen

3. Konfiguration “c:\clamav-devel\etc\clamav.conf” anpassen.  (Datei c:\clamav-devel\etc\clamav.conf mit einem Texteditor öffnen)

a) LocalSocket /cygdrive/c/clamav-devel/clamd.sock in der Datei suchen (eigentlich Zeile 82)

Diese Zeile durch das voranstellen eines # auskommentieren (siehe nachfolgende Zeile)

# LocalSocket /cygdrive/c/clamav-devel/clamd.sock

 

b) #TCPSocket 3310 in der Datei suchen (eigentlich Zeile 90)

In dieser Zeile das Kommentarzeichen # am Anfang entfernen (siehe nachfolgende Zeile)

TCPSocket 3310

 

c) Zur Aktivierung der Log Funktion (würde ich unbedingt empfehlen) folgende Einstellung vornehmen

#LogFileUnlock yes in der Datei suchen (eigentlich Zeile 32)

In dieser Zeile das Kommentarzeichen # am Anfang der Zeile entfernen (siehe nachfolgende Zeile)

LogFileUnlock yes

 

4. ClamAV (Hilfs)Dienst installieren

image

Hierzu öffnet man ein DOS (Kommando) Fenster.

Wechselt in das Verzeichnis C:\clamav-devel\thirdparty\runclamd

Gibt den Befehl runclamd -install ein und führt diesen aus

Wenn der Befehl erfolgreich durchgeführt wurde, gibt der Server im DOS Fenster “service installed” zurück.

image

Nun schließen wir das DOS Fenster

5. ClamAV (Hilfs)Dienst einrichten und starten

In den installierten Diensten suchen wir nun den Dienst Run Clamd

image

Öffnen das Eigenschaften Fenster

image

Und stellen den Starttyp für den Dienst von Manuell auf Automatisch

image

Nun starten wir den Dienst (dieses mal mit der Hand) beim nächsten Start wird er Automatisch gestartet.

6. Beheben von Zugriffproblemen der Log Datei

Wer möchte kann kann versuchen nun schon die Log Datei clamd.log im Verzeichnis C:\clamav-devel\log zu öffnen. Es wird schnell klar dass es nicht geht. Klar wird man denken, der Dienst greift ja darauf zu und deshalb ……
Nein das ist es nicht, wir haben übrigens in der Konfiguration Schritt 3c dem Program gesagt, dass wir die Log Datei lesen wollen. Also das Problem liegt nicht daran dass die Datei geöffnet ist, sondern (und da habe ich eine ganze Zeit suchen müssen) daran, dass die Zugriffsrechte für diese Datei etwas merkwürdig gesetzt sind.

Schauen wir uns doch mal die Rechte für diese Datei an:

image

Ich bin übrigens als Administrator an diesem System angemeldet, und trotzdem kann / darf ich die Rechte hier nicht ändern.

Es gibt aber einen ganz einfachen Trick wie wir hier weiterkommen. Hierzu betätigen wir den Button Erweitert und dort den Reiter Besitzer:

image

Hier sehen wir,dass der Besitzer das System ist. Das werden wir nun einfach ändern, indem wir den Besitzer ändern auf “Administratoren”.

Wenn wir nun alle Rechte Fenster geschlossen und das Fenster der Dateiberechtigungen noch einmal öffnen:

image

Können wir auch das Lesen Recht für Jeden (oder wie auch immer) setzen (Und danach auch die Log Datei öffnen).

7. ClamAV in hMailServer eintragen und aktivieren

Nun müssen wir die nachfolgenden Einstellungen im hMailServer Administrations Tool im Bereich Anti-Virus vornehmen

image

Auf der Karteikarte External Virus Scanner nehmen wir folgende Einstellungen vor:

image

  • Use external scanner (aktivieren)
  • Im Feld Scanner executable wird “C:\clamav-devel\bin\clamdscan.exe” –no-summary –stdout “%FILE%” eingetragen (Mit den “)
  • Im Feld Return Value wird 1 eingegeben

 

8. Automatische Aktualisierung der Virus Signaturen einrichten

Einrichten eines geplanten Task für die Datei C:\clamav-devel\bin\freshclam.exe. Zum Beispiel Alle 2 Stunden

image

 

9. Tests

Zum Abschluss sollte man noch testen, ob alles einwandfrei funktioniert. Hierzu möchte ich zwei Beispiele geben, um den Viren Scanner und die Implementierung im hMailServer zu testen

Scanner testen

In einem geöffneten DOS Fenster gibt man die folgende Befehlszeile ein und führt sie aus:

“C:\clamav-devel\bin\clamdscan.exe” –no-summary –stdout “C:\clamav-devel\test\clam-nsis.exe”

Wenn der Scanner richtig installiert ist wird nach dem ausführen des Befehls die folgende Antwort im DOS Fensters zurückgegeben:

image 

Integration testen

Um die Mail Integration zu testen schickt man ein E-Mail mit der Datei C:\clamav-devel\test\clam-nsis.exe als Anhang an eine bekannte (eigene) E-Mail Adresse.

Wenn die Integration erfolgreich war, dann solle der Anhang von ClamAV über den hMailServer herausgefiltert werden.

Nachdem die beiden Tests durchgeführt sind, sollte man noch das Protokoll C:\clamav-devel\log\clamd.log anschauen. Dort sollten auf jeden Fall Protokolleinträge für die beiden Test aufzufinden sein.

hMailServer – “Ziemlich” Sicheres erkennen von SPAM

Ich habe seit vielen Jahren den hMailServer in verschiedenen Installationen, sowohl als eigenständigen E-Mail Server als auch im Zusammenspiel (als ESMTP Server) mit MS Exchange Server, im Einsatz. In kleinen und mittleren Betrieben ist hMailServer sicherlich eine günstige (da Lizenzkostenfrei) alternative zu einem hochpreisigen Produkt wie dem Microsoft Exchange Server. Vor allem dann, wenn es hauptsächlich um E-Mail geht und die Groupware Funktionen eines Exchange Server nicht benötigt werden.

Wobei ich gleich hier erwähnen möchte, dass die hier beschriebene Version des hMailServer über IMAP nun auch öffentlichen Ordner zur Verfügung stellt.

Nun aber zum eigentlichen Thema dieses Beitrags,:

“Ziemlich” Sicheres erkennen von SPAM !!!

In der heutigen Zeit ist das Thema SPAM so aktuell wie noch nie.

Ich persönlich erhalte täglich zwischen 300 und 1000 SPAM Mails (Das liegt sicherlich auch daran, dass ich schon seit über 20 Jahren mit teilweise den gleichen E-Mail Adressen arbeite).

Auch wenn es mittlerweile sehr gute SPAM Filter gibt, so kann man doch meistens die als SPAM erkannten Mails nicht einfach löschen, da hier und da doch einmal ein E-Mail welches man benötigt vom SPAM Filter als SPAM erkannt wird.

Was bleibt ist, die SPAM Mails in einen Ordner umzuleiten und diese bevor man sie löscht zu überfliegen um die eine oder andere “normale” Mail auszusortieren bevor man die “richtigen” SPAM Mails löscht.

Wenn man nun aber, wie ich bis zu 1000 SPAM Mails am Tag erhält, dann ist das fast ein Tagfüllender Job, vor allem dann, wenn man E-Mails zeitnahe bearbeitet.

Wenn man doch nur mehr Zuverlässigkeit in der Erkennung der SPAM Filter erreichen könnte !!!

Man kann !! (wenn man den hMailServer einsetzt)

Und das ganze auch noch vollkommen ohne zusätzliche Kosten mit den Bordmitteln von hMailServer, ohne zusätzliche Installation eines weiteren SPAM Filters wie Beispielsweise SpamAssassin.

Nun aber zur Theorie und der Praxis:

Der in hMailServer integrierte SPAM Filter besteht aus mehreren Komponenten:

Zuerst sind sind das die “einfachen” SPAM Test varianten:

image

  • Verwendung SPF (nicht sehr aussagekräftig da noch viele dieses Feature nicht nutzen)
  • HELO Prüfung (lest selber wie zuverlässig diese Prüfung ist)
  • DNS-MX Record (eigentlich sollte den jeder haben, aber auch hier würde ich nicht sehr viel Aussagekraft bescheinigen)
  • DKIM-Signatur (meiner Meinung nach noch nicht verbreitet genug um aussagekräftig zu sein)

Auch wenn diese einfachen SPAM Test verfahren im einzelnen nicht sehr viel Aussagekraft haben, so kann doch das auftreten mehrerer dieser Testergebnisse ein zusätzliches Merkmal zur Erkennung von “echter” SPAM sein.

Wie man schon auf der obigen Abbildung erkennen kann ist jedem der Testverfahren ein Score zugeordnet. Dieser Score wird noch eine entscheidende Rollen in diesem Beitrag spielen. Mehr dazu später.

Nu gibt es außer den einfachen Tests noch weitere SPAM Erkennungsverfahren:

image

Neben den für diesen Beitrag nicht relevanten Verfahren des Grey- und Whitelisting  widmen wir den beiden SPAM Erkennungsverfahren die für diese Beitrag relevant sind:

DNS Blacklist

DNS Blacklist Server sind im Prinzip Server die Listen von IP Adressen enthalten die als Herkunft von zweifelhaften Mails bekannt sind.

Man kann unter hMailServer mehrere solcher DNS Blacklisten einrichten.

image

Ich habe hier die beiden oben dargestellten Blacklist Server eingerichtet.

Man kann bei jedem der Blacklist Server wieder einen Score vergeben (mehr dazu später):

image

SURBL Server

Wie bei den DNS Blacklisten kann man bei den SURBL Servern auch mehrere einrichten. Wie aus der nachfolgenden Abbildung zu sehen ist, begnüge ich mich mit einem:

image

Und wen wundert es, wenn ich sage, man kann jedem SURBL Server wiederum einen Score zuweisen kann.

Nun möchte ich nicht auf die Arbeitsweisen der einzelnen SPAM Prüfverfahren eingehen, dafür kann man die Links verwenden und von Menschen die wirklich was davon verstehen die Einzelheiten zu den einzelnen Verfahren nachlesen.

Jetzt aber endlich zum Thema “SPAM score” auf das ich im gesamten Verlauf des Beitrags schon mehrfach hingewiesen habe.

Auf der Einstiegsseite des Anti Spam Konfiguration des hMailServer finden wir unter anderem den folgenden Eintrag:

image

Die einzelnen Testverfahren besitzen jeweils einen score, der von hMailServer beim durchlaufen der SPAM Filter zu einem Wert (dieses SPAM mark treshold) addiert werden.

Erst wenn die Summe der Score aus den einzelnen Testverfahren diesen Schwellwert (hier sind es 5) übersteigen wird die Mail als SPAM gekennzeichnet.

Unabhängig dieser Kennzeichnung wird aber der Score (Summe aller SPAM Score der Prüfverfahren welche die Mail als SPAM identifiziert haben) auch als X-Header in das E-Mail eingefügt.

Dieser X-Header lautet: X-hMailServer-Reason-Score

Dieses Header kann man mit den meisten E-Mail Programmen aber auch direkt mit dem Regelassistent des hMailServer abfragen.

Und genau hierdurch haben wir eine einfache Möglichkeit mit hoher Genauigkeit SPAM Mails erkennen zu können..

Am besten veranschauliche ich das an einem Beispiel:

Eine eingehende Mail wird von hMailServer empfangen und wird durch die “einfachen” SPAM Tests durchlaufen.

Daraus resultiert ein SPAM core von 2 weil kein die HELO Prüfung fehlgeschlagen ist.

Nun wird der DSN Blacklist Test durchlaufen und auf dem Server bl.soamcop.net wird die IP Adresse des Absender gelistet, dadurch wird der Score um 3 erhöht. Somit ist der SPAM score nun 5.

Als nächstes erfolgt der SURBL SPAM Test und auch dort wird der Mail Inhalt als mögliche SPAM Mail erkannt was den SPAM core noch einmal um 3 erhöht. Das bedeutet der SPAM core ist nun 8.

Nun, da ich ein Kriterium an der Hand habe um “sichere” SPAM Mails von “eventuellen” SPAM Mails unterscheiden zu können kann ich ein weiteres Feature des hMailServer verwenden um Mails mit einem SPAM Core > X direkt zu löschen.

Dies kann ich, mit dem ebenfalls im hMailServer direkt enthaltenen Regelassistenten, welcher unter dem jeweiligen Account des Benutzer (Im Administrationstools zu finde ist, einfach bewerkstelligen.

image

Hier richte ich eine neue Regel mit den nachfolgenden Kriterien ein:

image

Bei den Aktionen wird Delete E-Mail ausgewählt.

image

Ich habe zusätzlich noch ein “Stop Rule Processing” verwendet, damit nach dem löschen der Mail nicht noch versucht wird weitere Regeln zu durchlaufen. (Ist ja keine Mail mehr vorhanden Smile)

Nach diesem Prinzip kann man natürlich ohne Grenzen andere Regeln definieren, wie das verschieben von Mails in einen speziellen IMAP Ordner die manuell geprüft werden müssen usw.

Die X-Header die von hMailServer eingefügt werden können alternativ auch von Mail Clients (z.B. Thunderbird, Outlook usw.) zur Ausführung von lokalen Regeln und Skripten verwendet werden.

Übrigens: Die hier beschriebenen Feature sind enthalten im hMailServer Version 5.1.2