articoli.gif (8610 byte)

Il formato dei messaggi: MIME

Dario De Judicibus

Testi, immagini e suoni: tutto questo può essere incluso in un messaggio codificato MIME. Ma in che modo avviene, e come fare a orientarsi in mezzo alle centinaia di formati che esistono per ogni tipo di dato?

Nel numero scorso abbiamo introdotto MIME illustrando le modalità che gli consentono di superare le limitazioni tipiche dei messaggi basati sullo standard RFC 822. Questo standard, infatti, permette di utilizzare per i messaggi solo l’ASCII-US a 7 bit. Tale codifica non solo esclude la possibilità di inserire oggetti binari o testi che richiedano alfabeti differenti da quello latino moderno, ma ha problemi a supportare anche semplicemente le vocali accentate o altri simboli utilizzati in molti alfabeti occidentali. Per ovviare a ciò MIME prevede la possibilità di strutturare il contenuto del messaggio in una o più sezioni, ognuna preceduta da una breve intestazione che servirà poi per la decodifica e l’interpretazione del contenuto vero e proprio. Ogni sezione può quindi essere ricondotta a una serie di sequenze di caratteri ASCII-US le quali possono a loro volta essere trasmesse via TCP/IP senza violare le regole dell’RFC 822.

Come abbiamo descritto nella prima parte, MIME prevede cinque nuovi campi per l’intestazione del messaggio, che estendono quelli già analizzati quando abbiamo parlato di RFC 822. Di questi solo il primo, e cioè quello relativo alla versione di MIME (MIME-Version) va obbligatoriamente nell’intestazione principale. Esso di fatto segnala che il messaggio è codificato MIME. Gli altri possono far parte sia dell’intestazione principale sia di quelle specifiche di ogni sezione. Abbiamo anche aggiunto che il campo Content-Type serve a indicare il tipo di dati contenuti nella sezione, mentre il campo Content-Transfer-Encoding serve a specificare il meccanismo di codifica utilizzato.

Gli ultimi due campi

Vediamo ora gli ultimi due campi definiti dallo standard MIME base, come avviene la suddivisione in sezioni, e come si specifica il tipo di dati contenuti in ogni sezione. Il quarto campo definito in MIME è Content-ID, e permette di associare a ogni sezione un identificativo. Questo identificativo di sezione, costruito utilizzando le stesse regole usate per l’identificativo dei messaggi, è unico a livello globale. In altre parole, non possono esistere due sezioni in altrettanti differenti messaggi con lo stesso identificativo; ciò permette di poter fare riferimento a una sezione specifica di un determinato messaggio all’interno di un altro messaggio, un documento Html o un articolo di una conferenza elettronica.

Il quinto e ultimo campo si chiama Content-Description; permette di associare a ogni sezione una breve descrizione. Il tipo di dato, infatti, spesso non è sufficiente a far capire che cosa in effetti una sezione contiene. Questo campo può, per esempio, servire a riportare il titolo di un brano musicale, l’autore di una fotografia, o semplicemente l’indicazione di eventuali diritti d’autore.

Esistono poi altri campi, definiti in vari RFC successivi, che aggiungono ulteriori possibilità allo standard MIME. Tra essi, il campo Content-Disposition viene utilizzato per fornire alcune informazioni per la gestione della sezione da parte dell’applicazione che visualizza la posta elettronica. Così un’immagine può essere visualizzata all’interno del messaggio, cioè in mezzo al testo (inline) oppure essere gestita come un allegato separato (attachment). Nel caso la sezione in questione possa essere salvata separatamente dal resto del messaggio, questo campo prevede anche un parametro che fornisce il nome del file nel quale memorizzare i dati.

Facciamo un esempio. Supponiamo di voler allegare a un messaggio un documento Microsoft Word. L’intestazione della sezione relativa somiglierebbe più o meno a questa:

Content-Type: application/msword; name="Cappuccetto Rosso.doc"

Content-Transfer-Encoding: base64

Content-Disposition: attachment; filename="C_Rosso.doc"

Content-ID: <5.9.23.19971011223409.0072016d@nowhere.it>

Content-Description: La favola di Cappuccetto Rosso

Ma quali sono i tipi supportati da MIME?

Il documento originale prevede un certo numero di tipi e sottotipi, ma lo standard è stato pensato per essere estremamente flessibile; gli autori hanno ipotizzato fin dall’inizio una crescita esponenziale di entrambi. È stato così definito un processo di registrazione basato sulla IANA (Internet Assigned Numbers Authority) per gestire le richieste di eventuali nuovi tipi e sottotipi. Fra i tipi base ci sono text, image, audio e video e message. Nel caso un tipo sia più complesso o richieda una gestione particolare, sono stati previsti anche i tipi application e multipart. Qualora poi la coppia tipo/sottotipo non dovesse bastare a capire come gestire i dati, lo standard prevede l’utilizzo di uno o più parametri che possono anche essere differenti a seconda della tipologia del contenuto della sezione. Una lista dei principali tipi e delle raccomandazioni relative a come vadano gestite le sezioni è riportata in tabella 1.

Tipo Sottotipo Significato Gestione
text plain Testo semplice non contenente alcun comando di formattazione o particolare direttiva Va visualizzato così com'è e non richiede software specifico
  enriched Testo semplice arricchito di elementi di formattazione base quali il grassetto, il corsivo, tipi differenti, ed eventualmente colori Può essere visualizzato come testo semplice, oppure sfruttare le capacità specifiche del sistema operativo per rendere correttamente tipi ed attributi
Image jpeg Immagine a mappa di bit compressa in formato JPEG basato sullo schema di codifica JFIF Richiede un visualizzatore di immagini JPEG, o quantomeno si dovrebbe permettere di salvare la sezione come file
  gif Immagine a mappa di bit compressa in formato GIG Richiede un visualizzatore di immagini GIF, o quantomeno si dovrebbe permettere di salvare la sezione come file
  (altre) Immagine in uno specifico formato Richiede un visualizzatore di immagini di quel formato, o quantomeno si dovrebbe permettere di salvare la sezione come file
Audio basic Singolo canale audio codificato utilizzando una ISDN mu-law ad 8 bit [PCM] con una frequenza di campionamento a 8.000 Hz Richiede un riproduttore audio, o quantomeno si dovrebbe permettere di salvare la sezione come file
Video mpeg Video basato sullo standard MPEG Richiede un riproduttore video MPEG, o quantomeno si dovrebbe permettere di salvare la sezione come file
Application octet-stream Informazioni binarie semplici Si dovrebbe permettere di salvare la sezione come file
  PostScript Istruzioni PostScript Vanno passate a un interprete PostScript, o quantomeno si dovrebbe permettere di salvare la sezione come file
  (altre) Informazioni binarie pensate per essere interpretate da una specifica applicazione Vanno passate all'applicazione in grado di interpretarle correttamente, o quantomeno si dovrebbe permettere di salvare la sezione come file
multipart mixed La sezione è divisa in sottosezioni, non necessariamente dello stesso Tipo e relative a dati differenti Ogni sottosezione va gestita come un oggetto a se stante
  alternative La sezione è divisa in sottosezioni, relative a modi diversi di codificare gli stessi dati Tutte le sottosezioni rappresentano lo stesso oggetto. Si può decidere di visualizzare quella più completa, di scegliere in base alle impostazioni del sistema, o di lasciar scegliere all'utente
  parallel La sezione è divisa in sottosezioni da rappresentare simultaneamente Tutte le sezioni vanno rappresentate contemporaneamente
  digest La sezione è divisa in sottosezioni, ognuna delle quali ha come tipo di default message/rfc822 (compendio) Ogni sottosezione rappresenta un messaggio codificato RFC822
message rfc822 Un messaggio codificato secondo lo standard RFC 822 e incapsulato in una sezione A seconda dell'utilizzo può servire come riferimento al messaggio originale; quello presente è una risposta di un successivo inoltro.
  partial Un pezzo di messaggio codificato secondo lo standard RFC 822 e incapsulato in una sezione Si tratta in genere di un frammento di un messaggio spezzato in più parti e che va prima ricostruito, e poi gestito come un normale messaggio codificato MIME.
  external-body Un riferimento a un messaggio, generalmente di grosse dimensioni, il cui contenuto è reperibile da una fonte esterna al messaggio nel quale è presente la sezione Si raccomanda di dare la possibilità all'utente di decidere se scaricare o meno il contenuto del messaggio dalla sorgente esterna, anche perché può essere di grandi dimensioni

 

Tabella 1 - Tipi e sottotipi standard

 

Il tipo text/plain prevede un parametro che può servire a specificare lo schema di codifica dei caratteri, e precisamente charset. Per esempio

Content-type: text/plain; charset=iso-8859-1

Nella tabella 2 abbiamo riportato la lista iniziale prevista dallo standard MIME per gli schemi di codifica dei caratteri. Altri schemi possono essere registrati sempre via IANA.

 

Schema Descrizione

 

US-ASCII

Caratteri ASCII a 7 bit come definito dallo standard ANSI X3.4-1986. È il default, e va utilizzato ogni qual volta non è necessario ricorrere ad uno schema internazionale (ISO).

 

ISO-8859-X

Schema di riferimento internazionale per la posta elettronica Internet, come definito dallo standard ISO-8859. Al momento ci sono 10 sottoschemi, per cui X può prendere i valori da 1 a 10. Da notare che lo schema 6 (Latino/Arabo) e lo schema 8 (Latino/Ebraico) comprendono sia caratteri che vanno scritti da sinistra a destra, sia caratteri che vanno scritti da destra a sinistra.

 

Tabella 2 - Schemi di codifica dei caratteri standard

 

Il tipo application/octet-type prevede due parametri: type, che serve a fornire una descrizione leggibile del tipo di dati codificati, e padding, che conta quanti zeri sono stati aggiunti alla sequenza di bit per riportare il numero di bit ad un multiplo intero di otto. Per esempio:

Content-type: application/octet-type; type="Vector map X3"; padding=6

Per quanto riguarda il tipo application/postscript e in generale per quanto riguarda tutti quei sottotipi di application che rappresentano veri e propri linguaggi di programmazione, è necessario definire tutta una serie di limitazioni e raccomandazioni per evitare che la semplice "lettura" di un messaggio faccia eseguire sulla macchina locale operazioni potenzialmente dannose o comunque non volute. Questo discorso ci porterebbe comunque troppo lontano.

Una sezione dentro l’altra

E veniamo ora ai tipi multiparte, descriviamo cioè come un messaggio MIME può contenere più sezioni contemporaneamente. Una sezione multiparte non è altro che una sezione che contiene altre sezioni. Ogni sottosezione è preceduta da una stringa di caratteri chiamata separatore. L’ultima sottosezione viene seguita da una stringa simile chiamata chiusura. Inoltre, ogni sottosezione è formata da un’intestazione che però può contenere solo campi di tipo Content-*. Qualunque altro campo tipico dei messaggi RFC822 viene ignorato. In questo modo è possibile collocare all’interno di una sottosezione un messaggio RFC 822 senza il pericolo che l’intestazione del messaggio venga a sua volta decodificata. La stringa di separazione è definita per mezzo del parametro boundary, che va definito nel campo Content-type della sezione principale. Una sezione multiparte può a sua volta contenere altre sezioni multiparte. Nel caso tuttavia di sezioni multiparte annidate, ogni sezione dovrà ovviamente avere un separatore differente.

Un esempio di sezione multiparte è riportato nella tabella 3.

From: Dario de Judicibus <ddj@mclink.it>

 

To: Internet News <inews@tecnet.it>

Date: Sun, 28 Apr 1998 22:59:08 +0100 (CET)

Subject: Esempio di messaggio multiparte

MIME-Version: 1.0

Content-type: multipart/mixed; boundary="SePaRaToRe"

Questa parte puo' essere ignorata, sebbene sia preferibile mettere qui qualcosa

che possa essere utilizzato da un lettore di messaggi che non supporta MIME.

--SePaRaToRe

Dato che questa sezione non ha un'intestazione, si assume che sia scritta semplicemente in US-ASCII.

--SePaRaToRe

Content-Type: text/plain; charset=ISO-8859-1;

Content-Transfer-Encoding: quoted-printable

Questa sezione =E8 invece scritta in Latin-1 e contiene alcuni caratteri accentati.

--SePaRaToRe

Content-Type: text/html; charset="iso-8859-1"

Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML//IT">

<HTML>

<HEAD>

</HEAD>

<BODY>

<P>

Questo invece =E8 un testo <B>HTML</B> e quindi

contiene <I>tag</I> ed un collegamento al sito di

<A HREF="http://inews.tecnet.it/">Internet

News</A>.

</BODY>

</HTML>

--SePaRaToRe

Content-Type: image/jpeg

Content-Transfer-Encoding: base64

Content-ID: <007001ad912d$eef3f1e60$0a00a0c0@pq00>

/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK

CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU

… Questa invece è un'immagine in formato JPEG. …

jVreN449zLv3bt395v8AaqO8RXWNfs8fmbfl27v3f/fNFFWtwP/Z

--SePaRaToRe--

Questo e' l'epilogo e puo' anch'esso essere ignorato.

 

Tabella 3 - Esempio di sezione multiparte

 

Come si vede, il separatore si ottiene facendo precedere la stringa specificata dal parametro boundary da due trattini o segni meno, mentre la chiusura è formata dalla stessa stringa a cui si aggiungono all’inizio e alla fine i due segni meno. Inoltre, mentre ogni singola sottosezione può utilizzare un algoritmo di codifica differente, segnalato dalla presenza del campo Content-Transfer-Encoding, la sezione multiparte stessa accetta solo codifiche del tipo 7 bit, 8 bit e binary, come già accennato lo scorso numero. Infine, la stringa utilizzata per il separatore deve essere formata solamente da caratteri ASCII-US e nel caso contenga anche caratteri non alfanumerici si raccomanda di racchiuderla fra doppie virgolette al momento della definizione, ma non quando è usata come separatore o chiusura.

I tipi di sezione multiparte

Una sottosezione senza intestazione o della quale non viene comunque fornito il tipo, è di tipo text/plain nel caso di sezione multiparte mista (mixed) e di tipo message/rfc822 nel caso di sezione multiparte di tipo compendio (digest). Esistono, infatti, quattro tipi di sezioni multiparte.

Il primo tipo è multipart/mixed, e va utilizzato quando le varie sottosezioni sono indipendenti e vanno assemblate seguendo un ordine ben definito. Il secondo è multipart/alternative. In questo caso tutte le sezioni rappresentano lo stesso oggetto o dato, ma codificato in modo differente. Il lettore del messaggio sceglierà quale dei vari formati andrà visualizzato in funzione delle capacità del sistema su cui viene letto. In genere il livello di dettaglio aumenta mano a mano che ci si sposta in avanti nella sezione multiparte. Per esempio, se la sezione contiene un testo, la prima sezione potrebbe essere in Latin-1, la seconda potrebbe essere in Html, la terza potrebbe contenere lo stesso testo come documento Corel WordPerfect. Se il messaggio è visualizzato su una piattaforma Windows 95 su cui non è stato installato un browser verrà visualizzato solo il testo ISO-8859, se è disponibile, per esempio, Netscape Communicator verrà visualizzata la pagina Html; se, infine, il tipo WPD è regolarmente registrato, verrà caricato il documento WordPerfect. Da notare che benché l’oggetto sia lo stesso, ogni rappresentazione può contenere un livello di dettaglio differente. Per esempio, la pagina Html può contenere alcune immagini grafiche e una musica di sottofondo, il documento WordPerfect contenere le immagini grafiche e una serie di annotazioni dell’autore, mentre il testo semplice non può ovviamente includere alcun tipo di componente multimediale.

Il terzo tipo è multipart/digest, e rappresenta un compendio di messaggi RFC 822. In effetti una sottosezione di questo tipo potrebbe anche non essere di tipo message/rfc822, ma la cosa è fortemente sconsigliata. In tal caso è bene utilizzare il tipo misto. Un esempio di compendio è riportato nella tabella 4.

From: Bibliotecario

 

To: Lettori

Date: Mon, 29 Mar 1996 16:34:31 +0000

Subject: Discussione sul film Nirvana

MIME-Version: 1.0

Content-Type: multipart/mixed; boundary="SePaRaToRe PrInCiPaLe"

--SePaRaToRe PrInCiPaLe

 

--SePaRaToRe PrInCiPaLe

Content-Type: multipart/digest; boundary="SePaRaToRe DeI mEsSaGgI"

-- SePaRaToRe DeI mEsSaGgI

From: Sonia

Date: Fri, 26 Mar 1996 11:13:32 +0200

Subject: Che ne pensate di Nirvana?

A me è piaciuto, e a voi?

Sonia "Chili"

--SePaRaToRe DeI mEsSaGgI

From: Franco

Date: Fri, 26 Mar 1996 10:07:13 –0500

Subject: Re: Che ne pensate di Nirvana?

A me un po' meno, ma almeno è il primo film di fantascienza serio

prodotto in Italia.

F.G.

--SePaRaToRe DeI mEsSaGgI—-

--SePaRaToRe PrInCiPaLe—

 

Tabella 4 - Esempio di compendio

 

Risulta chiaro ora perché qualunque campo che non sia di tipo Content-* non venga interpretato all’interno di una sottosezione. L’ultimo tipo è multipart/parallel, in cui le varie sezioni sono da considerarsi parti di un aggregato, e l’ordine in cui sono riportate non è significativo. Per esempio, un messaggio di questo tipo potrebbe contenere vari oggetti 3D, uno per sezione, da mostrare contemporaneamente in una scena.

Da notare che il tipo message/rfc822 non necessariamente deve contenere messaggi conformi allo standard RFC 822. In realtà sezioni di questo tipo possono contenere sia articoli USENET sia generici messaggi codificati MIME. Oltre al sottotipo rfc822, il tipo message prevede anche il sottotipo partial. Quest’ultimo è stato ideato nel caso di messaggi molto lunghi che può essere conveniente, o addirittura necessario, frammentare e spedire in più pezzi. Tuttavia, esiste una forte limitazione: i messaggi devono sempre essere codificati in ASCII-US. Non è infatti permesso codificare in alcun modo le sezioni di tipo message perché le intestazioni del messaggio devono sempre essere leggibili durante il trasporto. Questo vuol dire che una sezione di questo tipo va spedita così com’è. Se tale sezione contenesse dati ad 8 bit e passasse attraverso una sottorete in grado di supportare solo dati a 7 bit una parte dell’informazione andrebbe persa, né si potrebbe richiedere al gateway in ingresso di codificare il messaggio base64 o quoted-printable per poi farlo ricostruire da quello in uscita. Tale codifica dovrebbe infatti avvenire per tutto il messaggio, non per i singoli frammenti; è cioè necessario che l’intero messaggio venga prima ricostruito e poi convertito. Il problema è che non è detto che tutti i frammenti passino per lo stesso gateway o anche semplicemente attraversino la stessa sottorete. Da qui la suddetta limitazione. Un esempio di message/partial è mostrato nella tabella 5. Come si può vedere, i vari frammenti fanno riferimento allo stesso identificativo di messaggio.

From: Isabella

 

To: Amichetti

Date: Fri, 11 Nov 1998 17:13:32 +0100

Subject: Festa di compleanno (parte 1 di 3)

MIME-Version: 1.0

Message-ID: <isa1@tecnet.it>

Content-Type: message/partial; number=1; total=3; id="Axu8906:896tyq@tecnet.it"

Subject: Festa di compleanno

Content-Type: text/plain; charset="iso-8859-1"

Content-transfer-encoding: quoted-printable

Dopodomani compio ben tre anni. Siete tutti invitati alla mia festa di compleanno.

Questa =E8 la lista dei giochi che faremo…

 

From: Isabella

To: Amichetti

Date: Fri, 11 Nov 1998 17:13:32 +0100

Subject: Festa di compleanno (parte 2 di 3)

MIME-Version: 1.0

Message-ID: <isa2@tecnet.it>

Content-Type: message/partial; number=1; total=3; id="Axu8906:896tyq@tecnet.it"

Nascondino a coppie: allora, per ogni coppia uno si nasconde e l'altro…

 

From: Isabella

To: Amichetti

Date: Fri, 11 Nov 1998 17:13:32 +0100

Subject: Festa di compleanno (parte 3 di 3)

MIME-Version: 1.0

Message-ID: <isa3@tecnet.it>

Content-Type: message/partial; number=1; total=3; id="Axu8906:896tyq@tecnet.it"

Per arrivare a casa mia prendete…

Vi aspetto numerosi!

Isabella

 

Tabella 5 - Esempio di messaggi frammentati

Ogni messaggio parziale è inoltre identificato da un numero che rappresenta la posizione del frammento nel messaggio originale. Il numero totale di frammenti è obbligatorio solo nell’ultimo parziale, ma lo standard raccomanda di metterlo anche negli altri frammenti. Le regole di ricomposizione del messaggio originale sono un po’ complesse, e vanno oltre gli scopi di questo articolo. A ogni modo abbiamo riportato in grassetto, a titolo di esempio, le parti che verranno a ricomporre il messaggio originale. Le altre saranno scartate. Un altro importante sottotipo di message è external-body. In questo caso il corpo del messaggio non è incluso nello stesso ma semplicemente referenziato. I parametri del sottotipo servono a segnalare da dove il corpo vero e proprio può essere ottenuto. La tabella 6 ne mostra un esempio.

 

Content-type: message/external-body; access-type=local-file; name="/pub/girl.jpeg"

 

Content-type: image/jpeg

Content-ID: <789.00@cicciobello.tecnet.it>

Content-Transfer-Encoding: binary

 

QUESTO È SOLO UN CORPO "FANTASMA"!

 

 

Tabella 6 - Messaggio con corpo “esterno”

Come si può vedere, il corpo è stato sostituito da uno falso che in genere è ignorato, ma che può contenere informazioni ausiliarie per l’accesso ai dati veri e propri. L’identificativo del messaggio è in questo caso obbligatorio. Fra i parametri di questo sottotipo ci sono access-type ("FTP", "ANON-FTP", "TFTP", "LOCAL-FILE" e "MAIL-SERVER"), che indica il tipo di sorgente dove possono essere reperiti i dati, expiration, una data oltre la quale i dati potrebbero non essere più disponibili, e size, che dà le dimensioni dei dati in ottetti. Quest’ultimo parametro ha lo scopo di fornire un’utile indicazione per decidere se vale la pena o meno accedere al corpo del messaggio. Per esempio, se size è 100 MB una persona potrebbe porsi problemi prima di scaricare il messaggio. Per ogni tipo di accesso esistono poi ulteriori parametri che servono a indicare esattamente dove i dati sono stati memorizzati (sito, Url, directory, filename). Per chi ne volesse sapere di più, al momento gli RFC relativi a MIME sono quelli dal 2045 al 2049 inclusi. A ogni modo, la prossima volta che vi arriva un messaggio un po’ complesso in casella postale, provate a dare un’occhiata al testo originale. Può essere un’esperienza interessante…

(ddejudicibu@tecnet.it)