Invio di posta elettronica con SMTP e SSL mediante le funzioni esterne del API di Libcurl

Da Gambas-it.org - Wikipedia.

Libcurl è una libreria gratuita lato-client di trasferimento dati con la sintassi URL, capace di supportare diversi protocolli. Essa consente - fra l'altro - di inviare posta elettronica.

Per poter fruire in Gambas delle risorse della libreria Libcurl, è necessario avere installata nel sistema e richiamare la libreria dinamica condivisa: "libcurl.so.4.7.0 ".


L'esempio pratico, che di seguito mostriamo, consente di inviare una e-mail ad uno o più destinatari corrispondenti agli indirizzi:

  • To:
  • Cc:
  • Ccn

Gli indirizzi di posta elettronica del mittente e dei destinatari devono essere compresi fra i segni di maggiore > e minore <

<nome_utente@dominio.xx>

Va impostato almeno un indirizzo di posta elettronica di un destinatario. Qualora non si intenda imposare uno o due indirizzi dei destinatari, bisognerà porre nella rispettiva stringa dell'indirizzo uno spazio:

" "

Nell'esempio - per la gestione corretta di una prevista linked list - si farà uso di alcune righe di codice, scritto in C, mediante la generazione di apposita libreria dinamica .so esterna.

' Imposta l'indirizzo di posta elettronica del mittente:
Private Const MITTENTE As String = "<nome_utente@dominio>"

' Imposta l'indirizzo di posta elettronica dei destinatari:
Private Const DESTINATARIO As String = "<nome_utente@dominio>"
Private Const CC As String = "<nome_utente@dominio>"
' Se non si vuole impostare un "qualunque" destinatario, è necessario porre un semplice spazio fra le doppie-virgolette:
Private Const CCN As String = " "

Public Struct upload_status
  lines_read As Integer
End Struct

Private costrutto As String[] = ["From: " & MITTENTE & "\r\n",
                                 "To: " & DESTINATARIO & "\r\n",
                                 "Cc: " & CC & "\r\n",
                                 "Ccn: " & CCN & "\r\n",
                                 "Subject: Esempio di messaggio con SMTP SSL\r\n",
                                 "\r\n",   ' Linea vuota per dividere l'intestazione dal corpo del testo, vedere RFC5322
                                 "Prima riga del testo del messaggio.\r\n",
                                 "Seconda riga del testo del messaggio.\r\n",
                                 "\r\n",
                                 "Terza riga del testo del messaggio.\r\n",
                                 "\nQuarta riga del testo del messaggio.\r\n",
                                 Null]
                                   

Library "libcurl:4.7.0"

Private Const CURLOPT_USERNAME As Integer = 10173
Private Const CURLOPT_PASSWORD As Integer = 10174
Private Const CURLOPT_URL As Integer = 10002
Private Const CURLOPT_MAIL_FROM As Integer = 10186
Private Const CURLOPT_READFUNCTION As Integer = 20012
Private Const CURLOPT_READDATA As Integer = 10009
Private Const CURLOPT_UPLOAD As Integer = 46
Private Const CURLOPT_VERBOSE As Integer = 41

' CURL *curl_easy_init(void)
' Start a libcurl easy session.
Private Extern curl_easy_init() As Pointer

' CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...)
' Set options for a curl easy handle
Private Extern curl_easy_setopt(curl As Pointer, option As Integer, opts As String) As Integer
Private Extern curl_easy_setopt_callback(curl As Pointer, option As Integer, callback As Pointer) As Integer Exec "curl_easy_setopt"
Private Extern curl_easy_setopt_upload_Status(curl As Pointer, option As Integer, us As Upload_status) As Integer Exec "curl_easy_setopt"

' CURLcode curl_easy_perform(CURL *curl)
' Perform a blocking file transfer.
Private Extern curl_easy_perform(curl As Pointer) As Pointer

' const char *curl_easy_strerror(CURLcode)
' Turn a CURLcode value into the equivalent human readable error string.
Private Extern curl_easy_strerror(CURLcode As Integer) As String

' void curl_easy_cleanup(CURL *curl)
' End a libcurl easy handle.
Private Extern curl_easy_cleanup(curl As Pointer)


Library "/tmp/lib_cu"

' void Imposta_Destinatari(CURL *curl, char * dest[])
Private Extern Imposta_Destinatari(curl As Pointer, dest As String[])


Public Sub Main()

 Dim cu As Pointer
 Dim upload_ctx As New Upload_status
 Dim ris As Integer
 Dim destinazioni As String[]
 Dim l As Long
 
' Va a generare l'apposita libreria dinamica condivisa esterna:
  CreaSo()
  
  destinazioni = [DESTINATARIO, CC, CCN]
  
  cu = curl_easy_init()
  If cu = 0 Then Error.Raise("Impossibile inizializzare la libreria 'curl' !")
   
' Imposta il nome dell'utente dell'account email e la sua password:
  curl_easy_setopt(cu, CURLOPT_USERNAME, "nome_utente")
  curl_easy_setopt(cu, CURLOPT_PASSWORD, "password_utente")
   
' L'URL del mailserver dell'utente:
  curl_easy_setopt(cu, CURLOPT_URL, "smtps://mainserver.esempio.it")
   
' Imposta il mittente dell'email:
  curl_easy_setopt(cu, CURLOPT_MAIL_FROM, MITTENTE)
   
  Imposta_Destinatari(cu, destinazioni)
  
  curl_easy_setopt_callback(cu, CURLOPT_READFUNCTION, Dati)
  curl_easy_setopt_upload_Status(cu, CURLOPT_READDATA, upload_ctx)
  l = CLong(Val("&" & "1"))
  curl_easy_setopt(cu, CURLOPT_UPLOAD, l)
  curl_easy_setopt(cu, CURLOPT_VERBOSE, l)
  
' Invia la posta elettronica:
  ris = curl_easy_perform(cu)
  If ris <> 0 Then Error.Raise("Invio dell'email non riuscito: " & curl_easy_strerror(ris))
   
   
' Va in chiusura:
  curl_easy_cleanup(cu)
  
End 

Private Function Dati(ptr As Pointer, size As Long, nmemb As Long, userdata As Pointer) As Long
 
 Dim upload_ctx As Upload_status
 Dim data As String
 Dim lenl As Long
 Dim st As Stream
 
  upload_ctx = userdata
  
  If ((size = 0) Or (nmemb = 0) Or ((size * nmemb) < 1)) Then Return
   
  data = costrutto[upload_ctx.lines_read]
  
  If IsNull(data) = False
    lenl = Len(data)
    st = Memory ptr For Write
    Write #st, data, lenl
    st.Close
    Inc upload_ctx.lines_read
    Return lenl
  Endif
  
  Return 0
  
End 

Private Procedure CreaSo()
 
 File.Save("/tmp/lib_cu.c", "#include <curl/curl.h>" &
 "\n\n" &
 "void Imposta_Destinatari(CURL *curl, char * dest[]) {" &
 "\n\n" &
 "   struct curl_slist *recipients = NULL;" &
 "\n\n" &
 "/* Aggiunge tre 'recipients', che in questo caso corrispondono agli indirizzi:\n" &
 "*  To:\n" &
 "*  Cc:\n" &
 "*  Ccn:\n*/\n" &
 "   if (*dest[0] != 0x20)\n" &
 "      recipients = curl_slist_append(recipients, dest[0]);\n" &
 "   if (*dest[1] != 0x20)\n" &
 "      recipients = curl_slist_append(recipients, dest[1]);\n" &
 "   if (*dest[2] != 0x20)\n" &
 "      recipients = curl_slist_append(recipients, dest[2]);\n\n" &
 "   curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);\n\n}")
 
 Shell "gcc -o /tmp/lib_cu.so /tmp/lib_cu.c -lcurl -shared -fPIC" Wait
 
End


Riferimenti