7 Sending an Email
Finally, let us set up GMail to email us the Reddit News using our redditnews package.
First, we will create an Email() function in redditnews.go, that we can call within our main() function to include the formatted Articles list inside the Email HTML body:
func Email() string {
var buffer bytes.Buffer
items, err := Get("golang")
if err != nil {
log.Fatal(err)
}
// Need to build strings from items
for _, item := range items {
buffer.WriteString(item.String())
}
return buffer.String()
}
What we’re doing here is using the:
-
logpackage, and - inbuilt bytes package to build strings from our items which we can then call from the Body section of our scheduled Email. Let’s revisit the
main()function, and actually build the email we are going to send.
The modified redditnews.go (remember to add the following imports bytes and log) file is:
Program redditnews.go
package redditnews
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
)
type Item struct {
Author string `json:"author"`
Score int `json:"score"`
URL string `json:"url"`
Title string `json:"title"`
}
type response struct {
Data1 struct {
Children []struct {
Data2 Item `json:"data"`
} `json:"children"`
} `json:"data"`
}
func Get(reddit string) ([]Item, error) {
url := fmt.Sprintf("http://reddit.com/r/%s.json", reddit)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, errors.New(resp.Status)
}
r := new(response)
err = json.NewDecoder(resp.Body).Decode(r)
if err != nil {
return nil, err
}
items := make([]Item, len(r.Data1.Children))
for i, child := range r.Data1.Children {
items[i] = child.Data2
}
return items, nil
}
func (i Item) String() string {
return fmt.Sprintf(
"Author: %s\nScore: %d\nURL: %s\nTitle: %s\n\n",
i.Author,
i.Score,
i.URL,
i.Title)
}
func Email() string {
var buffer bytes.Buffer
items, err := Get("golang")
if err != nil {
log.Fatal(err)
}
// Need to build strings from items
for _, item := range items {
buffer.WriteString(item.String())
}
return buffer.String()
}
You can download this code here.
Create a new folder inside your redditnews folder named redditmail. Here create a file redditmail.go as:
Program redditmail.go
package main
import (
"github.com/SatishTalim/redditnews"
"log"
"net/smtp"
)
func main() {
to := "satish@joshsoftware.com"
subject := "Go articles on Reddit"
message := redditnews.Email()
body := "To: " + to + "\r\nSubject: " +
subject + "\r\n\r\n" + message
auth := smtp.PlainAuth("", "satish.talim", "password", "smtp.gmail.com")
err := smtp.SendMail(
"smtp.gmail.com:587",
auth,
"satish.talim@gmail.com",
[]string{to},
[]byte(body))
if err != nil {
log.Fatal("SendMail: ", err)
return
}
}
You can download this code here.
- Sign up for a free Gmail account, if you don’t have one already.
- We use net/smtp package to connect to GMail.
- Call smtp.PlainAuth with your gmail username, password and domain name, and it returns you back an instance of smtp.Auth that you can use to send e-mails.
- If you have setup the 2-Step Verification process in Gmail, then you need to set an application-specific password. Use this password in the above program.
- You can send mail with smtp.SendMail.
- SMTP on port 587 uses TLS. SSL and TLS both provide a way to encrypt a communication channel between two computers (e.g. your computer and a server). TLS is the successor to SSL and the terms SSL and TLS are used interchangeably unless youre referring to a specific version of the protocol.
Run the program and you’ll get an email with the details. If interested, you could setup a cron job to send you an email at 6 am everyday as follows:
0 6 * * * cd folder_containing_redditmail_executable && ./redditmail
We are telling our Cron Job to run at 0 minutes past the 6th hour (6am) every day here. The Cron Job is changing into the directory in which our executable file is located, then simply running the program.