I'm trying to send a html email using the gmail API but for some reasons it randomly sends the email as plain/text. It seems that Google alters the content type header I set. Is there any reason for that? The email content is exactly same all the time (as I test it). Is the API still experimental?
Sometimes when it works it also adds Content-Type: multipart/alternative; (although I never set it).
The encoding process looks as below. The code is Go but I guess it self explanatory and the process is language agnostic.
header := make(map[string]string)
header["From"] = em.From.String()
header["To"] = em.To.String()
// header["Subject"] = encodeRFC2047(em.Subject)
header["Subject"] = em.Subject
header["MIME-Version"] = "1.0"
header["Content-Type"] = "text/html; charset=\"utf-8\""
// header["Content-Transfer-Encoding"] = "base64"
header["Content-Transfer-Encoding"] = "quoted-printable"
var msg string
for k, v := range header {
msg += fmt.Sprintf("%s: %s\r\n", k, v)
}
msg += "\r\n" + em.Message
gmsg := gmail.Message{
Raw: encodeWeb64String([]byte(msg)),
}
_, err = gmailService.Users.Messages.Send("me", &gmsg).Do()
Hmm, are you sure it's not a bug in your program? Can you print out the entire string and paste it here?
I just used the Gmail API to send an email like:
To: <redacted>
Subject: test html email 2015-01-14 09:45:40
Content-type: text/html
<html><body><b>hello</b>world</body></html>
and it looked as expected by the recipient's end in Gmail. Well, actually looks like it got wrapped it in a multipart/alternative and added a text/plain part as well (good thing IMO):
<random trace headers>
MIME-Version: 1.0
From: <redacted>
Date: Wed, 14 Jan 2015 09:46:41 -0800
Message-ID:
Subject: test html email 2015-01-14 09:45:40
To: <redacted>
Content-Type: multipart/alternative; boundary=089e0141a9a2875c38050ca05201
--089e0141a9a2875c38050ca05201
Content-Type: text/plain; charset=UTF-8
*hello*world
--089e0141a9a2875c38050ca05201
Content-Type: text/html; charset=UTF-8
<html><body><b>hello</b>world</body></html>
--089e0141a9a2875c38050ca05201--
In any case, it's doing some parsing/sanitizing but does allow sending text/html email.
Related
I get the following error when attempting to use Google's SMTP server.
535 5.7.8 Username and Password not accepted. Learn more at 5.7.8 https://support.google.com/mail/?p=BadCredentials fa15sm2375541pjb.40 - gsmtp
This is my code:
// Sender data.
from := req.FormValue("email")
//password := "xxxx" //<- log in password fails
password := "xxxx" // <- app password fails
// Receiver email address.
to := []string{
"myemail#gmail.com",
}
// smtp server configuration.
smtpHost := "smtp.gmail.com"
smtpPort := "587"
msg := req.FormValue("name") + "\n" + req.FormValue("message")
message := []byte(msg)
auth := smtp.PlainAuth("", from, password, smtpHost)
err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, to, message)
if err != nil {
tmp.Message = "Message not sent: " + err.Error()
htmlTags["contact"] = tmp
err = tmpl.ExecuteTemplate(w, "send_failure", htmlTags["contact"])
} else {
tmp.Message = "Message sent"
htmlTags["contact"] = tmp
err = tmpl.ExecuteTemplate(w, "send_success", htmlTags["contact"])
}
} else {
tmp.Message = "You message has not been sent. Cookies are required to send messages."
htmlTags["contact"] = tmp
err = tmpl.ExecuteTemplate(w, "send_failure", htmlTags["contact"])
}
The account has 2FA enabled and app password is used.
Allow less secure apps: ON
The sending code also lives on a server with a self signing cert giving the following error:
Certificate - missing
This site is missing a valid, trusted certificate (net::ERR_CERT_AUTHORITY_INVALID).
Provided your username and password is correct, these are the steps to get Gmail working from any client.
# Visit https://accounts.google.com
#
# 1. Click on [Security] menu
# 2. Scroll to section [Less secure app access] and set it to ON
# 3. Scroll to section [Signing in to Google] and set [Use your phone to sign in] to OFF
# 4. Scroll to section [Signing in to Google] and set [2-step Verification] to OFF
Now a simple text/plain email example to send:
To: "Jane Doe" <jane#gmail.com>
From: "John Doe" <john#gmail.com>
Subject: A text/plain email
MIME-Version: 1.0 (Created with SublimeText 3)
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
Good morning.
This is a message in text/plain format.
It contains text/plain.
It contains no base64 inline images or attachments.
Each line is no more than 76 characters in length.
Please reach out if you have any questions.
Thank you,
John Doe
SENIOR DEVELOPER
XYZ Solutions Inc.
P | 999.555.1234
Then, you can use CURL to send it:
# GMAIL TEST - text-plain.eml
curl --verbose -ssl smtps://smtp.gmail.com:465 --login-options AUTH=PLAIN --user john#gmail.com:passwword123 --mail-from john#gmail.com --mail-rcpt jane#gmail.com --mail-rcpt-allowfails --upload-file text-plain.eml
I am writing a websocket server in C++ and am not able to get the handshake to work. Chrome reports the error is due to a bad accept header, but I believe the value to be correct.
As one example exchange, the client sends the following key:
Sec-WebSocket-Key: ypX0m2zum/pt80mxlVo8PA==
and my server sends back:
Sec-WebSocket-Accept: Kl4mnqm5QA6bBmGf3EAN0nyGXws=
I have tested my server against the example in the RFC and it checks out. I don't know why its not being accepted. My theory is that I must be doing something else that generates the same error as a bad accept value.
Here is different request from a wireshark capture:
Hypertext Transfer Protocol
GET /websocket HTTP/1.1\r\n
Host: 127.0.0.1:8443\r\n
Connection: Upgrade\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36\r\n
Upgrade: websocket\r\n
Origin: chrome-extension://eajaahbjpnhghjcdaclbkeamlkepinbl\r\n
Sec-WebSocket-Version: 13\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: en-US,en;q=0.9\r\n
Sec-WebSocket-Key: +zJ3/KI/Zrumgh+AjxopRQ==\r\n
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n
\r\n
[Full request URI: http://127.0.0.1:8443/websocket]
[HTTP request 1/1]
[Response in frame: 6]
And here is the response:
Hypertext Transfer Protocol
HTTP/1.1 101 Switching Protocols\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Accept: anTEIFyI/gTepr8Q3okBj81M2/4=\r\n
\r\n
[HTTP response 1/1]
[Time since request: 0.000245010 seconds]
[Request in frame: 4]
Can someone tell me what is wrong with the response? Is my accept value incorrect?
EDIT 1:
The code I use to create the response value. The websocket_key is grabbed from the request prior to this.
const char *magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
int pre_hash_size = 36 + websocket_key.size();
char pre_hash[pre_hash_size];
memcpy(pre_hash, websocket_key.c_str(), websocket_key.size());
memcpy(pre_hash + websocket_key.size(), magic_string, 36);
unique_ptr<Botan::HashFunction> hash1(Botan::HashFunction::create("SHA-1"));
Botan::secure_vector<uint8_t> post_hash = hash1->process(reinterpret_cast<const uint8_t *>(pre_hash), pre_hash_size);
string accept_response = base64_encode(post_hash.data(), post_hash.size());
Here is the base 64 function:
/*
base64.cpp and base64.h
base64 encoding and decoding with C++.
Version: 1.01.00
Copyright (C) 2004-2017 René Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
René Nyffenegger rene.nyffenegger#adp-gmbh.ch
*/
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
std::string base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len)
{
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--)
{
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3)
{
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while ((i++ < 3))
ret += '=';
}
return ret;
}
The problem was that when I concatenated the pre_hash string from the websocket key (sent by client) and the magic string (constant), I didn't account for the null terminator that the size() function includes in it's count. an extra space I had inadvertently added when parsing the request header.
Remember kiddies, C++ strings are null terminated and size() reflects that.
I use Embarcadero C++Builder 10.2 Tokyo with Indy 10.
The task is to check emails via POP3. I can get emails, but I don't know how to decode their subjects, attachment file name, etc from koi8-r to windows-1251 or UTF-8.
Can anybody help me?
The code is:
int nMess = pop3->CheckMessages();
if (nMess == 0) return;
for (int i = 1; i <= nMess; i++) {
pop3->UIDL(sl,i); // check for UID
UnicodeString sUID = sl->Strings[0]; // get one of them
if (isLetterYetRead(sUID,_idBox)) continue;
// if new, read it
pop3->Retrieve(i,IdMessage1);
int mSize = pop3->RetrieveMsgSize(i);
// parsing
for (int j = 0; j < IdMessage1->MessageParts->Count; j++) {
TIdMessagePart *mp = IdMessage1->MessageParts->Items[j];
// attacnets later
if (mp->PartType() == mptAttachment) continue;
TIdText *pt = (TIdText*) mp;
if (pt->ContentType == "text/plain" )
plain = pt->Body->Text;
else if (pt->ContentType == "text/html" ) {
html = pt->Body->Text;
// ??? bool g = NeedConvertToUnicode(IdMessage1->,pt->);
}
}
}
How to decode non-english fields?
The email is:
` Return-path: <babichev#meccanosoft.com>
Envelope-to: ear#meccanosoft.com
Delivery-date: Thu, 12 Jul 2018 14:00:33 +0300
Received: from [213.79.95.226] (helo=pccomerc)
by server120.hosting.reg.ru with esmtpa (Exim 4.90_1)
(envelope-from <babichev#meccanosoft.com>)
id 1fdZKr-0002FS-1c
for ear#meccanosoft.com; Thu, 12 Jul 2018 14:00:33 +0300
From: =?KOI8-R?B?4sHCyd7F1yDzxdLHxco=?= <babichev#meccanosoft.com>
To: ear#meccanosoft.com
Subject: test8
Date: Thu, 12 Jul 2018 14:00:29 +0300
Message-Id: <006901d419cf$8e2aeed0$aa80cc70$#meccanosoft.com>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="UMwhv1yjwbAJnDKFK8wyCH0CYSe2=_553g"
X-Mailer: Microsoft Outlook 16.0
Thread-Index: AdQZz4RBq8MEckA1Rq6W+ide2hSKlw==
Content-Language: ru
In-Reply-To: <006901d419cf$8e2aeed0$aa80cc70$#meccanosoft.com>
This is a multipart message in MIME format.
--UMwhv1yjwbAJnDKFK8wyCH0CYSe2=_553g
Content-Type: multipart/alternative;
boundary="jEgWjeMCC35bF=_m8mr8EoHknZfRtWVKzB"
--jEgWjeMCC35bF=_m8mr8EoHknZfRtWVKzB
Content-Type: text/plain; charset="koi8-r"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
TEST8
--jEgWjeMCC35bF=_m8mr8EoHknZfRtWVKzB
Content-Type: text/html; charset="koi8-r"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas=
-microsoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:off=
ice:word" xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml"=
xmlns=3D"http://www.w3.org/TR/REC-html40"><head><meta http-equiv=3DCo=
ntent-Type content=3D"text/html; charset=3Dkoi8-r"><meta name=3DGenera=
tor content=3D"Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
#font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
#font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;
mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri",sans-serif;
color:windowtext;}
=2EMsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri",sans-serif;
mso-fareast-language:EN-US;}
#page WordSection1
{size:612.0pt 792.0pt;
margin:2.0cm 42.5pt 2.0cm 3.0cm;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]--></head><body lang=3DRU link=3D"#0563=
C1" vlink=3D"#954F72"><div class=3DWordSection1><p class=3DMsoNormal><=
span lang=3DEN-US>TEST8<o:p></o:p></span></p></div></body></html>
--jEgWjeMCC35bF=_m8mr8EoHknZfRtWVKzB--
--UMwhv1yjwbAJnDKFK8wyCH0CYSe2=_553g
Content-Type: text/plain;
name="=?KOI8-R?B?0M/e1MExLnR4dA==?="
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="=?KOI8-R?B?0M/e1MExLnR4dA==?="
................................................
--UMwhv1yjwbAJnDKFK8wyCH0CYSe2=_553g--
`
Result of receiving is:
List of letters after receiving
Code is:
` TIdPOP3 *pop3 = new TIdPOP3 ();
TIdMessage *IdMessage1 = new TIdMessage();
pop3->Host = qPop3->FieldByName("pop3server")->AsString;
pop3->Port = qPop3->FieldByName("pop3port")->AsInteger;
pop3->Username = qPop3->FieldByName("pop3login")->AsString;
pop3->Password = password;
pop3->Connect();
int nMess = pop3->CheckMessages();
if (nMess == 0) return;
for (int i = 1; i <= nMess; i++) {
pop3->UIDL(sl,i); // ask for UID
UnicodeString sUID = sl->Strings[0];
pop3->Retrieve(i,IdMessage1);
int mSize = pop3->RetrieveMsgSize(i);
UnicodeString s = L"c:\\Temp\\"+sUID+".eml";
IdMessage1->SaveToFile(s,false);
// Parsing
for (int j = 0; j < IdMessage1->MessageParts->Count; j++) {
TIdMessagePart *mp = IdMessage1->MessageParts->Items[j];
// -------- and etc -------------
}
}
`
Sure I do something wrong, but what?
I am exploring Rust and trying to make a simple HTTP request (using the hyper crate) and print the response body to the console. The response implements std::io::Read. Reading various documentation sources and basic tutorials, I have arrived at the following code, which I compile & execute using RUST_BACKTRACE=1 cargo run:
use hyper::client::Client;
use std::io::Read;
pub fn print_html(url: &str) {
let client = Client::new();
let req = client.get(url).send();
match req {
Ok(mut res) => {
println!("{}", res.status);
let mut body = String::new();
match res.read_to_string(&mut body) {
Ok(body) => println!("{:?}", body),
Err(why) => panic!("String conversion failure: {:?}", why)
}
},
Err(why) => panic!("{:?}", why)
}
}
Expected:
A nice, human-readable HTML content of the body, as delivered by the HTTP server, is printed to the console.
Actual:
200 OK
thread '<main>' panicked at 'String conversion failure: Error { repr: Custom(Custom { kind: InvalidData, error: StringError("stream did not contain valid UTF-8") }) }', src/printer.rs:16
stack backtrace:
1: 0x109e1faeb - std::sys::backtrace::tracing::imp::write::h3800f45f421043b8
2: 0x109e21565 - std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h0ef6c8db532f55dc
3: 0x109e2119e - std::panicking::default_hook::hf3839060ccbb8764
4: 0x109e177f7 - std::panicking::rust_panic_with_hook::h5dd7da6bb3d06020
5: 0x109e21b26 - std::panicking::begin_panic::h9bf160aee246b9f6
6: 0x109e18248 - std::panicking::begin_panic_fmt::haf08a9a70a097ee1
7: 0x109d54378 - libplayground::printer::print_html::hff00c339aa28fde4
8: 0x109d53d76 - playground::main::h0b7387c23270ba52
9: 0x109e20d8d - std::panicking::try::call::hbbf4746cba890ca7
10: 0x109e23fcb - __rust_try
11: 0x109e23f65 - __rust_maybe_catch_panic
12: 0x109e20bb1 - std::rt::lang_start::hbcefdc316c2fbd45
13: 0x109d53da9 - main
error: Process didn't exit successfully: `target/debug/playground` (exit code: 101)
Thoughts
Since I received 200 OK from the server, I believe I have received a valid response from the server (I can also empirically prove this by doing the same request in a more familiar programming language). Therefore, the error must be caused by me incorrectly converting the byte sequence into an UTF-8 string.
Alternatives
I also attempted the following solution, which gets me to a point where I can print the bytes to the console as a series of hex strings, but I know that this is fundamentally wrong because a UTF-8 character can have 1-4 bytes. Therefore, attempting to convert individual bytes into UTF-8 characters in this example will work only for a very limited (255, to be exact) subset of UTF-8 characters.
use hyper::client::Client;
use std::io::Read;
pub fn print_html(url: &str) {
let client = Client::new();
let req = client.get(url).send();
match req {
Ok(res) => {
println!("{}", res.status);
for byte in res.bytes() {
print!("{:x}", byte.unwrap());
}
},
Err(why) => panic!("{:?}", why)
}
}
We can confirm with the iconv command that the data returned from http://www.google.com is not valid UTF-8:
$ wget http://google.com -O page.html
$ iconv -f utf-8 page.html > /dev/null
iconv: illegal input sequence at position 5591
For some other urls (like http://www.reddit.com) the code works fine.
If we assume that the most part of the data is valid UTF-8, we can use String::from_utf8_lossy to workaround the problem:
pub fn print_html(url: &str) {
let client = Client::new();
let req = client.get(url).send();
match req {
Ok(mut res) => {
println!("{}", res.status);
let mut body = Vec::new();
match res.read_to_end(&mut body) {
Ok(_) => println!("{:?}", String::from_utf8_lossy(&*body)),
Err(why) => panic!("String conversion failure: {:?}", why),
}
}
Err(why) => panic!("{:?}", why),
}
}
Note that that Read::read_to_string and Read::read_to_end return Ok with the number of read bytes on success, not the read data.
If you actually look at the headers that Google returns:
HTTP/1.1 200 OK
Date: Fri, 22 Jul 2016 20:45:54 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
P3P: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."
Server: gws
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Set-Cookie: NID=82=YwAD4Rj09u6gUA8OtQH73BUz6UlNdeRc9Z_iGjyaDqFdRGMdslypu1zsSDWQ4xRJFyEn9-UtR7U6G7HKehoyxvy9HItnDlg8iLsxzlhNcg01luW3_-HWs3l9S3dmHIVh; expires=Sat, 21-Jan-2017 20:45:54 GMT; path=/; domain=.google.ca; HttpOnly
Alternate-Protocol: 443:quic
Alt-Svc: quic=":443"; ma=2592000; v="36,35,34,33,32,31,30,29,28,27,26,25"
Accept-Ranges: none
Vary: Accept-Encoding
Transfer-Encoding: chunked
You can see
Content-Type: text/html; charset=ISO-8859-1
Additionally
Therefore, the error must be caused by me incorrectly converting the byte sequence into an UTF-8 string.
There is no conversion to UTF-8 happening. read_to_string simply ensures that the data is UTF-8.
Simply put, assuming that an arbitrary HTML page is encoded in UTF-8 is completely incorrect. At best, you have to parse the headers to find the encoding and then convert the data. This is complicated because there's no real definition for what encoding the headers are in.
Once you have found the correct encoding, you can use a crate such as encoding to properly transform the result into UTF-8, if the result is even text! Remember that HTTP can return binary files such as images.
I am interacting with an API that sometimes will return a reference number for certain functions. How would i go about displaying this reference number. At present the API returns for example this string (some code taken out for security reasons).
if (AppSettings.GetLandingPageReceipts())
{
long returnValue = loanLP.AddWithdrawalToBankID(CustomerID, SavingsAccountID, BankAccID, Amount);
return string.Concat("Requested Withdrawal Ref No: ", returnValue);
}
ReceiptWithdrawal withdraw = new ReceiptWithdrawal(CustomerID, SavingsAccountID, Amount, session, pp, BankAccID);
ReceiptTRN TRN = new ReceiptTRN();
TRN.Post(withdraw);
return JsonConvert.SerializeObject(withdraw.ReceiptNo);
In the Ruby code I use this for Post calls
def post_call(routePath, params)
started_at = Time.now
logger.bench 'SERVICE - POST', started_at, routePath
uri = URI.parse("#{settings.abacus_service_endpoint}#{routePath}")
http = Net::HTTP.new(uri.host, uri.port)
http.set_debug_output $stderr
req = Net::HTTP::Post.new(uri.request_uri,get_header_for_abacus_service)
req.form_data = params
resp = http.request(req)
if response_ok?(resp)
if #errors
puts '======= post request form_data ======='
puts params
puts '==================='
end
return resp
end
end
I can see the following in my console when working locally so I know its being passed. Its just accessing it is the problem.
opening connection to 10.10.10.27...
opened
<- "POST /Accounts/WithdrawalToBank HTTP/1.1\r\nAuthorization: Token 433\r\nX-Customer-Id: 433\r\nX-Customer-Pin: 8EFD155E7C829421E16F14D367568C4179C4548320CD7E1B6AD6E9A485F2AF092FA42D0F645085F3DBBA5AEC2434720FC76E407E41443C3F5EDAFB958793254A\r\nX-Ip-Address: 10.0.2.2\r\nAccept: */*\r\nUser-Agent: Ruby\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection: close\r\nHost: 10.10.10.27:3579\r\nContent-Length: 81\r\n\r\n"
<- "CustomerID=433&SavingsAccountID=10922&BankAccountID=2450&Amount=10.00&Reference=a"
-> "HTTP/1.1 200 OK\r\n"
-> "Transfer-Encoding: chunked\r\n"
-> "Content-Type: text/html\r\n"
-> "Server: Microsoft-HTTPAPI/2.0\r\n"
-> "Date: Mon, 23 Nov 2015 11:03:02 GMT\r\n"
-> "Connection: close\r\n"
-> "\r\n"
-> "22\r\n"
reading 34 bytes...
-> "Requested Withdrawal Ref No: 10059"
read 34 bytes
reading 2 bytes...
-> "\r\n"
read 2 bytes
-> "0\r\n"
-> "\r\n"
Conn close
If any further information is needed please let me know.
If the API is returning a body you should be able to get this from your response with resp.body