Die Multi-Media-Mail-Datei der Zukunft, SMS, MMS, Internet-Mail

Es wird Zeit, den MIME-Standard abzulösen

Der hier vorliegende Artikel ist ein Draft, ein Entwurf. Dieser Entwurf beschreibt einen möglichen zukünftigen Standard für die Übertragung von Multi-Media-Dateien als SMS, MMS oder Mail (Internet).

Gegenüber dem bisherigen MIME-Standard ergeben sich Vorzüge:

Die Maildatei der Zukunft ist ebenso wie eine MIME-Mail eine Multipart-Message, verzichtet jedoch auf eine Strukturierung mit textlichen Mitteln, so entfällt die Boundary und es entfallen weitere Encodings wie Quoted-Printable und Base64. Mit dem Verzicht auf Letzteres sind Maildateien mit Attachments wesentlich kleiner als Mails nach dem MIME-Standard, bekanntlich vergrößert Base64 eine Binary um den Faktor 4/3.

Untenstehender Perl-CODE veranschaulicht die Funktionsweise und den möglichen Aufbau einer Maildatei der Zukunft, welche den 8-Bit-Bereich ausschöpft, also die bisherige 7-Bit-Grenze sprengt. Zur Veranschaulichung wird mit IO::String eine PIPE erstellt, in der Praxis wäre PIPE das unter SMTP liegende Socket.

Der Serializer ist so gebaut, dass ein MTA (Mail Transfer Agent) weitere Informationen (Return-Path usw.) einfach anfügen kann, ohne den Gesamtinhalt der Maildatei kennen oder die Maildatei parsen zu müssen. Des Weiteren kann ein Serializer in jeder Programmiersprache implementiert werden und hinzugefügte Header können beliebige Zeichen enthalten ohne weiteres Encoding.

Selbstverständlich ist eine solche Maildatei auf jedem Endgerät auch darstellbar, z.B. auch mit einem gewöhnlichen Browser, sofern der Serializer mit JavaScript programmiert ist. Das, was in untenstehendem CODE der Data::Dumper macht, kann genausogut auch ein Browser oder auch ein beliebiger Mail-Client: Den Text der Nachricht ausgeben und die eingebetten Attachments als Objekte zeigen oder zum Speichern unter... anbieten.

Moderne Browser könnten derartig aufgebaute Mail-Dateien auch über ein Websocket versenden oder aus einem Websocket lesen.

use strict;
use warnings;
use IO::File;
use Data::Dumper;
use 5.010;
use bytes;
use IO::String;

# Prepare Attachment
my $gif_binary = do{
    my $fh = IO::File->new;
    $fh->open('red.gif', O_RDONLY|O_BINARY) or die $!;
    read($fh, my $buffer, -s $fh);
    $fh->close;
    $buffer;
};

# Datenstruktur einer Mail als Multimedia Datei
my $mail = [
    {
        role => 'header',
        mta => 'localhost',
        mesgid => 123456789,
        date => scalar(localtime),
    },
    {
        role => 'header',
        from => 'hugo@example.org',
        to   => 'lupo@example.com',
        subject => 'Multi-Media-Mail'
    },
    {
        role => 'part',
        type => 'text/plain; Charset=UTF-8',
        body => 'Inhalt der Nachricht als Text'
    },
    {
        role => 'part',
        type => 'image/gif',
        body => $gif_binary,
        label => 'Ein bischen Grafik',
        filename => 'red.gif',
    }
];

# Serialize
my $pipe = IO::String->new;
my $file = freeze($pipe, $mail);
# Übertragung: Jeder MTA fügt der Datei einen Block mit role => 'header' hinzu
# Dieser Block hat eine variable Länge und kann beliebige Informationen enthalten

# ein MTA fügt einen Block hinzu
addheader($pipe,
    role => 'header',
    mta  => 'mail.example.com'
);



# Deserialize
# Das macht der Mailclient nach der Übertragung
say Dumper thaw($pipe);


###########################################################################
# für den Mail Transfer Agent
# Der Einfachheit halber werden weitere Header am Ende der
# Maildatei angehängt
sub addheader{
    my $io = shift;
    my %av = @_;
    my $cnt_keys = scalar keys %av;
    $io->print(pack "C", $cnt_keys);
    foreach my $att(keys %av){
        my $val = $av{$att};
        $io->print( pack("NN", length($att), length($val)).$att.$val  );
    }
};


###########################################################################
# Serializer

sub freeze{
    my $io = shift;
    my $arr = shift;
    $io->seek(0,0);
    foreach my $av( @$arr ){
        my $cnt_keys = scalar keys %$av;
        $io->print( pack "C", $cnt_keys  );
            # Anzahl der Schlüssel-Werte-Paare
        foreach my $att (keys %$av){
            my $val = $av->{$att};
            $io->print( pack("NN", length($att), length($val)).$att.$val  );
        }
    }
}

sub thaw{
    my $io = shift;
    $io->seek(0,0);
    my @arr = ();
    while( read($io, my $buffer, 1)  ){
        my $cnt_keys = unpack "C", $buffer;
        my %hash = ();
        foreach my $cnt(1 .. $cnt_keys){
            read($io, $buffer, 8);
            my($klen, $vlen) = unpack "NN", $buffer;
            read($io, my $key, $klen);
            read($io, my $val, $vlen);
            $hash{$key} = $val;
        }
        push @arr, \%hash;
    }
    return \@arr;
}

Anbieter: nmq​rstx-18­@yahoo.de, die Seite verwendet funktionsbedingt einen Session-Cookie und ist Bestandteil meines nach modernen Aspekten in Perl entwickelten Frameworks.