How to send an attachment with email using libcurl and c language? - c

I am using curl library for email sending.
I am able to send email successfully. I can see FROM, Subject and body properly at receiving end.
Now my need is for attachment in the email.
I have followed in this way:
http://msdn.microsoft.com/en-us/library/ms526560(v=exchg.10).aspx
static const char *text[]={
"Date: Wed, 06 Feb 2013 12:30:30 +1100\n",
"To: " RECIPIENT "\n",
"From: " MAILFROM "\n",
"MIME-Version: 1.0",
"Content-Type: multipart/mixed",
"boundary=""XXXXX""\n",
"Subject: email example message\n",
"--XXXXX",
"\n", /* empty line to divide headers from body, see RFC5322 */
"The body of the message starts here.\n",
"Check RFC5322.\n",
"--XXXXX",
"Content-Type: text/plain" "\n",
"Content-Disposition: attachment" "\n",
"filename="FILE_PATH "\n",
"--XXXXX--",
NULL
};
They are suggesting RFC5322. But in that I could not find anything like attachment.
Is it correct? Any other way using libcurl + C language is also welcomed.
I think the person named as Jorge has asked same kind of question on october 13,2012. But the answer is not there.

The easiest way is to encode using something like base64 encoding which turns binary data into ASCII characters that are able to be sent via email. base64 encode the file and insert the string as below. Replace everything in caps with the correct stuff.
--XXXXboundary text
Content-Type: application/FILETYPE; name="FILENAME"
Content-Disposition: attachment; filename="FILENAME"
Content-Transfer-Encoding: base64
STRINGFROMBASE64ENCODING
Heres a thread on base64: How do I base64 encode (decode) in C?

I think you are right, but why did you attached a null file? I think you need put something in the final attachment body apartment.
For example:
--XXXXboundary text
Content-Type: text/plain;
Content-Disposition: attachment;
filename="test.txt"
this is the attachment text ---- this is attachment content
--XXXXboundary text--

Maybe you should take a look at libquickmail (http://sf.net/p/libquickmail/).
It does all the magic needed to attach files and it uses libcurl for the SMTP transport (or even without libcurl in libquickmaillight).

It can be done as below;
static const char *payload_text[] = {
"To: " TO "\r\n",
"From: " FROM "(Example User)\r\n",
"Cc: " CC "(Another example User)\r\n",
"Subject: SMTPS Example\r\n",
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
"User-Agent: My eMail Client\r\n",
"MIME-Version: 1.0\r\n",
"Content-Type: multipart/mixed;\r\n",
" boundary=\"------------030203080101020302070708\"\r\n",
"\r\nThis is a multi-part message in MIME format.\r\n",
"--------------030203080101020302070708\r\n",
"Content-Type: text/plain; charset=utf-8; format=flowed\r\n",
"Content-Transfer-Encoding: 7bit\r\n",
"\r\n", /* empty line to divide headers from body, see RFC5322 */
"The body of the message starts here.\r\n",
"\r\n",
"It could be a lot of lines, could be MIME encoded, whatever.\r\n",
"Check RFC5322.\r\n\r\n",
"--------------030203080101020302070708\r\n",
"Content-Type: text/plain; charset=utf-8; format=flowed\r\n",
" name=\"send.c\"\r\n",
"Content-Type: text/plain; charset=utf-8; format=flowed\r\n",
"Content-Disposition: attachment;\r\n",
" filename=\"abc.txt\"\r\n",
"\r\n",
"bla bla file content is here\r\n",
"--------------030203080101020302070708--\r\n",
NULL
};

Related

Openssl library for interacting with POP3 local server inconsistency while retrieving response

Im working with on pop3 clinet using openSSL library. However I run to this incosistency problem, when reading from BIO socket, 4 times out of 5 there is "\r\n.\r\n" at the end, indicating end of multi-line response from server. But sometimes only "\r\n" is being returned for some reason, and the rest ".\r\n" appears in the next BIO_read. Buffer is not overflowing, it is set to 1024 length and this happens even in 604 characters long response.
Example:
+OK 555 octets
Return-Path: test1#mail.local
Received: from [127.0.0.1] (mail.local [127.0.0.1])
by LAPTOP-R30GIL79 with ESMTPA
; Wed, 20 Oct 2021 11:55:24 +0200
Message-ID: <dad24da8-dd91-62ed-3338-95fe46890c32#mail.local>
Date: Wed, 20 Oct 2021 11:55:24 +0200
MIME-Version: 1.0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Content-Language: sk
To: test1#mail.local
From: test1 <test1#mail.local>
Subject: testing
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Text testovacej spravy.
.
calling it exactly same after that results in:
+OK 555 octets
Return-Path: test1#mail.local
Received: from [127.0.0.1] (mail.local [127.0.0.1])
by LAPTOP-R30GIL79 with ESMTPA
; Wed, 20 Oct 2021 11:55:24 +0200
Message-ID: <dad24da8-dd91-62ed-3338-95fe46890c32#mail.local>
Date: Wed, 20 Oct 2021 11:55:24 +0200
MIME-Version: 1.0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.2.0
Content-Language: sk
To: test1#mail.local
From: test1 <test1#mail.local>
Subject: testing
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Text testovacej spravy.
\r\n
As you can see ".\r\n" is missing for some reason. Octets does match but it disappear somehow. There are no memory leaks. This is function Im using for reading BIO socket
int readBIO(){
memset(buf, 0, strlen(buf));
int x = BIO_read(bio,buf,BUFF_SIZE);
if (x == 0 )
{
fprintf(stderr, "Error: Trying to read from closed connection.\n");
freeAll();
exit(1);
}else if(x < 0){
if (! BIO_should_retry(bio))
{
fprintf(stderr, "Error: Reading from bio socked has failed.\n");
freeAll();
exit(1);
}
}
if (checkResponse() != 0)
{
fprintf(stderr, "Error: Incorrect command / typo in command detected.\n Or wrong username / password has been entered.\n Server responded with -ERR.\n");
freeAll();
exit(1);
}
return 0;
}
Anyone might have an idea why this is happening?

Gmail API to send an inline images

How can i send an inline images using Google API, here is my sameple code
Kindy let me know what am i missing ?
String email =
"Content-Type: multipart/related; boundary:\"multipart_related_boundary\"\r\n" +
"MIME-Version: 1.0\r\n" +
FROM_ME +
TO + toAddress + "\r\n" +
SUBJECT + "welcome" + "\r\n"
+ "--multipart_related_boundary" + "\r\n" +
"Content-type: image/gif; name=\"083.gif\"\r\n" +
"MIME-Version: 1.0\r\n" +
"Content-ID: <083.gif>\r\n" +
"Content-Disposition: inline\r\n"
+ "--multipart_related_boundary" + "\r\n" +
"MIME-Version: 1.0\r\n" +
"Content-Type: text/html; charset=utf-8\r\n" +
CONTENT_TRANSFER_ENCODING_QUOTED_PRINTABLE +
"<html><body><img src=\"cid:083.gif\"/> welcome " +
"</body></html>\r\n\r\n";
byte[] converted = Base64.encodeBase64(email.getBytes());
String encodedStr = new String(converted);
encodedStr = encodedStr.replace("/", "_").replace("+", "-");
MediaType mediaType = MediaType.parse(APPLICATION_JSON);
RequestBody body = RequestBody.create(mediaType, RAW + encodedStr + END_BRACKET);
Request request = new Request.Builder()
.url(HTTPS_WWW_GOOGLEAPIS_COM_GMAIL_V1_USERS_ME_MESSAGES_SEND).post(body)
.addHeader(AUTHORIZATION,
BEARER + gmailAuthService.getRefreshToken(token).getAccessToken())
.addHeader(CONTENT_TYPE, "multipart/related; boundary:\"multipart_related_boundary\"").build();
Response response = okHttpClient.newCall(request).execute();
Finally in my gmail, i am not able to seethe inline image.
You are including the image section of your MIME message, but not the image itself.
After the Content-ID: <083.gif> and Content-Disposition: inline headers you need to include the actual image. Specifically, you probably want to add a Content-Transfer-Encoding: base64 header to that section and include a base64 encoded image payload.
An easy way to see how it could/should work is to use Gmail to email yourself a short test email with a small image. Then, in Gmail (Web UI) go to the message options (near the Reply button) and select "Show Original". That will show you exactly how the MIME message is built.

email parsing by JavaMail , when mail contents is encoded by BASE64

Mail server: James.
Mail container: Maria DB
Mail parsing source is like below:
Return-Path: <monad#monad.com>
Delivered-To: yoonsang#bsecm.net
Received: from 192.168.10.159 ([192.168.10.159])
by WIN-55ERUE9ID5R (JAMES SMTP Server 2.3.2) with SMTP ID 374
for <monad#monad.net>;
Sat, 14 Nov 2015 16:08:06 +0900 (KST)
Received: from unknown (HELO cas01.bsecm.com) (192.168.10.14)
by 192.168.10.159 with ESMTP; 14 Nov 2015 16:07:48 +0900
X-Original-SENDERIP: 192.168.10.14
X-Original-MAILFROM: monad#monad.com
X-Original-RCPTTO: monad#monad.net
Resent-From: <monad#monad.com>
Received: from spam.bsecm.com (192.168.10.159) by cas01.bsecm.com
(192.168.10.14) with Microsoft SMTP Server (TLS) id 14.3.224.2; Sat, 14 Nov
2015 16:07:42 +0900
Received: from unknown (HELO ?219.255.136.51?) (219.255.136.51) by
192.168.10.159 with ESMTP; 14 Nov 2015 16:07:47 +0900
X-Original-SENDERIP: 219.255.136.51
X-Original-MAILFROM: allcredit#allcredit.co.kr
X-Original-RCPTTO: monad#monad.com
Date: Sat, 14 Nov 2015 16:07:56 +0900
Subject: =?euc-kr?B?W0tCxKu15Vdpc2VJbmZvIMfDt6+9ul3AscDnyKO01MDHIDExv/kgvcW/68Gkurizu7+qvK3A1LTPtNku?=
From: =?euc-kr?B?v8PFqbe5tfc=?= <allcredit#allcredit.co.kr>
To: <monad#monad.com>
Reply-To: <allcredit#allcredit.co.kr>
MIME-Version: 1.0
Content-Transfer-Encoding: BASE64
X-Mailer: Netpion Service Server v3.0.0
X-NetpionMsgID: 1447484876647.10284.1455.759978089,KB06,1006190838.1
Content-Type: multipart/mixed;
boundary="--Netpathy_Netpion.1447484876647.AA"
Message-ID: <11342c7a-220f-4538-9203-3610a6896f3e#CAS01.bsecm.com>
LS0tLU5ldHBhdGh5X05ldHBpb24uMTQ0NzQ4NDg3NjY0Ny5BQQ0KQ29udGVudC1UeXBlOiBtdWx0
aXBhcnQvYWx0ZXJuYXRpdmU7DQoJYm91bmRhcnk9Ii0tTmV0cGF0aHlfTmV0cGlvbi4xNDQ3NDg0
ODc2NjQ3LlpaIg0KDQotLS0tTmV0cGF0aHlfTmV0cGlvbi4xNDQ3NDg0ODc2NjQ3LlpaDQpDb250
NEthVzVwZENncE93bzgNCkwzTmpjbWx3ZEQ0PQ0KDQotLS0tTmV0cGF0aHlfTmV0cGlvbi4xNDQ3
NDg0ODc2NjQ3LkFBLS0NCg==
The contents is encoded by BASE64. At "Content-Transfer-Encoding: BASE64".
When I get contents Java tells me "Missing start boundary" exception.
byte[] messageBody = (byte[])("*FROM DB BLOB DATA*");
Message jamesMail = new MimeMessage(session, new ByteArrayInputStream(messageBody) );
Multipart mp = (Multipart)jamesMail.getContent();
int i = mp.getCount();
And now I decode mail contents.
This can parse mail contents to be readable.
java.io.InputStream is = jamesMail.getInputStream();
java.io.InputStream decodedIs = MimeUtility.decode(is, contentTransferEncoding);
mp = (Multipart)ms.getContent();
for(int m=0; m < mp.getCount(); m++){
// contents text processing
// attached file processing
}
But, mail contents has an attached file with encoded by BASE64.
And my code can not parse that attached file.
Question
-. How can I parsing pre-encoded mail contents using Javamail?
-. How can I parsing pre-encoded attachment file?
The message is incorrectly formatted. Multipart content MUST not be encoded, only "leaf" body parts may be encoded. "Netpion Service Server" is broken, please report the bug to the owner of that software.
You can work around this bug in the server by setting the "mail.mime.ignoremultipartencoding" System property to "false".
Temporary Solution)
I made a message [Header] + [ BASE64 Decoded Contents]
String headerLines = "";
String contentTransferEncoding = "";
while (headers.hasMoreElements()) {
Header h = (Header) headers.nextElement();
headerLines += String.format("%s: %s\r\n",h.getName(),h.getValue());
if(h.getName().equalsIgnoreCase("Content-Transfer-Encoding")){
contentTransferEncoding = (StringUtils.isEmpty(h.getValue()))?"":h.getValue();
}
}
InputStream hStream = new ByteArrayInputStream(headerLines.getBytes());
InputStream is = orgJamesMail.getInputStream();
InputStream decodedIs = MimeUtility.decode(is, contentTransferEncoding);
Message ms = new MimeMessage(session, mm);
mp = (Multipart)ms.getContent();
1. Get header information by String.
2. Convert header information of String to InputStream.
3. Concatenate "header inputstream" and "decoded contents inputstream"
4. And parse concatenated message stream.
Maybe this is need:
System.setProperty("mail.mime.multipart.ignoreexistingboundaryparameter", "false");

Azure upload blob 403

I'm trying to upload file on one of my Azure containers
this is one of my request send with ajax:
headers: Object
Authorization: "SharedKey MYACCOUNT:ENC_KEY"
Content-Type: "application/octet-stream"
data: File
x-ms-blob-type: "BlockBlob"
x-ms-date: "Mon, 19 Oct 2015 13:54:53 GMT"
x-ms-version: "2009-09-19"
type: "PUT"
url: "https://MYACCOUNT.blob.core.windows.net/data-test"
for the ENC_KEY I use :
authorizationHeader =
compute: (options, xhrOptions) ->
sig = #_computeSignature(options, xhrOptions)
result = 'SharedKey ' + options.storageAccount + ':' + sig
result
_computeSignature: (options, xhrOptions) ->
sigString = #_getSignatureString(options, xhrOptions)
key = CryptoJS.enc.Base64.parse(options.primaryKey)
hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key)
hmac.update sigString
hash = hmac.finalize()
result = hash.toString(CryptoJS.enc.Base64)
result
any ideas?
EDIT :
all code for authorizationHeader ->
https://gist.github.com/F4Ke/88debcede3b7e2312b11
2)
ERROR RESPONSE :
PUT https://MYACCOUNT.blob.core.windows.net/data-test 403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.)
3)
#_getCanonicalizedHeadersString
itemcreation.coffee:232 x-ms-blob-type:BlockBlob
x-ms-date:Mon, 19 Oct 2015 14:33:15 GMT
x-ms-version:2009-09-19
#_getSignatureString
PUT
application/octet-stream
x-ms-blob-type:BlockBlob
x-ms-date:Mon, 19 Oct 2015 14:35:19 GMT
x-ms-version:2009-09-19
/MYACCOUNT/MYACCOUNT.blob.core.windows.net/data-test
The REST documentation describing how to sign a message can be found here. You can also take a look at the node shared key implementation hhere - might also help you...

Content-Type of Rest Api returning Null in salesforce

i am trying to call this rest api method
#HttpGet
global static String retrievingNotificationSettings(){
RestRequest req=RestContext.request;
RestResponse res=RestContext.response;
String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
if(req.headers.get('Content-Type').equals('application/xml'))
{
Map<String, SObjectField> fields = Notification_Settings__c.SObjectType.getDescribe().fields.getMap();
Schema.sObjectField T ;
Notification_Settings__c ss;
return 'hello World';
}
if(req.headers.get('Content-Type').equals('application/json'))
return System.JSON.serialize(note);
return null;
My request is
GET /services/apexrest/v.9/notifications/preferences/ritesh HTTP/1.1
X-HostCommonName:
ap1.salesforce.com
Authorization:
OAuth 00D90000000j9AW!AQkAQLba73cDzjXhQ4kkQ2PSru4XpFuJcwr5kg_W_MkZmQnm9vI653FBWeJaABwClQqtJZD_b6j7V0O_elkzvkh7IqRKSUop
X-PrettyPrint:
1
Host:ap1.salesforce.com
X-Target-URI:
https://ap1.salesforce.com
Content-Type: application/json
Connection:Keep-Alive
and the response i am getting is
HTTP/1.1 500 Internal Server Error
Date:
Fri, 25 Jan 2013 16:30:21 GMT
Content-Length:
203
Connection:
close
Content-Type:
application/json; charset=UTF-8
Server:
[
{
"message": "System.NullPointerException: Attempt to de-reference a null object\n\nClass.NotificationRestService.retrievingNotificationSettings: line 34, column 1",
"errorCode": "APEX_ERROR"
}
]
the line where i am getting error is
if(req.headers.get('Content-Type').equals('application/xml'))
i didn't understand why i am getting this error when in header i am passing value Content-Type as application/json ?? please tell me where i am making mistake
Can you System.debug(req.headers) to see if it was passed correctly?
To answer your null pointer question literally - use == instead of equals:
if(req.headers.get('Content-Type') == 'application/xml')
but that won't solve the real underlying problem.
You might want to try with different header (stupid, I know) or decide to add a GET parameter, something like &mode=json

Resources