Golang code to upload a file into personal box account - go

When I give this snippet of code in a golang program after recieving the access token:
f, err := ioutil.ReadFile("C:\\Users\\vembu\\Desktop\\hi.txt")
ioutil.WriteFile("hi.txt", f, 0x777)
r, _ := http.NewRequest("POST", urlStr, bytes.NewBuffer(f))
r.Header.Add("Authorization", "Bearer "+accessobj.Access_token)
r.Header.Add("attributes", "{\"name\":\"hi.txt\",\"parent\":{\"id\":\"3098791209\"}}")r.Header.Add("file", "hi.txt")
I get this error:
I face &{405 Method Not Allowed 405 HTTP/1.1 1 1 map[Allow:[GET, OPTIONS, HEAD] Content-Type:[text/html;charset=UTF-8] Content-Length:[0] Date:[Thu, 12 Mar 2015 13:07:32 GMT] Age:[0] Connection:[keep-alive] Server:[ATS]] 0xc08200b8c0 0 [] false map[] 0xc08201f2b0 0xc082060980}
Can anyone please help me to solve the method to add the attributes and the file name to upload into the box account?

urlStr should be https://upload.box.com/api/2.0/files/content
https://developers.box.com/docs/#files-upload-a-file
As they show in the docs, you may want to try out your queries using curl first:
curl https://upload.box.com/api/2.0/files/content \
-H "Authorization: Bearer ACCESS_TOKEN" -X POST \
-F attributes='{"name":"tigers.jpeg", "parent":{"id":"11446498"}}' \
-F file=#myfile.jpg

Related

Go send email gives error wsarecv: An existing connection was forcibly closed by the remote host

I have the below Go program which sends an email. The credentials are correct. I even tested them with curl and I see tha the connection is successsful. Please note that TLS is not required.
package main
import (
"fmt"
"log"
"net/smtp"
)
const (
USERNAME = "ryuken#email.com"
PASSWD = "password1111"
HOST = "mail.privateemail.com"
PORT = "465"
)
func main() {
from := "ryuken#email.com"
to := []string{
"info#email.com",
}
msg := []byte("From: ryuken#email.com\r\n" +
"To: info#email.com" +
"Subject: Golang testing mail\r\n" +
"Email Body: Welcome to Go!\r\n")
auth := smtp.PlainAuth("", USERNAME, PASSWD, HOST)
url := fmt.Sprintf(HOST + ":" + PORT)
fmt.Printf("url=[%s]\n", url)
err := smtp.SendMail(url, auth, from, to, msg)
if err != nil {
log.Fatal(err)
}
fmt.Println("Mail sent successfully!")
}
Could you please let me know why I get the below error?
read tcp 192.168.0.2:61740->198.54.122.135:465: wsarecv: An existing connection was forcibly closed by the remote host.
exit status 1
I tried using curl and I saw that it connects to the mail server but the the connection is closed.
c:\GoProjects\goemail
λ curl -v --url "smtp://mail.privateemail.com:465" --user "ryuken#email.com:password1111" --mail-from "ryuken#email.com" --mail-rcpt "info#email.com-" --upload-file sample.txt
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 198.54.122.135:465...
* Connected to mail.privateemail.com (198.54.122.135) port 465 (#0)
0 0 0 0 0 0 0 0 --:--:-- 0:00:09 --:--:-- 0* Recv failure: Connection was reset
0 0 0 0 0 0 0 0 --:--:-- 0:00:10 --:--:-- 0
* Closing connection 0
curl: (56) Recv failure: Connection was reset
I'm expecting an email to be sent.
Given the error Recv failure: Connection was reset I have a couple of things in mind which could potentially be your issue.
This response essentially says that the server returned an RST package back, which drops the connection immediately.
In other words this might be a TCP issue, or maybe a firewall misconfiguration from your end? Where is this app running and what kind of context/config is in place?
ps: you highlight that TLS is not required but you use port 465 which transmits messages via TLS. Is this intentional?
Many thanks for the responses. I switched to the implementation from https://gist.github.com/chrisgillis/10888032
and it is working fine. I still don't get what I was doing wrong. I was wrong about TLS - it is used and the go method also takes it into consideration.

Google SMTP server fails

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

How can I properly read the sequence of bytes from a hyper::client::Request and print it to the console as a UTF-8 string?

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.

lua os.execute doesn't work if the script runs from /etc/rc.local

I have this simple lua script that listens for a particular event and then fire a POST request to the twilio.com web service to start a call and then send a mail.
#!/usr/bin/lua
-- February 2015, Suxsem
local sock = require("socket")
local mosq = require("mosquitto")
local mqtt = mosq.new("sonny_lua_scattato", true)
mqtt:login_set("***", "***")
local call = function (from, to)
os.execute([[curl -X POST 'https://api.twilio.com/2010-04-01/Accounts/***/Calls.json' \
--data-urlencode 'To=]] .. to .. [[' \
--data-urlencode 'From=]] .. from .. [[' \
-d 'Url=https://demo.twilio.com/welcome/voice/' \
-d 'Method=GET' \
-d 'FallbackMethod=GET' \
-d 'StatusCallbackMethod=GET' \
-d 'Timeout=20' \
-d 'Record=false' \
-u ***:***> twiliolog.txt]])
end
local callback = function (mid, topic, message)
print("Received: " .. topic .. ": " .. message)
if topic == "ArseniAlarm/Scattato" then
local call_from = "+393317893***"
local call_to = {"+393299573***",
"+393473621***",
"+393492829***"}
for i, to in ipairs(call_to) do
call(call_from, to)
end
local rcpt = {"semer***.stef***#hotmail.it",
"miky.semer***#live.it"}
local sbj = "ANTIFURTO ARSENI"
local bdy = "ANTIFURTO ARSENI - " .. os.date("%T - %d/%m/%Y")
os.execute('echo -e "To: ' .. table.concat(rcpt, ",") .. '\r\nSubject: ' .. sbj .. '\r\n\r\n' .. bdy .. '" | msmtp --from=default -t')
end
end
mqtt:callback_set("ON_MESSAGE", callback)
local connected = false
mqtt:callback_set("ON_CONNECT", function ()
print("Connected")
connected = true
mqtt:subscribe("ArseniAlarm/Scattato", 2)
end)
mqtt:callback_set("ON_DISCONNECT", function ()
print("Disconnected")
connected = false
end)
mqtt:connect("127.0.0.1", 1883, 60)
while true do
mqtt:loop()
if connected then
sock.sleep(1.0) -- seconds
else
sock.sleep(5.0)
mqtt:reconnect()
end
end
Now... I run the script with the following command:
cd /root/mqtt_client/ ; lua /root/mqtt_client/mqtt_scattato.lua &
Everything works good, i receive tha call and the mail and in twiliolog.txt (if you look at the code I do "curl ... > twiliolog.txt" to start the call) I can see the twilio response.
BUT
If i put the same command (cd /root/mqtt_client/ ; lua /root/mqtt_client/mqtt_scattato.lua &) inside /etc/rc.local something strange happens:
1) i receive the mail but NOT the call!
2) twiliolog.txt (output of curl) is correctly created but it's empty!
My platform is a router with openwrt barrier breaker.
I really hope you can help me, thanks!
I ended up removing the os.execute call entirely.
I'm now using lua native https sockets:
local https = require("ssl.https")
local call = function (from, to)
local body = "To=" .. to .. "&From=" .. from .. "&Url=https://demo.twilio.com/welcome/voice/&Timeout=20&Record=false"
https.request {
protocol = "tlsv1",
method="POST",
url="https://api.twilio.com/2010-04-01/Accounts/***/Calls.json",
source=ltn12.source.string(body),
headers = {["content-length"] = #body, ["content-type"] = "application/x-www-form-urlencoded"},
user="***",
password="***",
}
end
I'm still using os.execute to send the mail and it works fine, so i think that the problem is related to the combination of curl + os.execute + start script on boot.
I have still no clue about what problem could cause this behaviour

Why the gmail API sends html emails as plain text?

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.

Resources