I want to send a image in email body using go lang.
Used this package from github
https://github.com/scorredoira/email
err := m.Attach("image.png")
if err1 != nil {
fmt.Println(err1)
}
Now i am able to send image file as attachment but my need is to send a image file in email body.
Thanks in advance.
You can use Gomail (I'm the author). Have a look at the Embed method which allow you to embed images in the email body:
package main
import "gopkg.in/gomail.v2"
func main() {
m := gomail.NewMessage()
m.SetHeader("From", "from#example.com")
m.SetHeader("To", "to#example.com")
m.SetHeader("Subject", "Hello!")
m.Embed("image.png")
m.SetBody("text/html", `<img src="cid:image.png" alt="My image" />`)
d := gomail.NewPlainDialer("smtp.example.com", 587, "user", "123456")
if err := d.DialAndSend(m); err != nil {
panic(err)
}
}
Related
Chromedp have a chromedp.Submit() function which query a form exist in html page and submit it. Now what I need is post a request in pure golang code, there are have no form elements in html page, similar ajax post, this post should base in current context, include cookies, headers. Is it possible to do it this way in Chromedp? Thank you for any suggestions!
One of the options is to use chromedp.Evaluate() to execute a JavaScript snippet which in turn use fetch to send the post request. See the demo below:
package main
import (
"context"
"log"
"github.com/chromedp/cdproto/runtime"
"github.com/chromedp/chromedp"
)
func main() {
ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()
js := `
async function postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(data)
});
return response.text();
}; postData('/post', {answer: 69634319})
`
var response string
if err := chromedp.Run(ctx,
chromedp.Navigate("https://httpbin.org/cookies/set?name=test"),
chromedp.Evaluate(js, &response, func(ep *runtime.EvaluateParams) *runtime.EvaluateParams {
return ep.WithAwaitPromise(true)
}),
); err != nil {
log.Fatal(err)
}
log.Println(response)
}
If you are curious about the js expression, follow this link for more information: https://github.com/chromedp/chromedp/issues/1028#issuecomment-1061482792
I am trying to send emails from my golang application using my Mailjet credentials, but I am trying to do it the normal golang way (yes, I know that their library is highly encouraged).
I have the emails working fine using the Mailjet library, but my boss made a really good point that we might not stay with Mailjet forever. If we switch to a different email solution, we don't want to have to rewrite all of our email code, we just want to change our hostname and credentials.
My printer sends emails just find through Mailjet using the same hostname and credentials, but for some reason my golang app won't!
My code was adopted from the golang smtp library SendEmail example.
Here it is (without my credentials, of course):
import (
"bytes"
"fmt"
"net/smtp"
)
func SendTestEmail() (bool, error) {
fmt.Println("Send Test Email: Enter")
success := false
hostname := "in-v3.mailjet.com"
auth := smtp.PlainAuth("", username, password, hostname)
to := []string{"me#example.com"}
msg := []byte("To: me#example.com\r\n" +
"Subject: discount Gophers!\r\n" +
"\r\n" +
"This is the email body.\r\n")
fmt.Println("Send Test Email: Sending Email")
err := smtp.SendMail(hostname+":587", auth, "sender#example.com", to, msg)
if err == nil {
fmt.Println("Send Test Email: Email successfully sent!")
success = true
} else {
fmt.Println("Send Test Email: Email failed to send", err)
}
fmt.Println("Send Test Email: Exit")
return success, err
}
Note that I am using port 587. I do not know if my printer is using 587 or 25, but it's working. I don't work when using port 25 either.
What is really weird is that smtp.SendEmail isn't returning any errors, but I still do not get any emails (yes, I am checking my junk folder)!
Also, when I log into Mailjet, I don't see that any emails were sent. I do see that an email was sent when I send something from the printer.
So, where is my email?!
Any help is greatly appreciated. Thanks!
First of all, thanks for choosing Mailjet as your email service provider! I'm leading the API Product and Developers Relations at Mailjet.
When it comes to send, you're right with SMTP. It's standard, widely supported and easy to switch (even if I don't hope we'll get there!). Our Go library will become handy when it comes to deal with our API to manage business processes.
I have several questions / feedback looking at your code:
I guess the "sender#example.com" from address used is not the one you use in your real code? Anyway, this email must have been validated on Mailjet side beforehands. See our dedicated guide
Seems you try to set some SMTP headers like Subject within the message, when it should be handled separately
Here's a working code I'm using to work with SMTP:
package main
import (
"log"
"net/smtp"
"fmt"
)
func main() {
auth := smtp.PlainAuth(
"",
"MAILJET_API_KEY",
"MAILJET_API_SECRET",
"in-v3.mailjet.com",
)
email := "foobar#test.com"
header := make(map[string]string)
header["From"] = email
header["To"] = email
header["Subject"] = "Hello Mailjet World!"
header["X-Mailjet-Campaign"] = "test"
message := ""
for k, v := range header {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\nHi! Thanks for using Mailjet."
err := smtp.SendMail(
"in-v3.mailjet.com:587",
auth,
email,
[]string{email},
[]byte(message),
)
if err != nil {
log.Printf("Error: %s", err)
} else {
log.Printf("Mail sent!")
}
}
Hope it helps! hAPI sending with Mailjet
I have been using the mgo driver for a while, but now its my first time having to write a fully tested REST API with it.
Here it my goal
GET /users - Retrieves a list of users
GET /users/12 - Retrieves a specific users
POST /users - Creates a new user
PUT /users/12 - Updates user #12
PATCH /users/12 - Partially updates user #12
DELETE /users/12 - Deletes user #12
My problems arise from the PATCH/PUT method. Here its what I have so far
dao := daos.NewUserCollection(r)
userRequest, err := dao.GetUserRequest(r)
found, err := dao.GetByID(mux.Vars(r)["id"])
err = dao.Patch(mux.Vars(r)["id"],userRequest)
updated, err := dao.GetByID(mux.Vars(r)["id"])
log.Println("##################################################")
log.Println("URL PARAMETER", mux.Vars(r)["id"])
log.Println("USER FROM BODY",util.Marshall(userRequest))
log.Println("USER FROM DB",util.Marshall(found))
log.Println("UPDATED USER FROM DB",util.Marshall(updated))
log.Println("##################################################")
I am getting the user like
func (c *UserCollection) GetByID(id string) (models.User, error) {
result := models.User{}
err := c.FindId(bson.ObjectIdHex(id)).One(&result)
return result, err
}
I am doing the patching like
func (c *UserCollection) Patch(selector string, user models.User) ( error) {
err := c.UpdateId(bson.ObjectIdHex(selector),user)
return err
}
But the logs show me an unwanted behaviour
2016/09/28 14:10:57 ##################################################
2016/09/28 14:10:57 URL PARAMETER 57ebf9a1926bbc5bd0e666d9
2016/09/28 14:10:57 USER FROM BODY {"id":"57ebf9a1926bbc5bd0e666d9","username":"Snarlripple","email":"Slavefair#confirmed.com","password":"password","role":"","devices":["POWERDEVICE"],"confirmed":false,"notification":false}
2016/09/28 14:10:57 USER FROM DB {"id":"57ebf9a1926bbc5bd0e666d9","username":"Snarlripple","email":"Slavefair#confirmed.com","password":"$2a$04$gWErsTOWohjoJNON8l0O8OBQU0zHesFxS2vtgcqrOzcbwCEvxfUC.","role":"user","devices":[],"confirmed":true,"notification":false}
2016/09/28 14:10:57 UPDATED USER FROM DB {"id":"57ebf9a1926bbc5bd0e666d9","username":"Snarlripple","email":"Slavefair#confirmed.com","password":"password","role":"","devices":["POWERDEVICE"],"confirmed":false,"notification":false}
2016/09/28 14:10:57 ##################################################
The api is changing the password and the role of the user. I do not want my clients to be able to do this. I want to make it so there are just a few fields it has Whats the idiomatic way of doing this?
UPDATE
I got it to work with the below. Not sure if it the best way, but works.
func (c *UserCollection) Patch(id string, user User) error {
coolmap := structs.Map(&user)
setBSON := bson.M{}
for key, value := range coolmap{
if !contains([]string{"ID","Role", "Password", "Devices"},key) {
setBSON[strings.ToLower(key)] =value
}
}
changes := bson.M{"$set": setBSON }
err := c.UpdateId(bson.ObjectIdHex(id),changes)
return err
}
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
I'm running into trouble when using Google Cloud storage's resume-able upload for music and video files. Namely that certain properties are lost when uploaded and then downloaded back from the bucket.
Details: (original file on the left, downloaded file on the right)
General: (original file on the left, downloaded file on the right)
This isn't necessarily a problem for audio but it is for video as the browser now won't playback it in-browser.
The process for uploading is much the same as this question
A small code sample that does the intial resumeable upload:
func StoreUpload(c appengine.Context, cn context.Context, contentType string, filename string, email string, origin string) (string, string, error) {
uuid, err := UUID()
if err != nil{
return "", "", err
}
filename = uuid + filename[len(filename)-4:]
tokenSource := google.AppEngineTokenSource(cn, storage.ScopeFullControl)
token, err := tokenSource.Token()
if err != nil{
return "", "", err
}
metaBody := []byte("{ \"metadata\": { \"x-goog-meta-uploader\": \""+ email +"\" }}")
req, err := http.NewRequest(
"POST",
fmt.Sprintf("https://www.googleapis.com/upload/storage/v1/b/%s/o?uploadType=resumable&name=upload/%s", models.HYLIGHT_EXTERNAL_BUCKET, filename),
bytes.NewReader(metaBody),
)
req.Header.Set("Authorization", "Bearer " + token.AccessToken)
req.Header.Set("X-Upload-Content-Type", contentType)
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
req.Header.Set("Content-Length", fmt.Sprint(len(metaBody)))
req.Header.Set("Origin", origin)
client := &http.Client{
Transport: &urlfetch.Transport{
Context: c,
Deadline: 20 * time.Second,
},
}
res, err := client.Do(req)
if err != nil{
return "", "", err
}
return res.Header.Get("Location"), filename, err
}
The result in the google cloud bucket will have the correct mimetype of video/mp4 (that was decided by the browser) but still can't be viewed on the browser.
EDIT:
I've also tried using the chrome extension 'Postman' to upload a file after receiving an resumeable upload link but also its properties are lost when uploading to GCS, so it doesn't seem to be related to the JS side involved in uploading a file to GCS.
If I directly upload a folder with the video file in it using the 'upload folder' button on console.developer.google, the file's properties are retained.
It turns out that the file is being corrupted when submitted to Google Cloud Storage via an HTML "input" form from the browser. However, if the same URL is used to post the file via JavaScript, the file is not corrupted, which is very strange.
I am having the GCS team looking into the issue to see if there is a fix.
The full details, along with a workaround, are here:
https://code.google.com/p/googleappengine/issues/detail?id=12268
Thank you for working with me to get to the bottom of this!
I have found this library and have managed to send an attachment in an empty email but not to combine text and attachments.
https://github.com/sloonz/go-mime-message
How can it be done?
I ended up implementing it myself: https://github.com/scorredoira/email
Usage is very simple:
m := email.NewMessage("Hi", "this is the body")
m.From = "from#example.com"
m.To = []string{"to#example.com"}
err := m.Attach("picture.png")
if err != nil {
log.Println(err)
}
err = email.Send("smtp.gmail.com:587", smtp.PlainAuth("", "user", "password", "smtp.gmail.com"), m)
I created gomail for this purpose. It supports attachments as well as multipart emails and encoding of non-ASCII characters. It is well documented and tested.
Here is an example:
package main
func main() {
m := gomail.NewMessage()
m.SetHeader("From", "alex#example.com")
m.SetHeader("To", "bob#example.com", "cora#example.com")
m.SetAddressHeader("Cc", "dan#example.com", "Dan")
m.SetHeader("Subject", "Hello!")
m.SetBody("text/html", "Hello <b>Bob</b> and <i>Cora</i>!")
m.Attach("/home/Alex/lolcat.jpg")
d := gomail.NewPlainDialer("smtp.example.com", 587, "user", "123456")
// Send the email to Bob, Cora and Dan.
if err := d.DialAndSend(m); err != nil {
panic(err)
}
}
I prefer to use https://github.com/jordan-wright/email for email purposes.
It supports attachments.
Email for humans
The email package is designed to be simple to use, but flexible enough
so as not to be restrictive. The goal is to provide an email interface
for humans.
The email package currently supports the following:
From, To, Bcc, and Cc fields
Email addresses in both "test#example.com" and "First Last " format
Text and HTML Message Body
Attachments
Read Receipts
Custom headers
More to come!
Attachements in the SMTP protocol are sent using a Multipart MIME message.
So I suggest you simply
create a MultipartMessage
set your text in the fist part as a TextMessage (with "Content-Type", "text/plain")
add your attachements as parts using AddPart.