lunedì 16 novembre 2015

Mandare email dal server livecode

Livecode, oltre ad essere un ottimo linguaggio di programmazione, è disponibile anche come server web.
Se abbiamo installato il livecode server su un sistema operativo Linux (o Mac), possiamo appoggiarci a un programma di posta già presente, in modo da poterlo sfruttare anche con altre applicazioni.
Uno dei programmi sempre presenti su linux è sendmail.
Qui di seguito vediamo il codice del messaggio che potremmo usare per inviare le email:

on mail pTo, pSub, pMsg, pFrom, pCc, pBcc, pHtml, pAtts
   #Questo messaggio serve per mandare le email
   #ogni indirizzo può essere del tipo "nome <indirizzo_email>"
   # gli indirizzi possono essere separati da virgola
   # la lista degli indirizzi, in alternativa, può essere un array, con un array degli allegati per ognugno
   #Variabili:
   -- pTo       - La lista degli indirizzi a cui spedire
   -- pSub       - L'oggetto del messaggio
   -- pMsg       - Il corpo del messaggio
   -- pFrom    - L'indirizzo email del mittente
   -- pCc       - La lista degli indirizzi in copia (CC)
   -- pBcc       - La lista degli insirizzi in copia nascosta (BCC)
   -- pHtml       - Questa variabile può essere true o false, e indica se il messaggio deve essere in HTML o meno
   -- pAtts       - L'array degli allegati da spedire, nella forma:
   --                   * name: il nome dell'allegato
   --                   * path: il percorso assoluto di dove si trova l'allegato sul server
   --                   * type: il tipo MIME dell'allegato
   
   #Qui costruiamo l'header del messaggio anche con gli indirizzi A: e CC:   
   put "From:" && pFrom & return & "To:" && pTo & return & "Subject:" && pSub & return into tMsg   
   if pCc is not empty then
      put "Cc:" && pCc & return after tMsg
   end if
   
   #qui mettiamo il separatore per gli allegati (multipart)   
   if pAtts is an array then
      local tBoundary
      put "boundary" & the seconds into tBoundary
      put "MIME-Version: 1.0" & return & "Content-Type: multipart/mixed; boundary=" & wrapQ(tBoundary) & return & "--" & tBoundary & return after tMsg
   end if
   
   #qui mettiamo il corpo del messaggio (HTML o TEXT)   
   if pHtml is true then
      put "Content-Type: text/html;" & return & return after tMsg
   else
      put "Content-Type: text/plain;" & return & return after tMsg
   end if
   put pMsg & return after tMsg
   
   #qui mettiamo gli allegati
   if pAtts is an array then
      put "--" & tBoundary & return after tMsg
      repeat for each element tAtt in pAtts
         if there is a file tAtt["path"] then
            if tAtt["type"] is empty then
               get "application/octet-stream"
            else
               get tAtt["type"]
            end if
            put "Content-Type:" && it & "; name=" & wrapQ(tAtt["name"]) & ";" & return & "Content-Transfer-Encoding: base64;" & return & return & base64Encode(URL ("binfile:" & tAtt["path"])) & return & "--" & tBoundary & return after tMsg
         end if
      end repeat
   end if
   
   #spediamo l'email con sendmail. Lo chiamiamo da shell e poi mandiamo la stessa email agli indirizzi in BCC.
   get shell("echo" && wrapQ(shellEscape(tMsg)) && "| /usr/sbin/sendmail" && wrapQ(shellEscape(pTo)) && "-f" && wrapQ(shellEscape(pFrom)))
   if pBcc is not empty then
      get shell("echo" && wrapQ(shellEscape(tMsg)) && "| /usr/sbin/sendmail" && wrapQ(shellEscape(pBcc)) && "-f" && wrapQ(shellEscape(pFrom)))
   end if
   #FINE   
end mail

function shellEscape pText
    repeat for each char tChar in "\`!$" & quote
       replace tChar with "\" & tChar in pText
    end repeat
    return pText
end shellEscape

-- wrap quotes around text
function wrapQ pText
    return quote & pText & quote
end wrapQ


Come vedete è quasi più grande il commento per spiegare come funziona che il codice del messaggio.
In fondo ci sono due funzioni piccolissime: una per mettere il carattere di escape per i caratteri riservati della shell (shellEscape()), l'altra funzione (wrapQ()) serve solo a mettere il virgolette all'inizio e alla fine di una stringa.
Interessante è la stringa utilizzata per separare gli allegati è creata unendo il la parola "boudary" con il numero che esce fuori con la funzione seconds(). Per chi non lo sapesse la funzione seconds indica il numero di secondi tra l'istante corrente è il 1/1/1970. In questo modo non ci dovrebbero essere problemi a separare gli allegati tra loro.
Dove vedete due e commerciali ("&&"), non è un errore, bensì è un sistema più veloce equivalente a scrivere "& space &".
Il resto del codice è tutto commentato, ma se avete domande, fatele pure nei commenti e proverò a rispondervi.