Copyrigtht © 1997 Università di Firenze. All rights reserved.
Free license available.
In questo capitolo si affrontano gli argomenti relativi all'analisi delle funzioni Messaging API (MAPI) e i loro utilizzi nei programmi di comunicazione per Windows 95.
A livello di architettura le MAPI sono divise in quattro componenti:
I Service Provider sono driver che MAPI usa per implementare molte delle sue funzioni. I drivers Message Store implementano la memorizzazione, l’organizzazione e la richiesta dei messaggi. I drivers Address Book implementano la ricerca e il mantenimento degli indirizzi dei messaggi. I drivers Transport consentono di inviare i messaggi attraverso la rete.Un quarto tipo di drivers chiamato Profile Driver memorizza le informazioni relative alla configurazione. Le MAPI DLLs connettono il Service Provider con l’applicazione. Windows 95 lavora con tutti e quattro i drivers. I drivers che MAPI usa per spedire particolari classi di messaggi possono essere configurati dal pannello di controllo di Windows, usando il Mail o Fax applet. Quest' ultimo, di default, richiama la finestra dialogo delle proprietà di configurazione di MS Exchange, con una lista di servizi informativi utilizzabili. Selezionando un servizio della lista, attraverso Properties, è possibile configurare il servizio. MAPI include anche Message Spooler: questo mette in fila i messaggi, che saranno serviti uno alla volta. Message Spooler opera come una valvola tra il Message Store e il Message Tranport, preoccupandosi di far fluire i dati dentro o fuori dal sistema. Un'applicazione non deve dialogare con le funzioni dello spooler; queste infatti sono dei processi che partono come una applicazione delle MAPI. MAPI DLL permette alle varie parti di lavorare insieme. MAPI coordina le attività di più applicazioni relative ai messaggi, provvedendo alla loro sicurezza, e gestendone il trasporto (es: gestione dei dati in uscita).
I messaggi tendono ad avere una struttura definita. Un messaggio non é altro che un testo al quale sono aggiunte alcune particolari informazioni necessarie per il suo corretto inoltro: l'indirizzo del mittente, quello del destinatario, la data e l'ora. Queste informazioni, situate nella parte iniziale del messaggio, rappresentano la "busta" della nostra lettera elettronica e sono chiamate header. Generalmente in un messaggio esse consistono in stringhe di testo precedute dalle seguenti parole: From (l'indirizzo del mittente), To (l'indirizzo del destinatario), Subject (titolo o argomento del messaggio), Date (data e ora in cui il messaggio è stato scritto), CC (Carbon Copy, contiene gli indirizzi di altri eventuali destinatari aggiuntivi), BCC (Blind Carbon Copy, equivalente al precedente, ma con la differenza che agli altri destinatari non viene notificato che il messaggio è la copia di un testo notificato ad altri) ed Attachments (usato per attaccare altri dati al messaggio, ad esempio un file).
Vediamo la struttura del messaggio Windows MAPI:
typedef struct {
ULONG ulReserveed;
LPSTR lpszSubject;
LPSTR lpszNoteText;
LPSTR lpszMessageType;
LPSTR lpszDateReceived;
LPSTR lpszConversationID;
FLAG flFlag;
lpMapirecipdesc lpOriginator;
ULONG nRecipCount;
lpMapiRecipDesc lpRecip;
ULONG nFileCount;
lpmapiFileDesc lpFiles;
}MapiMessage, FAR *lpMapiMessage;
Il primo parametro, ulReserved, è riservato e deve essere
configurato a zero. Il secondo, lpszSubject, punta ad una z-string
contenente il soggetto del messaggio (esempio: Agenda per 4:30 pm Meeting).
In questo modo non viene allocata memoria per la stringa; ciò deve
essere fatto direttamente dall'applicazione. Questo in generale è
vero per tutti gli elementi della struttura. Il terzo parametro, lpznNoteText,
punta al testo del messaggio; il quarto, lpszDateReceived, descrive
il tipo del messaggio. Esso è interpretato dal driver MAPI ed è
vincolato ad assumere uno dei valori predefiniti. Il tipo più comune
di messaggio supportato dalle implementazioni di Microsoft è interpersonal
message o IPM.Note.
A seconda del drivers installato, il messaggio del tipo IPM.Note può
essere usato per la posta elettronica o il fax. In ogni messaggio ricevuto,
MAPI inserisce un'etichetta contenente l'ora di ricezione, la quale è
memorizzata in lpszDateReceived. Il formato è: YYYY/MM/DD
HH:MM. Se il sistema supporta più linee di conversazione, lpszConversationID
specifica la linea di conversazione utilizzata per il messaggio. Il settimo
parametro, flFlags, è un insieme di bit di mascheratura che
identificano certe caratteristiche del messaggio. I possibili valori per
tale parametro sono :
MAPI_UNREAD indica che il messaggio nel inbox non è stato letto (è come un flag di sporco, che viene pulito quando il messaggio è stato letto).
MAPI_RECEIP_REQUESTED indica che è richiesta una read receipt per l'uscita dei messaggi.
MAPI_SEND indica che è stato spedito un messaggio in uscita .
L'ottavo parametro, lpOriginator, punta ad una struttura che descrive chi ha generato il messaggio (noto anche come FROM party). Questo prende la forma di una struttura MapiRecipDesc, la quale, come gli altri membri, è allocata esternamente alla struttura del messaggio. Vediamo la struttura della MapiRecipDesc:
typdef struct {
ULONG ulReserved;
ULONG ulRecipClass;
LPSTR lpszName;
LPSTR lpszAddress;
ULONG ulEIDSize;
LPVIOD lpEntryID;
}MapiReciDesc, FAR * lpMapiRecipDesc;
Il primo parametro della struttura, ulReserved, è riservato e deve essere configurato a zero. Il secondo, ulRecipClass, deve assumere uno dei seguenti valori:
MAPI_ORIG identifica il mittente del messaggio
MAPI_TO identifica il ricevente diretto del messaggio
MAPI_CC identifica il ricevente copy
MAPI_BCC identifica il ricevente blind copy
Nella struttura del messaggio il parametro lpOriginator->ulRecipClass deve essere configurato a MAPI_ORIG per identificare il generatore del messaggio. Il parametro lpszName specifica il nome dei riceventi. Il quarto elemento della struttura lpszAdress specifica l'indirizzo: può essere un numero telefonico o indirizzo internet; solitamente però MAPI utilizza un indirizzo estratto da un Windows Address Book. Gli ultimi due campi vengono usati per identificare in modo univoco il ricevente della chiamata. Il nono elemento della struttura MapiMessage, nRecipCount specifica il numero dei riceventi che verranno individuati nel decimo parametro della struttura. Non è ovviamente richiesto il numero dei generatori del messaggio, in quanto il messaggio può essere creato da una sola persona, ma ci possono essere molti riceventi che devono quindi essere specificati. Il parametro lpRecips punta ad una lista di riceventi, cioè ad un array di strutture del tipo MapiRecipDesc che si deve allocare nella applicazione. I riceventi sono specificati in maniera simile a quanto fatto per il mittente, l'unica differenza è che il membro ulRecipientClass è configurato o con MAPI_TO (ricevente diretto), o MAPI_BCC(ricevente blind copy), o MAPI_CC(ricevente copy). Le informazioni specifiche dei riceventi sono in genere estratte da un Windows Address Book, così l'applicazione non deve riempire il 4,5,6 campo della struttura MapiReciDesc. I prossimi due parametri della struttura MapiMessage specificano l'unione di file al messaggio. Il campo nFileCount definisce il numero di file attaccati. Il membro lpFiles è un array di dimensione nFileCount di strutture MapiFileDesc. Analizziamo la struttura MapiFileDesc:
typdef struct {
ULONG ulReserved;
ULONG flFlags;
ULONG nPosition;
LPSTR lpszPathName;
LPSTR lpFileType;
}MapiFileDesc, FAR * lpMapiFileDesc;
Il primo elemento della struttura è riservato; flFlags sono invece flags che possono valere zero oppure uno o entrambi dei seguenti valori :
MAPI_OLE il file attaccato è un OLE file che può essere attivato e modificato.
MAPI_OLE_STATIC è un attacco ad uno static OLE file il quale può essere solo letto ma non scritto (modificato).
Il parametro nPosition è usato per agganciare (incastrare) oggetti, in particolare OLE file, al corpo del messaggio. Per esempio un nPosition di valore 1000 incastra un file dopo 1000 bytes del messaggio di testo. Un valore pari a -1 indica che l'attacco è un file separato che non deve essere incastrato. Attenzione a non incastrare due file nella stessa posizione o in una posizione dopo la fine del messaggio di testo. Il membro lpszPathName specifica il completo pathname del file attaccato includendo il drive specificato e tutte le directory. Spesso capita che il file sia temporaneo creato con l'espresso proposito di essere spedito come parte di un messaggio (per esempio potrebbe essere un piccolo pezzo di un grande file); in questo caso si può richiedere alla MAPI di rinominare il file specificando il nuovo nome nel parametro lpszFileName. L'ultimo componente della struttura identifica il tipo di file attaccato.
Per spedire e ricevere messaggi un'applicazione deve essere registrata sul Windows messaging system. Parte del processo di creazione di una sessione è selezionare un profilo. Il profilo è configurato usando il Mail e Fax applet sul pannello di controllo di Windows. Più di ogni altra cosa, un profilo specifica l'insieme dei driver MAPI da usare con una particolare classe di messaggi. I profili non sono visibili, quindi non si può scoprire un profilo errato, così come non si può copiare un profilo da una macchina su un'altra e sperare che tutto funzioni. Questo non è però un problema in quanto il profilo può essere facilmente ricostruito usando Mail e Fax applet. Una Messaging Session tiene conto di tutto ciò che accade dal momento in cui un'applicazione viene registrata sul messaging system al momento in cui viene chiusa la sessione. In assenza di errori MAPI ritorna un gestore della sessione da usare in successive chiamate a funzioni MAPI. Il gestore della sessione diviene non valido quando l'applicazione termina. Per creare una sessione un’applicazione usa MAPILogon, la cui sintassi è mostrata sotto.
MAPILogon (ulUIParam, lpszProfileName, lpszPassword, flFlags, ulReserved, lplhSession);
Il primo argomento della funzione è il gestore della finestra
di dialogo principale che verrà visualizzata da MAPILogon.
Se questo parametro è configurato a zero la finestra di dialogo
è in modalità di applicazione. Nel secondo parametro si può
inserire il nome del profilo, che diventerà quello di default. Se
il nome del profilo specificato non esiste, MAPI rimanda MAPI_E_LOGIN_FAILURE.
Questo parametro può essere anche NULL.
LpszPassword serve se si vuole stabilire una password per il profilo.
Il quarto parametro specifica dei flags che possono essere configurati
per specificare se la sessione allocherà un user interface.
Se lpszProfileName assume il valore NULL, configurando il flag al
valore MAPI_LOGON_UI viene visualizzata la finestra di dialogo per la scelta
del profilo in maniera interattiva. Se non si è specificato una
password e il profilo selezionato invece la richiede, allora è necessario
inserirla. Se non viene configurato un profilo nel secondo parametro e
non si è posto il quarto parametro al valore MAPI_LOGON_UI allora
MAPI sceglie il profilo di default che è configurato dal pannello
di controllo. Configurando il flag al valore MAPI_LOGON_UI si può
scegliere il profilo di default per i successivi accessi digitando su Opzioni,come
mostrato in figura.

La sezione Opzioni di questa finestra di dialogo include anche una finestra di controllo, chiamata Mostra schermate di accesso per i servizi informazioni. Selezionando questa finestra verranno mostrati i vari componenti MAPI, come l'Address Book, Tranport, e Message Store. Con il tasto Nuovo si può creare un nuovo profilo. Se i messaggi sono memorizzati su un computer remoto è possibile accedervi specificando il flag MAPI_FORCE_DOWNLOAD (MAPI attende che ritornino i dati prima di iniziare MAPILogon). Il quinto parametro è riservato per il futuro. LplhSession punta ad una variabile nella quale MAPILogon ritorna il gestore della sessione, se questa ha successo. Per chiudere la sessione si chiama MAPILogoff la cui sintassi è mostrata sotto.
MAPILogoff(lhsession, ulULParam, flFlags, ulReserved)
Il primo parametro della funzione è il gestore della sessione ritornato da MAPILogon, il secondo è il gestore della finestra; gli ultimi due parametri non sono usati e vanno posti a zero.
I messaggi sono letti dal magazzino dei messaggi (Message Store), che è simile ad un archivio. Il magazzino dei messaggi può avere diverse cartelle. Per esempio, di default, Exchange usa 4 cartelle. Una cartella serve per ricevere messaggi (Inbox), una per i messaggi in partenza (Outbox), una per i messaggi in partenza che sono già stati spediti (Send Item), e una per cancellare i messaggi che non possono essere scartati. La funzione per leggere i messaggi è chiamata MAPIReadMail. Comunque, prima di poter chiamare MAPIReadMail, il messaggio da leggere deve essere localizzato nel magazzino dei messaggi usando la funzione MAPIFindNext, la cui sintassi è mostrata sotto:
ULONG FARPASCAL MAPIFindNext(LHANDLE lhSession, ULONG ulUIParam, LPSTR lpszMessageType, LPSTR lpszSeedMessageID, FLAGS flFlags, ULONG ulReserved, LPSTR lpszMessageID);
MAPIFindNext localizza un messaggio di un particolare tipo all'interno
del magazzino dei messaggi e ritorna un unico identificatore del messaggio.
Il primo parametro, lhSession, è il gestore della sessione
ritornato da MAPIlogon. Il secondo, ulUIParam, è il
gestore della finestra principale che potrà essere utilizzato successivamente
per la visualizzazione di ulteriori finestre. La funzione visualizzerà
una finestra di dialogo richiedente la password per accedere al magazzino
dei messaggi, se questo la richiede. Il terzo, lpszMessageType,
è una stringa che definisce il tipo di messaggio che l'applicazione
sta cercando. Generalmente questo tipo di stringa è IPM.Note. Infatti,
quando lpszMessageType è NULL, MAPI assume di default il
tipo IPM.Note. Se MAPIFindNext localizza un messaggio di tipo specifico,
ritorna un unico identificatore nel parametro lpszMessageID.
Questo parametro deve puntare al minimo 64 bytes dello spazio riservato
all'identificatore ID del messaggio, tuttavia per assicurare compatibilità
con IDs più lunghi, il parametro potrà puntare fino a 512
byte di spazio. L'identificatore ID ritornato può essere passato
nel parametro lpszSendMessageID in una susseguente chiamata a MAPIFindNext,
specificando un punto di partenza per localizzare un nuovo messaggio dello
stesso tipo. LpszSeedMessageID dovrebbe assumere il valore NULL
quando cerchiamo il primo messaggio di un certo tipo. Quando non ci sono
più messaggi di uno specifico tipo da cercare, MAPIFindNext
ritorna MAPI_E_NO_MESSAGE. UlReserved è riservato per un
uso futuro e deve essere configurato a zero. Il parametro flFlags
è un flag di maschera che controlla il comportamento di MAPIFindNext.
Il flag MAPI_UNREAD_ONLY chiama la funzione per localizzare solo i messaggi
che non sono stati letti. Quando un messaggio è stato letto, MAPI
lo marca come letto. Quando MAPI_UNREAD_ONLY è configurato, MAPIFindNext
controlla ciascun messaggio di uno specifico tipo per leggere questo marchio,
ed evidenzia solamente quelli che non lo hanno. Un altro flag che può
essere specificato è MAPI_GUARANTEE_FIFO, il quale costringe MAPIFindNext
alla ricerca dei messaggi e rimanda l'ordine con cui sono stati ricevuti.
La configurazione del flag MAPI_LOGON_MSGID indica che il valore del parametro
lpszMessageID può essere alzato al valore di 512 bytes. Se
questo flag non è configurato, l'ID potrà occupare solamente
64 bytes. Una volta ricevuto l'identificatore, usando MAPIFindNext,
il messaggio corrispondente a questo ID può essere ricevuto usando
MAPIReadMail, la cui sintassi è mostrata sotto:
ULONG FAR PASCAL MAPIReadMail (LHANDLE lhSession, ULONG ulUIParam, LPSTR lpszMessageID, FLAGS flFlags, ULONG ulReserved, lpMapiMessge FAR * lppMessage);
Il primo parametro, lhSession, è il gestore della sessione,
il secondo, ulUIParam, è il gestore della finestra principale.
LpszMessageID è l'identificatore del messaggio rimandato
da MAPIFindNext. C'è un parametro riservato, ulReserved,
il quale deve essere configurato a zero ed é un puntatore alla struttura
MapiMessage che indica quando il messaggio è ritornato. Ci
sono dei flag per controllare il comportamento della funzione. I parametri
flFlags agiscono sulle informazioni ritornate nella struttura del
messaggio. Configurando il flag MAPI_ENVELOP_ONLY quando si chiama la funzione
MAPIReadMail, questa non fa ritornare il testo del messaggio o eventuali
files attaccati. Questo flag è molto utile per scorrere rapidamente
le intestazioni dei messaggi, senza doverne leggere il contenuto. Configurando
il flag MAPI_BODY_AS_FILE si indica alla funzione MAPIReadMail di
impacchettare il testo del messaggio all'interno di un file o di aggiungerlo
come file attaccato.Tale procedura risulta conveniente se si ha la possibilità
di manipolare il messaggio di testo attraverso l'uso del file system. Per
sopprimere il ritorno di qualche file attaccato, bisogna specificare il
flag MAPI_SUPPRESS_ATTACH. Il flag MAPI_BODY_AS_FILE e il flag MAPI_SUPPRES_ATTACH
sono mutuamente esclusivi.
Leggendo un messaggio con MAPIReadMail si determina da parte della
MAPI la marcatura del messaggio come letto. Per prevenire MAPI dal marcare
il messaggio letto, viene configurato il flag MAPI_PEEK, in modo tale che
si potrà leggere il messaggio per quante volte si vorrà senza
che questo venga marcato. MAPIReadMail alloca in memoria la struttura
MapiMessage riempiendo il messaggio di informazioni e ritornando
un puntatore alla struttura allocata. E' più conveniente per MAPI
allocare la memoria per la struttura perché solamente MAPI conosce
quanta memoria è richiesta per il corpo del messaggio, lista riceventi,
indirizzi e unione di file. L'applicazione è terminata, liberando
la memoria associata, chiamando MAPIFreeBuffer la cui sintassi è
mostrata sotto.
MAPIFreeBuffer ( LPVOID lpBuffer );
Il singolo parametro di MAPIFreeBuffer è un puntatore al blocco di memoria allocato da MAPI. Passare il puntatore al messaggio ritornato da MAPIReadMail a MAPIFreeBuffer libera la memoria associata al messaggio.