Hello,
I have been trying to send mail using cURL from Cobol. I took an example from this forum but I am stuck with the mail body:
Here is the link to the example from cURL http://curl.haxx.se/libcurl/c/smtp-mail.html.
The following code (partly taken from a previous discussion on the forum) seems to work partially :
*> Demo showing how to make an http request from a COBOL program
*> using libcurl.
*> libcurl can be found at http://sourceforge.net/projects/curl/
*> libcurl documentation can be found at http://curl.haxx.se/libcurl/
*>
*> compile as follows:
*> cob -x urltest.cbl -L/usr/lib -lcurl -L/usr/ssl/lib -lssl -lcrypto -ldl
*>
Program-ID. urltest.
Working-Storage Section.
01 Curl-Handle pointer.
01 Bad-Handle pointer.
01 Recipients pointer.
78 CURLOPT-NOTHING value 0.
78 CURLOPT-FILE value 10001.
78 CURLOPT-URL value 10002.
78 CURLOPT-PORT value 3.
78 CURLOPT-ERRORBUFFER value 10010.
78 CURLOPT-WRITEFUNCTION value 20011.
78 CURLOPT-CRLF value 27.
78 CURLOPT-VERBOSE value 41.
78 CURLOPT-HEADER value 42.
78 CURLOPT-NOPROGRESS value 43.
78 CURLOPT-NOBODY value 44.
78 CURLOPT-HEADER-YES value 1.
78 CURLOPT-HEADER-NO value 0.
78 CURLOPT-MAIL-FROM value 10186.
78 CURLOPT-MAIL-RCPT value 10187.
78 CURLOPT-READFUNCTION value 20012.
78 CURLOPT-READDATA value 10009.
78 CURLOPT-UPLOAD value 46 .
78 CURLOPT-VERBOSE value 41 .
78 CURLE-OK value 0 .
78 78True value 1.
78 78FROM value z"<sender@example.org>".
78 78TO value z"<addressee@example.net>".
78 78CC value z"<info@example.org>".
01 Curl-URL pic x(256).
01 Writefunction-Ptr procedure-pointer.
01 Curl-Error-Text pic x(256).
01 Ws-Error pic x(40).
01 Web-Data pic x(65536).
01 Web-Data-Len pic x(04) comp-5 value 0.
01 Web-Data-Max pic x(04) comp-5.
01 Total-Size pic x(04) comp-5.
01 Bytes-Read pic x(04) comp-5.
Linkage Section.
01 Data-In pic x(04) comp-5.
01 Data-Elem-Size pic x(04) comp-5.
01 Data-Elem-Num pic x(04) comp-5.
01 Unused-Ptr pointer.
Procedure Division.
*>Curl-Handle = curl-easy-init();
set Curl-Handle to null
set Bad-Handle to null
call "curl_easy_init" returning Curl-Handle
if Curl-Handle = Bad-Handle then
move "Easy Init Error" to Ws-Error
perform 9000-Error
*> quit the program
end-if
display "Init OK"
call "curl_easy_setopt"
using by value Curl-Handle
by value CURLOPT-VERBOSE size 4
by value 78True size 4
end-call
if Return-Code not = 0
move "Verbose Error" to Ws-Error
perform 9000-Error
else
display "CURLOPT-VERBOSE OK"
end-if
*> This is the URL for your mailserver */
move z"smtp://mail.example.com" to Curl-URL
call "curl_easy_setopt"
using by value Curl-Handle
by value CURLOPT-URL size 4
by reference Curl-URL
end-call
if Return-Code not = CURLE-OK then
move "Smtp Error" to Ws-Error
perform 9000-Error
else
display "smtp ok"
end-if
*> Note that this option isn't strictly required, omitting it will result in
*> libcurl sending the MAIL FROM command with empty sender data. All
*> autoresponses should have an empty reverse-path, and should be directed
*> to the address in the reverse-path which triggered them. Otherwise, they
*> could cause an endless loop. See RFC 5321 Section 4.5.5 for more details.
*>curl-easy-setopt(Curl-Handle, CURLOPT-MAIL-FROM, FROM);
move 78From to Curl-URL
call "curl_easy_setopt"
using by value Curl-Handle
by value CURLOPT-MAIL-FROM size 4
by reference Curl-URL
end-call
if Return-Code not = CURLE-OK then
move "FROM Error" to Ws-Error
perform 9000-Error
else
display "FROM ok"
end-if
set recipients to null
*> Add two recipients, in this particular case they correspond to the
*> To: and Cc: addressees in the header, but they could be any kind of
*> recipient. */
*>recipients = curl-slist-append(recipients, TO);
*>recipients = curl-slist-append(recipients, CC);
call "curl_slist_append"
using by value recipients
by reference 78TO
returning recipients
if Return-Code not = CURLE-OK then
move "recipients Error" to Ws-Error
perform 9000-Error
else
display "recipients ok"
end-if
*>curl-easy-setopt(Curl-Handle, CURLOPT_MAIL_RCPT, recipients);
call "curl_easy_setopt"
using by value Curl-Handle
by value CURLOPT-MAIL-RCPT size 4
by value recipients
end-call
if Return-Code not = CURLE-OK then
move "TO Error" to Ws-Error
perform 9000-Error
else
display "TO ok"
end-if
*> callback function
call "curl_easy_setopt"
using by value Curl-Handle
by value CURLOPT-ERRORBUFFER size 4
by reference Curl-Error-Text
end-call
if Return-Code not = 0
move "Set Option ErrorBuffer Error" to Ws-Error
perform 9000-Error
else
display "CURLOPT-ERRORBUFFER OK"
end-if
call "curl_easy_setopt"
using by value Curl-Handle
by value CURLOPT-HEADER size 4
by value CURLOPT-HEADER-NO size 4
end-call
if Return-Code not = 0 then
move "Set Option Header Error" to Ws-Error
perform 9000-Error
else
display "CURLOPT-HEADER OK"
end-if
set Writefunction-Ptr to entry "curl-callback"
call "curl_easy_setopt"
using by value Curl-Handle
by value CURLOPT-WRITEFUNCTION size 4
by value Writefunction-Ptr
end-call
if Return-Code not = 0 then
move "Set Option Writefunction Error" to Ws-Error
perform 9000-Error
else
display "CURLOPT-WRITEFUNCTION OK"
end-if
*> We're using a callback function to specify the payload (the headers and
*> body of the message). You could just use the CURLOPT-READDATA option to
*> specify a FILE pointer to read from. */
*>curl_easy_setopt(Curl-Handle, CURLOPT-READFUNCTION, payload-source);
*>curl_easy_setopt(Curl-Handle, CURLOPT-READDATA, &upload-ctx);
*>curl_easy_setopt(Curl-Handle, CURLOPT-UPLOAD, 1L);
*> Here I should have the body of the message
*> Send the message */
*> res = curl-easy-perform(Curl-Handle);
call "curl_easy_perform"
using by value Curl-Handle
end-call
if Return-Code not = CURLE-OK then
move "Perform Error" to Ws-Error
perform 9000-Error
else
display "Send ok"
end-if
*> Check for errors
*> if (res != CURLE-OK)
*> fprintf(stderr, "curl-easy-perform() failed: %s\n",
*> curl-easy-strerror(res));
*>
*> /* Free the list of recipients */
*>curl-slist-free-all(recipients);
*> curl won't send the QUIT command until you call cleanup, so you should be
*> able to re-use this connection for additional messages (setting
*> CURLOPT-MAIL-FROM and CURLOPT-MAIL-RCPT as required, and calling
*> curl-easy-perform() again. It may not be a good idea to keep the
*> connection open for a very long time though (more than a few minutes may
*> result in the server timing out the connection), and you do want to clean
*> up in the end.
*>
*>curl-easy-cleanup(Curl-Handle);
call "curl_easy_cleanup" using by value Curl-Handle end-call
if Return-Code not = CURLE-OK then
move "Cleanup Error" to Ws-Error
perform 9000-Error
else
display "cleanup ok"
end-if
continue
goback.
9000-Error.
display Ws-Error
display "Return-Code: " Return-Code
display "Error Text: " Curl-Error-Text
call "curl_easy_cleanup" using by value Curl-Handle
goback.
Program-Termination.
entry "curl-callback"
using by reference Data-In
by value Data-Elem-Size
by value Data-Elem-Num
by value Unused-Ptr.
E1000-Buffer-Data.
compute Total-Size = (Data-Elem-Size * Data-Elem-Num)
compute Web-Data-Max = (length of Web-Data - Web-Data-Len)
if Total-Size > Web-Data-Max then
move Web-Data-Max to Total-Size
end-if
move Data-In(1:Total-Size)
to Web-Data(Web-Data-Len + 1:Total-Size)
add Total-Size to Web-Data-Len
move Total-Size to Bytes-Read
goback returning Bytes-Read.
Entry-Termination.
When it comes to modifiying this section :
*>curl_easy_setopt(Curl-Handle, CURLOPT-READFUNCTION, payload-source);
*>curl_easy_setopt(Curl-Handle, CURLOPT-READDATA, &upload-ctx);
*>curl_easy_setopt(Curl-Handle, CURLOPT-UPLOAD, 1L);
i must confess that I don't kno how to handle it in cobol
Has someone an idea on how to proceed ?
Regards,