Lokaler Mailserver mit MailCatcher unter Windows

Wer unter Windows Anwendungen entwickelt, die E-Mails versenden sollten, sieht sich schnell vor die Herausforderungen gestellt einen lokalen Mailserver zu Testzwecken aufzusetzen. Der Aufwand dafür ist immens. Hier kommt MailCatcher ins Spiel! MailCatcher ist ein Ruby gem, das einen einfachen SMTP Server und ein Webinterface zur Verfügung stellt.

Screen shot 2011-06-23 at 11.39.03 PM

Eine lokale Ruby Installation inkl. DevKit vorausgesetzt, lässt sich Mailcatcher wie auf der Website beschrieben installieren.

gem install mailcatcher

Nach erfolgreicher Installation kann Mailcatcher durch den Befehl mailcatcher gestartet werden. Als mögliche Parameter können u.a IP-Adresse und Port für den SMTP-Server und das Webinterface angegeben werden. Eine genau Übersicht der Parameter liefert

mailcatcher --help

Ohne weitere Parameter gestartet kann das Webinterface über die URL http://localhost:1080/ erreicht werden.
Der SMTP-Server lauscht auf dem Port 1025, SSL/TLS-Verschlüsselung werden derzeit nicht unterstützt, ebenso ist die Angabe von Benutzernamen und Passwort nicht nötig.

Laravel Database Seeding mit Faker

Das Problem dürfte vielen Entwicklern bekannt sein: Woher bekomme ich Testdaten während der Entwicklung einer Anwendung. Die manuelle Eingabe ist mühsam und kostet viel Zeit und während die Datenbank sich im Entwicklungsprozess verändert, müssen diese Daten immer wieder angepasst oder ergänzt werden.
Laravel bietet mit dem Database Seeding eine einfache Möglichkeit, Datenbaktabellen mit Testdaten zu füllen. Allerdings müssen auch diese zunächst manuell als Array erfasst werden.

Um den Prozess der manuellen Dateneingabe zu automatisieren und auch umfangreichere Datenmengen im Entwicklungsprozess zu verwenden, hat sich im PHP-Umfeld die Bibliothek Faker etabliert. Mit Hilfe von Faker können zufällige Testdaten für einen großen Pool von Datenklassen wie z.B. Vorname, Nachname, Anschrift, E-Mailadressen, Blindtexte bis hin zu zufälligen Bildern generiert werden. Über die Provider steht sogar eine Schnittstelle zu Verfügung, um Faker um eigene Inhaltstypen zu erweitern. Ein herausragendes Merkmal ist zudem die Lokalisierung der Testdaten.

Um Faker in das Laravel-Projekt einzubinden, muss die composer.json um die Zeile "fzaninotto/faker": "1.5.*@dev" ergänzt werden, um die neue Abhängigkeit zu definieren.

"require": {
		"laravel/framework": "4.2.*",
		"fzaninotto/faker": "1.5.*@dev"
	}

Alternative ließe sich die composer.json auch über den Befehl composer require fzaninotto/faker um den Eintrag ergänzen.

Mit dem Kommando composer update wird Faker dann geladen.


<?php

class UserSeeder extends Seeder {

	public function run(){
		// Faker mit deutscher Lokalisierung über Factory initialisieren
		$faker = Faker\Factory::create('de:DE');
		$faker->seed(1234); // Zufallsgenerator initialisieren
		// Wir laden dynamisch einen Provide rhinzu, um Passwörter zu generieren 
		$faker->addProvider(new Faker\Provider\Internet($faker));
		$users = array();
		for ($i=0; $i < 10000; $i++) { // Wir generieren 10.000 Testdatensätze

			$firstname = $faker->firstName; //Vorname über Generator
			$surname = $faker->lastName; // Nachname über Generator
			$initials = $firstname[0] . $surname[0]; 
			// Einen Datensatz für die Tabelle User definieren wir als Array
			// und erzeugen dieses dynamisch über die Faker-Generatoren 
			$user = array(
			'email' => $faker->email,
			'initial'=> $initials,
			'firstname' => $firstname,
			'surname' => $surname,
			'username' => $faker->userName,
			'password' => Hash::make($faker->password()),
			'bio'=> $faker->text(255),
			'confirmation' => str_random(20),
			'confirmed'=> true,
			'registration_date'=> $faker->dateTimeThisDecade($max = 'now')

		);
		DB::table('user')->insert(array($user));
		}
	}
}

Mit dem Befehl php artisan db:seed wird der UserSeeder ausgeführt und erzeugt 10.000 sinvolle Testdatensätze.

Tom goes C#

Ich arbeite mich momentan in C# ein und bin von der Sprache begeistert. Sie bietet alle Merkmale, die ich mir von einer modernen, objektorientierten Programmiersprache wünsche und bringt in der .NET-Umgebung Standardbibliotheken für nahezu alle Probleme mit, die sich im Alltag eines Programmierers stellen.
Da ich – vor allem bedingt durch mein Studium – geübt im Umgang mit Java bin, brauchte ich nicht mehr als dieses Wochenende, um mich mit Syntax und Konzepten von C# vertraut zu machen.

MySQL mit Ruby unter Mac OS X

Möchte man eine MySQL-Datenbank mit Ruby ansprechen, muss unter UNIX-artigen Betriebsystemen den Datenbanktreiber manuell kompilieren.
Dazu genügt es die jeweils aktuelle Version von http://www.tmtm.org/downloads/mysql/ruby/ zu laden und zu kompilieren. Derzeit aktuell ist Version 2.7.3 .

Das Archiv ist mit tar xzvf mysql-ruby-2.7.3.tar.gz schnell entpackt. Danach wechseln wir ins Verzeichnis mysql-ruby-2.7.3 konfigurieren das Modul:

sudo ruby extconf.rb --with-mysql-include=/usr/local/mysql/include --with-mysql-lib=/usr/local/mysql/lib --with-mysql-dir=/usr/local/mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config

Ich habe MySQL unter /usr/local/mysql installiert – der Pfad muss unter Umständen angepasst werden. Wo MySQL installiert ist, lässt sich z.B. mit einem which mysql in Erfahrung bringen.

Der bekannte Einzeiler sudo make && make install erledigen den Rest.

Mit einem kleinen Script lässt sich die Installation testen:

require "mysql"
begin
  Mysql.new("localhost","dbuser","geheim")
  puts "Klappt! :)" 
rescue StandardError
  puts "Klappt nicht. :("   
end 

wget aufbohren: dotfiles per –mirror mitkopieren

Ich benutze GNU wget gerne um verschiedene Websites per FTP mit dem Parameter --mirror zu spiegeln. Leider werden dabei versteckte Dateien (so genannte dotfiles) wie etwa .htaccess nicht berücksichtigt. Nach eingehendem Studium der manpage stellte ich enttäuscht fest, dass wget tatsächlich keine Option zur Lösung des Problem vorsieht.

Aber zum Glück lässt sich GNU wget als Open-Source-Software an die eigenen Bedürfnisse anpassen, so dass ich folgenden q&d Patch „entwickelte“.

— wget-1.10.2_orig/src/ftp-basic.c 2005-06-19 15:47:10.000000000 +0200
+++ wget-1.10.2/src/ftp-basic.c 2007-04-21 14:17:33.000000000 +0200
@@ -977,7 +977,7 @@
uerr_t err;

/* Send LIST request. */
– request = ftp_request („LIST“, file);
+ request = ftp_request („LIST -a“, file);
nwritten = fd_write (csock, request, strlen (request), -1.0);
if (nwritten < 0) { [/code]
wget ftp://ftp.gnu.org/pub/gnu/wget/wget-1.10.2.tar.gz
tar -xzf wget-1.10.2.tar.gz
patch -p0 < wget-1.10.2_dotfiles ./configure make make install

Es genügt also LIST -a anstatt LIST an den FTP-Server zu senden, um wget zu überreden auch dotfiles rekursiv zu kopieren.
Der Patch ist – wie gesagt – ein übler Hack, der mir zur schnellen Lösung eines Problems dienen solle. Für mich funktioniert er gut. Perspektivisch wäre es jedoch wünschenswert durch einen Parameter zwischen LIST und LIST -a wählen zu können. Nach meiner mündlichen Diplomprüfung werde ich das sauber implementieren und als Feature vorschlagen.

EDIT 16:40: Hier gibt es einen sauberen Patch, allerdings nur für Version 1.9.1. Doch es sollte nicht allzu schwer fallen ihn auf die aktuelle Version zu portieren.

Ultimate Tag Warrior: URL-Rewriting

UTW ist ein tolles Plugin für WordPress, um Postings mit Tags zu versehen und Tagclouds als Navigationsmittel zu erzeugen. Dabei ist sogar eine Option vorgesehen, mit der sich schöne URL in Form von BASEURL/tag/tag erzeugen lassen. Bislang blieb diese Funktionalität meiner WordPress Installation jedoch versagt. Zwar konnte ich die Option aktivieren, die Tag Links verweisen auch auf URLs wie BASEURL/tag/linux, aber WordPress vermochte sie nicht auf den eigentliche URL BASEURL/index.php?tag=linux umzuschreiben.
Des Rätsels Lösung fand ich während ich mich in das Rewriting von WordPress einarbeitete.
Wenn Permalinks (so der von WordPress gewählte Name für scheinbar statische, saubere URLs) aktiviert werden, schreibt WordPress eine .htaccess mit folgendem Inhalt (gekürzt):

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

Sofern es sich bei der angeforderten Ressource nicht um ein tatsächlich auf dem Webspace vorhandenes Verzeichnis oder File handelt, wird die Anfrage auf die index.php umgeschrieben.
Hier übernimmt dann die Klasse WP_Rewrite, die mit eigenen Regelwerk die sonst an mod_rewrite delegierte Aufgabe übernimmt statische URLs in dynamische umzusetzen. Geparster PHP-Code ist zwar nicht ansatzweise so effizient wie das in C implementiere und bewährte mod_rewrite, bringt aber den entscheidenden Vorteil einer durch Plugins nutzbaren API mit sich. Von der macht der Entwickler des Ultimate Tag Warrior auch Gebrauch, indem er in der Funktion ultimate_rewrite_rules (zu finden in der Datei ultimate-tag-warrior-actions.php) ein neues Rewrite-Tag registriert und zwei neue Rewrite-Regeln hinzufügt.

$wp_rewrite->add_rewrite_tag('%tag%', '([^/]+)', 'tag=');
// without trailing slash
$rules += $wp_rewrite->generate_rewrite_rules($baseurl . "%tag%");
// with trailing slash
$rules += $wp_rewrite->generate_rewrite_rules($baseurl . "%tag%/");

Soweit so gut, funktioniert nur leider nicht. Ich vermutete, dass die von UTW registrierte Rewrite-Regel mit anderen, zuvor hinterlegten, kollidierte. Darum passte ich versuchsweise den Code dahingehend an, dass die UTW-Rewrite-Regeln vor allen anderen abgearbeitete würden.

$wp_rewrite->add_rewrite_tag('%tag%', '([^/]+)', 'tag=');
// without trailing slash
$rules = $wp_rewrite->generate_rewrite_rules($baseurl . "%tag%") + $rules;
// with trailing slash
$rules = $wp_rewrite->generate_rewrite_rules($baseurl . "%tag%/") + $rules;

Und tatsächlich: Nun sind auch saubere URLs mit dem Ultimate Tag Warrior möglich. Alles andere scheint auch zu funktionieren. Jedoch ist das weder eine saubere noch befriedigende Lösung. Ich wüsste gerne, warum und mit welchen Regeln die von UTW registrierten zusammenstoßen. Mir fehlt es momentan allerdings an Zeit und Lust den Code zu debuggen – zumal ich mir nicht sicher bin, ob UTW kaputt ist, WP_Rewrite oder mir nur ein anderes Plugin in die Quere kommt.

Mr Wong codes wrong

Mich erschreckt immer mehr, wie dilletantisch proffessionelle Websites mit hohen Bekanntheitsgrad und Besucherzahl implementiert sind. Heute Morgen zum Beispiel hat der Social-Bookmarking-Dienst Mr Wong einen Totalausfall:

Mr Wong Fehlermeldung

Das kann passieren, auch bei Profis. Die Frage ist nur, wie man mit solchen Fehlern umgeht. PHP-Fehlermeldungen in einem Produktivsystem über den Browser auszugeben, ist eine schlechte Idee. Oftmals geben diese Fehlermeldungen Auskunft über Implementierungsdetails aus, die einem potentiellen Angreifer Sicherheitslücken offenbaren können. Normale Benutzer können mit Fehlermeldungen des PHP-Interpreters gar nichts anfangen, darum sollten sie in verständlichen Worten darüber informiert werden, warum der Dienst momentan nicht funktioniert. Etwa in der Form von: „Unsere Datenbank ist ausgefallen. Unser Administrator wurde informiert. In Kürze wird der Dienst wieder zur Verfügung stehen. Wir bitten den Ausfall zu entschuldigen.“ Und bevor solche Meldungen überhaupt ausgegeben werden, sollte der Administrator benachrichtigt werden. Mit Exceptions wäre das alles kein Problem:

try {
	// Hier kann was schiefgehen!
} catch (Exception $fehler)
{
	// Gib was sinnvolles aus, informiere den Sysadmin, don't panic!
}

Um keinen Code duplizieren zu müssen und Exceptions gezielter behandeln zu können, lassen sich in PHP5 sogar eigene Exceptions implementieren. Außerdem bringt die PHP-SPL vordefinierte Exceptionklassen mit. Doch dazu wann anders mehr.

Ironischerweise hat die Agentur hinter Mr Wong vor kurzem eine Stelle für PHP-Entwickler ausgeschrieben. 😉

Professionelle Softwareentwicklung mit PHP5

Professionelle Softwareentwicklung mit PHP5Der Code der meisten in PHP implementierten Anwendungen ist schlecht. Schlecht bedeutet nicht etwa, dass er nicht funktionieren würde. Aber er ist schlecht zu warten, kaum wiederverwendbar und anfällig für Fehler. Die Objektorientierung bietet Paradigmen und Patterns, die konsequent angewandt zu guten Code führen, doch bis zu Version 4 wurde ein objektorientierter Ansatz in PHP gar nicht oder nur nominell unterstützt. Seit Version 5 beginnt die populäre Scriptsprache sich zu professionalisieren, allerdings können nur wenige Entwicklern einen Nutzen daraus ziehen. Denn viele, wenn nicht die meisten PHP-Programmierer lernten PHP als erste Programmiersprache und sind nicht mit professionellen Entwurfs- und Implementierungstechniken vertraut. Abhilfe schafft das Buch Professionelle Softwareentwicklung mit PHP5 von Sebastian Bergmann: Der Autor richtet sich an den fortgeschrittenen PHP-Entwickler und erläutert ihm Objektorientierung, Entwurfsmuster und Modellierung mit UML aufs Wesentliche reduziert, abstrakt und doch praxisnah. Wer professionell in PHP entwickeln möchte, meistert mit diesem Buch den bequemen Einstieg.

Die erste Auflage des Buchs stellt der Autor auf seiner Website als HTML-Version kostenlos zur Verfügung.

Zeichensätze bequem konvertieren

Eine bequeme Möglichkeit Zeichensätze zu konvertieren kommt natürlich aus der UNIX-Welt: iconv

Kürzlich wurde ich mit der Migration eines CRM beauftragt. Das alte CRM speicherte die Daten ISO 8859-1 codiert ab, das neue in UTF-8.

Hier die Lösung:

iconv -f iso-8859-1 -t utf-8 crm8859-1.sql > crmUTF-8.sql

Das SQL-Dump war übrigens > 2 GB, iconv eignet sich im Gegensatz zu vielen anderen Tools auch für umfangreichere Datenmengen.
Iconv lässt sich übrigens auch über viele Scriptsprachen wie etwa PHP, Perl oder Ruby benutzen.