Amazon SES Sending email with attachments - amazon-web-services

I am trying to send mails with attachment by using Amazon SES
HttpRequest httpReq = new HttpRequest();
httpReq.setMethod('POST');
httpReq.setEndpoint('https://email.us-east-1.amazonaws.com');
Blob bsig = Crypto.generateMac('HmacSHA256', Blob.valueOf(awsFormattedNow), Blob.valueOf(secret));
httpReq.setHeader('X-Amzn-Authorization','AWS3-HTTPS AWSAccessKeyId='+key+', Algorithm=HmacSHA256, Signature='+EncodingUtil.base64Encode(bsig));
httpReq.setHeader('Date',awsFormattedNow);
httpReq.setHeader('From','sample#gmail.com');
httpReq.setHeader('To','sample#gmail.com');
httpReq.setHeader('Subject','Hello');
httpReq.setHeader('Accept-Language','en-US');
httpReq.setHeader('Content-Language','en-US');
httpReq.setHeader('Content-Type','multipart/mixed;boundary=\"_003_97DCB304C5294779BEBCFC8357FCC4D2\"');
httpReq.setHeader('MIME-Version','1.0');
// httpReq.setHeader('Action','SendRawEmail');
String email = 'Action=SendRawEmail';
email += '--_003_97DCB304C5294779BEBCFC8357FCC4D2 \n Content-Type: text/plain; charset="us-ascii" \n Content-Transfer-Encoding: quoted-printable \n';
email +='Hi Andrew. Here are the customer service names and telephone numbers I promised you.';
httpReq.setBody(email);
System.debug(httpReq.getBody());
Http http = new Http();
HttpResponse response = http.send(httpReq);
I am getting error like
<AccessDeniedException>
<Message>Unable to determine service/operation name to be authorized</Message>
</AccessDeniedException>
Kindly please help me where i am doing wrong .Thanks in advance

Take another look at the documentation. There are several issues with your code.
SES expects an HTTP POST with all of the parameters strung together consistent with application/x-www-form-urlencoded POST requests.
Your HTTP request needs to be Content-type: application/x-www-form-urlencoded, not multipart/mixed... -- that's part of the raw message you're trying to send.
You are mixing up things that should be in the body, and setting HTTP request headers, instead. For example, these are also incorrect:
httpReq.setHeader('From','sample#gmail.com');
httpReq.setHeader('To','sample#gmail.com');
httpReq.setHeader('Subject','Hello');
These should go in the request body, not in the HTTP request headers. Also, the values are urlencoded. From the example code:
Action=SendEmail
&Source=user%40example.com
&Destination.ToAddresses.member.1=allan%40example.com
The line breaks were added for clarity.
Your interests might be best served by trying to successfully send a simple e-mail, first, and then later attempting to modify your code to support attachments, because you have numerous errors that will need to be corrected before this code will work properly.
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/query-interface-requests.html
http://docs.aws.amazon.com/ses/latest/APIReference/API_SendRawEmail.html

Related

what should be the User-Agent header for this call?

this code snippet is taken from Postman. cURL taken from the postman works fine and java code generated from postman gives a 200 response for the particular call. but the response body is not there.
what should be the user agent header?
Do I need to use this postman token in my java code as well?
Do I need to add additional headers?
My Goal is to fetch some data from this GET call.
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://blahblah=60041441&attributes=blah,blah,blah")
.get()
.addHeader("User-Agent", "PostmanRuntime/7.13.0")
.addHeader("Accept", "*/*")
.addHeader("Cache-Control", "no-cache")
.addHeader("Postman-Token", "7af03a15-blah,364c160f-92d7-459f-b261-4993801944a7")
.addHeader("Host", "blahblah.na.blah.net:9081")
.addHeader("cookie", "someURL=1800; com.ibm.isim.lastActivity=blahblahToekn; JSESSIONID=blahblahblah:1ajblahi8; LtpaToken2=blahblahbalah")
.addHeader("accept-encoding", "gzip, deflate")
.addHeader("Connection", "keep-alive")
.addHeader("cache-control", "no-cache")
.addHeader("User-Agent", "postman")
.build();
okhttp3.Response response= client.newCall(request).execute();
System.out.println(response.body().toString());
Suppose for simple get request following will do just fine, all other details can be omitted:
Request request = new Request.Builder()
.url("http://blahblah=60041441&attributes=blah,blah,blah")
.get()
.build();
Most of the headers (like user-agent, accept-encoding etc) will be automatically added by OkHttp client, so you can safely remove those from request:
.addHeader("User-Agent", "PostmanRuntime/7.13.0")
.addHeader("Host", "blahblah.na.blah.net:9081")
.addHeader("accept-encoding", "gzip, deflate")
.addHeader("Cache-Control", "no-cache")
.addHeader("Connection", "keep-alive")
.addHeader("cache-control", "no-cache")
.addHeader("User-Agent", "postman")
Since / is a wildcard, suppose you can skip it as well.
.addHeader("Accept", "*/*")
If you endpoint requires authentication, suppose before sending this particular Get request you need to send authentication request first. To automatically handle authentication cookies you can try to add CookieJar to your client, so those can be omitted as well (assume headers names were altered somehow, btw?):
.addHeader("Postman-Token", "7af03a15-blah,364c160f-92d7-459f-b261-4993801944a7")
.addHeader("cookie", "someURL=1800; com.ibm.isim.lastActivity=blahblahToekn; JSESSIONID=blahblahblah:1ajblahi8; LtpaToken2=blahblahbalah")
You can also check answers for that question about the ways to add CookieJar.

identifying the proper syntax for using HTTP dataset in ADFv2

I am able to successfully use Postman to authenticate and subsequently get data housed within a sandbox but I cannot figure out how to specify the same data within ADFv2.
I'm expecting to retrieve, temporarily store and later use a bearer token that this API generates. This token is then used in the second step that actually downloads the data I want in JSON format.
For the Authentication step, Postman generates code that looks this:
POST /v1/oauth/token HTTP/1.1
Host: api.sandbox.COMPANY.com
Ocp-Apim-Subscription-Key: MYKEY
Content-Type: multipart/form-data; boundary=----
WebKitFormBoundaryALPHANUM
cache-control: no-cache
Postman-Token: MYTOKEN
Content-Disposition: form-data; name="key"
MYKEY
Content-Disposition: form-data; name="grant_type"
vapi_key
------WebKitFormBoundaryALPHANUM--
I've created a linked HTTP and REST connection in ADFv2 with the base URL of "https://api.sandbox.COMPANY.com" and using no authentication.
I cannot figure out how to translate the functional Postman connection to a way that ADFv2 will work. Thoughts?
You could check this example.
https://learn.microsoft.com/en-us/azure/data-factory/connector-http#dataset-properties

Using postman to test POST request, how do I access the form-data inside the request?

I've been googling for a few hours, and I need help. I dont think I'm using the correct words. Anyhow, I'm using Claudia.JS to set up a POST request to my AWS Lambda function. Here's the basics of the function:
api.post('/leads', function (request) {
console.log(request);
return request;
});
When I use postman to test the post request, I'm returned the request object. Awesome. Then I try to pass form-data through. I set the key to 'username' and the value to 'this is the username'. This is what request.body is:
"body": "---------------------------
-019178618034620042564575\r\nContent-Disposition: form-data;
name=\"username\"\r\n\r\nthis is the username\r\n----------------------
------019178618034620042564575--\r\n",`
I thought I could return request.body.username... to key the value of username...but I'm missing something.
How do I access the form data in the request?
update: okay. The website is taking the form data, making a post request...this function is receiving the post request? still-- in postman...if I were to put my own JSON in...why can I not access request.body like... request.body.username?
You should try console.log(request.data) to see your request object, ie. in my own case I can see the content of my request's body.
Have a look at https://www.getpostman.com/docs/postman/scripts/postman_sandbox to see all the relevant information about your request.
I solved this by looking at the header set in postman. It was set to form-data instead of application/JSON. All gravy now.

Can libcurl.net be used to post a new page to confluence?

I'm just getting started using the REST API to create pages.
I'm trying to configure a basic example and I thought of using libcurl.net to do it.
Does anyone see any reason why that wouldn't work?
UPDATE:
Here is what I have so far adapted from the curllib.net "bookpost" example
Option Explicit On
Imports System.IO
Imports System.Net
Imports SeasideResearch.LibCurlNet
Public Class CurlOperations
Public Shared Sub CurlPost()
Try
Dim credUserName As String = "username"
Dim credPassword As String = "password"
Dim response As String = Nothing
Dim outputStdErr As Stream = Nothing
Curl.GlobalInit(CURLinitFlag.CURL_GLOBAL_ALL)
Dim easy As Easy
easy = New Easy
' Set up write delegate
Dim wf As Easy.WriteFunction
wf = New Easy.WriteFunction(AddressOf OnWriteData)
easy.SetOpt(CURLoption.CURLOPT_WRITEFUNCTION, wf)
'Authentication
easy.SetOpt(CURLoption.CURLOPT_HTTPAUTH, CURLhttpAuth.CURLAUTH_BASIC)
easy.SetOpt(CURLoption.CURLOPT_USERPWD, credUserName & ":" & credPassword)
'disable ssl peer verification
easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYPEER, False)
'Header
easy.SetOpt(CURLoption.CURLOPT_HTTPHEADER, "Content-Type: application/json; charset=utf-8")
' Simple post - with a string
easy.SetOpt(CURLoption.CURLOPT_POSTFIELDS, WikiTools.CommREST.WebToCF.PostCurl())
' and the rest of the cURL options
easy.SetOpt(CURLoption.CURLOPT_USERAGENT, ".NET Framework Client")
easy.SetOpt(CURLoption.CURLOPT_URL, "https://domain.com/confluence/rest/api/content/")
easy.SetOpt(CURLoption.CURLOPT_POST, True)
response = easy.Perform().ToString
LoggingAndActivites.WriteLog("Response: " & response, GetFunctionName.GetCallerName, True, True)
Catch ex As Exception
LoggingAndActivites.WriteLog("Exception: " & ex.ToString, GetFunctionName.GetCallerName, True, True)
End Try
Curl.GlobalCleanup()
End Sub
' Called by libcURL.NET when it has data for your program
Public Shared Function OnWriteData(ByVal buf() As Byte, ByVal size As Int32, ByVal nmemb As Int32, ByVal extraData As Object) As Int32
LoggingAndActivites.WriteLog(System.Text.Encoding.UTF8.GetString(buf), GetFunctionName.GetCallerName, True, True)
Return size * nmemb
End Function
End Class
I am getting connected because if I remove the username and password I get a response through the "onWriteData" function as follows:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>401 Unauthorized</title>
</head>
<body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested. Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache Server at domain.com Port 7080</address>
</body>
</html>
The problem now is that if I correctly log on I'm not getting any response other than the "CURLE_OK" from the "easy.Perform()" function.
It's good because I know it's working to some degree.
According to the libcurl.net docs : http://www.libcurl.org/
libcurl also supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, and user+password authentication.
So I guess you should be able to make a REST API call with it. I have used curl (the linux version) to create and update pages, using something like this:
curl --globoff --insecure --silent -u username:password -X PUT -H 'Content-Type: application/json' --data #body.json confluenceRestAPIURL/pageId
where body.json is a file containing the data to update the page.
I wrote a blog about this here: https://javamemento.blogspot.no/2016/05/jira-confluence-3.html
You can get the code here: https://github.com/somaiah/jira-confluence-graphs
So it does work
Here is what I added/changed to make the code above work
'I added an Slist to store the header items (I only had one)
Dim slistHeaders As New Slist
slistHeaders.Append("Content-Type: application/json")
'Then I added the slist to the HTTPHEADER
easy.SetOpt(CURLoption.CURLOPT_HTTPHEADER, slistHeaders)
THINGS TO WATCH FOR:
(1) The URL of course is the number one thing
In my case I was using was https://domain.com/confluence/rest/api/content/ because the Confluence Documentation assumes you would be using the root domain name (as did I)
However, what I didn't know was that the URL I was given to test was already directing me into the "confluence" folder.
So my URI needed to be https://domain.com/rest/api/content/ instead
(2) An indicator that your HTTPHEADER needs to be put into an Slist is this return from the server: 415 Unsupported Media Type
(3) Be sure NOT to use the CURLOPT_HEADER property. If you are seeing this header in your responses you need to make sure it's not used:
HTTP/1.1 500 Internal Server Error
Date: Sun, 22 May 2016 17:50:32 GMT
Server: Apache
Content-Location: 500.en-GB.html
Vary: negotiate,accept-language
TCN: choice
Accept-Ranges: bytes
Content-Length: 7575
Connection: close
Content-Type: text/html; charset=UTF-8
Content-Language: en-gb
Refer to my post here for an explanation of why: CURLOPT_HEADER
(4) Lastly, when you build your app if you receive this error:
An unhandled exception of type 'System.AccessViolationException' occurred in libcurl.NET.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
This is caused by libcurl.net process not being cleaned up.
The "cleanup()" method isn't available in the DLL, despite being lsited in the examples.
So instead use EASY.Dispose() at the end of your procedure and this error will stop. (I kept the "GlobalCleanup()" method in just for good measure)
(5) Ironically I went the way of using CURL because I thought that the Confluence interface might require it.
But it appears now that it doesn't and that you can simply use the "HttpWebRequest" Class in .NET to get the same results.
However, the Jury is still out because the "lightweight" test server I was assigned to crashed and I'm waiting for them to fix it so I can verify this.
Either Way I hope all this helps someone
M

Any idea why I can't POST to this Django REST API?

I'm currently trying to get a POST request using multipart/form-data running to the Django REST framework. I've successfully run through some test requests via the interactive API screens, which work fine. I've then tried to convert these over to using a non-Session based auth strategy, and I've consistently got errors. The requests I've sent are of the form:
POST /api/logs/ HTTP/1.1
Host: host:8080
Connection: keep-alive
Content-Length: 258
Accept: application/json
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryTOhRsMbL8ak9EMQB
Authorization: Token -token-
------WebKitFormBoundaryx6ThtBDZxZNUCkKl
Content-Disposition: form-data; name="SubmittedAt"
2014-01-23T10:39:00
------WebKitFormBoundaryx6ThtBDZxZNUCkKl
Content-Disposition: form-data; name="Device"
CheeseDevice
------WebKitFormBoundaryx6ThtBDZxZNUCkKl--
Sadly, the result has been (for all the requests I've run):
{"Device": ["This field is required."], "SubmittedAt": ["This field is required."], "LogFile": ["This field is required."]}
Interestingly, I've been able to send chunks of JSON through to the endpoint, and they're accepted as expected, eg:
POST /api/logs/ HTTP/1.1
Content-Type: application/json
Host: host:8080
Connection: keep-alive
Content-Length: 35
Accept: application/json
Authorization: Token -token-
{
"Device": "CheeseDevice"
}
Returns:
{"SubmittedAt": ["This field is required."], "LogFile": ["This field is required."]}
As expected - it actually accepts the Device argument and only raises errors on the missing items. I'd switch to using JSON, but sadly cannot upload files with it...
Thanks in advance for any help!
Edit:
Further investigation (ie: writing a view method that returns the request data shows that request.DATA isn't getting populated, for some reason. Method I'm using to debug follows:
def test_create(self, request, pk=None):
return Response(request.DATA)
Edit 2:
Even further investigation (and dropping code chunks into the framework for debugging) indicates that the requests are getting caught up in _perform_form_overloading and never hitting the MultiPartParser. Not sure why this is occurring but I'll try and trace it further.
After delving down every level I could find...
Looks like the problem stems from the line endings - ie: the libs and request senders I've been using send the content through with "\n" (LF) endings, while the HTTP spec requires "\r\n" endings (CR,LF)
This hinges on the following code in the Django core, within http/multipartparser.py - in parse_boundary_stream:
header_end = chunk.find(b'\r\n\r\n')
For dev purposes (and because it's going to be way easier to patch at the Django end than in the clients...) I've switched the above line to:
header_end = chunk.replace("\r\n","\n").find(b'\n\n')
This updated code follows the recommendations in Section 19.3 of the HTTP/1.1 spec regarding Tolerant Applications and accepting LF instead of just CRLF - I'll try and get around to seeing if this is suitable for inclusion in the Django core.
Edit:
For reference, the patch is up on GitHub: https://github.com/tr00st/django/commit/9cf6075c113dd27e3743626ab0e18c6616488bd9
This could be due to malformed multipart post data.
Also possible that you don't have MultiPartParser installed, but I don't think that'll be it as you'd normally expect to see a 415 Unsupported Media Type response in that case.