Sincronizza Indice |
Scarica il progetto |
Testo dell'articolo |
Stampa l'articolo |
Nell'articolo precedente abbiamo visto com'è semplice inviare un'e-mail utilizzando il protocollo mailto; il limite maggiore di quella soluzione è quello di non poter allegare uno o più files al messaggio. Viste le numerosissime richieste sull'argomento abbiamo preferito affrontare anche una seconda soluzione che superasse questo limite. Quest'articolo espone una soluzione leggermente più complessa ma che consente di allegare files all'e-mail.
La soluzione è basata sull'uso delle funzioni Simple-MAPI (Messaging
API) e pertanto richiede l'uso di
un client di posta elettronica MAPI, come Outlook Express, correttamente
configurato. L'insieme delle istruzioni è stato raggruppato in
un modulo di classe
semplicemente riutilizzabile.
La prima delle due enumerazioni specifica il tipo di Recipient (ricevente) ammesso dal metodo AddRecipient trattato successivamente; l'enumerazione eMAPIErrors specifica gli errori conosciuti restituiti dalle funzioni MAPI.
I tre tipi di dati UDT saranno utilizzati per specificare, rispettivamente le informazioni sul Recipient, sul file allegato e sul messaggio da inviare. Ad un livello logico in realtà il tipo MAPIMessage conterrà un riferimento ad un array di recipients (campo Recipients) ed ad un array di files (campo Files) da allegare. Prima di procedere è opportuno approfondire il meccanismo con il quale operano le funzioni di messaggistica MAPI: prima di poter accedere al sistema di ricezione, invio o memorizzazione del programma client MAPI è necessario creare o recuperare una sessione, che dovrà essere specificata durante le operazioni di recupero o di invio di messaggi di posta elettronica.
La costante MAPI_DIALOG consente di confermare il messaggio prima del suo invio e verrà utilizzata su richiesta dell'utente del nostro esempio. Le due costanti MAPI_LOGON_UI e MAPI_PASSWORD_UI sono utilizzate per richiedere esplicitamente di mostrare le finestre di dialogo di accesso, se il cliente di posta lo permette e se si rende necessario. La prima delle funzioni API dichiarate è MAPILogon e consente di recuperare un numero di sessione nuovo o preesistente, con il quale accedere al sistema di messaggistica. Nel nostro esempio proveremo a recuperare un ID di sessione esistente e se non esistente, la medesima funzione ne creerà uno nuovo. È comunque possibile richiedere forzatamente la creazione di un nuovo ID di sessione, senza recuperare quello preesistente, specificando il flag MAPI_NEW_SESSION (corrispondente al valore 2) nel richiamo della funzione MAPILogon.
La funzione MAPILogoff, com'è intuibile, effettua l'operazione di disconnessione dal sistema di posta elettronica liberando l'ID di sessione utilizzato. La funzione MAPISendMail della riga 77 si occuperà quindi di comporre il messaggio di posta elettronica ed eventualmente spedirlo.
La funzione MAPISendMail utilizza una variabile di tipo MAPIMessage di nome m_Message; questa utilizzerà anche due array di nome m_Attachments e m_Recipients, rispettivamente per i files da allegare e per i destinatari del messaggio; le due variabili membro m_AttachmentsCount e m_RecipientsCount rifletteranno semplicemente il numero di allegati e di destinatari. La variabile m_SendImmediately della riga 84 manterrà il valore della proprietà SendImmediately, che determinerà in fase di invio se dovrà essere mostrato il messaggio prima di inviarlo oppure l'invio sarà immediato. L'ultima variabile membro m_SessionID conterrà l'ID di sessione recuperato dalla funzione MAPILogon ed utilizzato per inviare il messaggio.
Le due proprietà in sola lettura AttachmentsCount e RecipientsCount restituiranno rispettivamente il numero di allegati e di recipients al momento associati al messaggio di posta. La prprietà SendImmediately regolerà il comportamento di invio del messaggio come già spiegato in precedenza. La proprietà SessionID restituirà invece l'ID di sessione recuperato dalla funzione MAPILogon in occasione del primo messaggio inviato.
Le ultime due proprietà Body e Subject assegnano e restituiscono il corpo e l'oggetto del messaggio lavorando direttamente sui campi NoteText e Subject della variabile m_Message.
La routine AddRecipient è utilizzata per aggiungere un destinatario al messaggio, composto di nome (Name), indirizzo (Address) e tipo di recipient (RecipType). Sarà utilizzata una variabile di nome udtRecip e di tipo MAPIRecip, che al termine dell'operazione verrà aggiunta all'array di destinatari. Poiché la funzione MAPISendMail si aspetta che nome ed indirizzo del destinatario siano forniti in formato ANSI, è necessario convertirli in questo formato mediante la funzione StrConv (righe 127 e 128). Dalla riga 130 viene aggiunto un elemento alla matrice m_Recipients, cui viene assegnata la variabile udtRecip appena riempita, e viene incrementato il numero di recipients finora assegnati.
I tre metodi AddTo, AddCC e AddBCC dichiarati alle righe 135-145 costituiscono delle mere semplificazioni del metodo AddRecipient dichiarato in precedenza; le stesse infatti non fanno altro che richiamare la routine precedente, aggiungendovi soltanto il tipo di destinatario. La routine Clear azzera semplicemente gli array m_Recipients e m_Attachments ed i due rispettivi contatori. Va utilizzata in occasione della creazione di un nuovo messaggio.
In maniera analoga alla routine AddRecipient, la FileAdd crea una nuova variabile di tipo MAPIFile, vi assegna il nome del file specificato in PathName dopo averlo convertito dal formato Unicode. La stessa sarà quindi aggiunta alla matrice m_Attachments ed il contatore m_AttachmentsCount verrà incrementato.
La funzione Send recupera tutti i dati forniti ed invia il messaggio mediante le funzioni MAPI. Il valore di ritorno della funzione è inizializzato su MAPI_E_INVALID_RECIPS ovvero "Destinatari non validi"; questo perché il messaggio sarà inviato soltanto se esiste almeno un destinatario. Alle righe 166-169 è verificata la presenza di almeno un file allegato; in tal caso i membri FileCount e Files della variabile m_Message sono riempiti con il numero di files allegati e con l'indirizzo dell'array contentente l'elenco dei files. Alle righe 170-176 se esiste almeno un destinatario, viene completo il riempimento della struttura m_Message ed il messaggio viene inviato. Il numero di destinatari viene assegnato al membro RecipCount, mentre l'array contenente i recipients è assegnato al membro Recipients. Alla riga 173, se non esiste già un ID di sessione per l'istanza della classe, viene recuperato mediante la funzione MAPILogon. Tale ID è memorizzato nella variabile m_SessionID e verrà conservato ed utilizzato dalla funzione MAPISendMail successivamente. Anche all'uscita della funzione l'ID di sessione sarà mantenuto, per velocizzare l'eventuale invio di un ulteriore messaggio. Alla riga 174 è verificato il valore della variabile m_SendImmediately e se il suo valore è False, il messaggio non sarà spedito immediatamente ma verrà mostrato all'utente prima di eseguire l'operazione di spedizione. L'opzione è specificata nella variabile lngFlags che sarà quindi passata alla funzione successiva. L'ultima istruzione della funzione richiamerà la funzione MAPISendMail, fornendogli la variabile di tipo MAPIMessage e le opzioni per l'invio, specificati in m_Message e lngFlags. Il valore di ritorno sarà assegnato come valore di ritorno del metodo Send.
Prima di concludere la visione del codice della classe si vuole specificare che il codice da scaricare per questo articolo conterrà anche altre due routine qui non presentate: si tratta di NewMail che in una sola chiamata genera un nuovo messaggio, completo di destinatari multipli, oggetto, corpo ed allegati e provvede anche al suo invio, utilizzando le funzioni sin qui presentate. L'altra funzione non specificata è MAPIError che, ricevendo il numero di errore restituito dalle funzioni Send e NewMail (quindi da MAPISendMessage) restituisce una descrizione del tipo di errore. Costituisce in realtà un lungo elenco di assegnazioni condizionali. La classe si conclude con la routine Class_Terminate che provvederà a disconnettersi dal client MAPI e liberare l'ID di sessione:
La disconnessione è effettuata semplicemente richiamando la funzione MAPILogoff fornendogli l'ID di sessione utilizzato. La dimostrazione d'uso della classe clsMAPISendMail sin qui affrontata passa per la costruzione di uno spartano client di posta elettronica che consenta la specifica di destinatari, oggetto, corpo e files allegati. Per necessità di spazio non sarà trattata la disposizione dei controlli sopra il form, ma il solo codice che, fra l'altro, farà uso del modulo modCommonDialog trattato nell'HowTo dedicato alla scelta di un file. Il codice si compone di tre sole routine legate alla pressione sui pulsanti per l'aggiunta di un destinatario (-> A:, -> Cc:, ->Ccn:), di un file allegato (Aggiungi allegato) e per l'invio del messaggio composto (Invia email):
Se è presente un indirizzo nella casella txtNewRecipient esso sarà accodato alla ListBox lbRecipients; l'operazione è svolta utilizzando la funzione Choose che, lo ricordiamo, è a base 1; pertanto l'indice del pulsante premuto (Index) dovrà essere incrementato di 1. Al termine dell'operazione la casella di testo è svuotata (riga 6).
La pressione del pulsante cmdNewAttachments richiamerà la funzione ShowOpen del modulo modCommonDialog per richiedere il nome di un file da allegare. Se il risultato di quest'operazione è un nome di file (ovvero l'utente non ha premuto il pulsante Annulla) esso sarà aggiunto alla ListBox lbAttachments.
La pressione del pulsante cmdSendMail dovrà raccogliere le informazioni da tutti i controlli e formare con esse un nuovo messaggio nell'istanza SendMail allocata alla riga 21. Il messaggio verrà inizialmente svuotato mediante il metodo Clear (anche se non è strettamente necessario) ed in seguito (righe 24-31) dovranno essere recuperati tutti i destinatari, suddividendoli per tipo di recipient, dalla ListBox. Leggendo infatti il prefisso To, Cc o Bcc dall'elenco è possibile assegnare l'indirizzo al gruppo corretto, mediante i metodi AddTo, AddCC e AddBCC (righe 27-29).
Alle righe 32 e 33 sono riempite le proprietà Subject e Body del messaggio; successivamente saranno recuperati tutti i files dall'elenco lbAttachments ed aggiunti al messaggio mediante il metodo FileAdd. La CheckBox chkSendNow determinerà il valore della proprietà SendImmediately. Raccolte tutte queste informazioni, sarà possibile inviare il messaggio con il metodo Send. Il valore restituito sarà quindi discriminante del messaggio mostrato a seguito dell'invio (righe 39-43). Completata l'operazione sarà possibile deallocare la variabile SendMail. L'esecuzione del progetto con la compilazione di tutti i campi, al momento della pressione del pulsante Invia email richiamerà il client MAPI di posta predefinito (spesso assegnato ad Outlook Express). Nell'esempio mostrato a fianco i destinatari del messaggio sono 3, uno per ciascun tipo di recipient (Diiretto a, Copia carbone e Copia carbone nascosta). Gli stessi sono mostrati sulla destra con i loro rispettivi prefissi To, Cc e Bcc. In fondo sono mostrati i nomi di due files allegati di cui uno eseguibile (WC2.EXE). Il client di posta si occuperà infatti di codificare ove necessario i files in Base64. La spunta sul flag Immediatamente farà si che il messaggio venga inviato direttamente senza una necessaria revisione dello stesso. Senza la spunta invece il messaggio apparirà a video e sarà richiesto l'intervento dell'utente (come per l'articolo precedente). IMPORTANTE!
Alcune versioni recenti di Outlook Express presentano una finestra di conferma simile a quella mostrata a fianco. Ciò rende più sicuro l'uso del programma client, in modo da evitare che lo stesso venga usato a sproposito e senza che l'utente ne venga a conoscenza. Sia che l'utente risponda Invia o Non inviare,
la funzione Send restituirà comunque il risultato 0 e nessun
errore verrà riportato al nostro programma. |
Come la precedente, anche questa soluzione necessita di un account di posta correttamente configurato presso il client di posta; inoltre lo stesso client deve rispondere alle specifiche MAPI. Nonostante le numerose limitazioni di questa soluzione, viste le svariate richieste sull'argomento, abbiamo comunque preferito riportarla ed evidenziarne i punti deboli. Fibia
FBI e Andrea Barchetti
|
Torna all'indice degli HowTo |