Attempting to Learn Go - Sending Email Via API Again
Tags: go, continuingeducation, atlg
Published: 2018-12-22 18:52:18

---
title: Attempting to Learn Go - Sending Email Via API Again
published: true
description: "Let's roll together our previous two posts and start sending some mail!"
tags: go, continuing-education, atlg
cover_image: https://shindakun.glitch.me/content/images/2018/01/attemptinggo.png
series: "Attempting to Learn Go"
---

# Mailing List

[Previously on ATLG](https://dev.to/shindakun/attempting-to-learn-go---rest-api-and-a-bit-on-templates-4kca), we looked at how we can use Go templates to quickly use marked-up text. This time around we're going to put those new formatting skills to good use! To do that we'll be pulling in the [`mailgunner` package](https://dev.to/shindakun/attempting-to-learn-go---now-sending-rest-requests-akp) we put together a few weeks ago. See I told you I had plans for it.

We're going to jump right in and start building on top of what we already have so, you may want to take a moment to [read the other](https://dev.to/shindakun/attempting-to-learn-go---now-sending-rest-requests-akp) [two posts](https://dev.to/shindakun/attempting-to-learn-go---rest-api-and-a-bit-on-templates-4kca) if you have not already.

***

Once again starting at the top! If you've been following the series so far you will no that for our examples we're starting off with the current set of imports. You may notice one new standard library this time around `errors`, we'll get to how we are using it in a moment. You may also note, that this time around we've trimmed out most of the unneeded struct parts and just left `[]Users` with the `name`, `username`, and `email` entries. As I said last time that was really only for demonstration purposes on that post, so I've left it out.

You may also notice that our import from the `mailgunner` package, which currently doesn't actually exist up on GitHub, is a little different. Having the leading `c` allows us to use the import as just that the letter "c" - so we can type out `c.SomeFunc()` instead of using `client`. *Note that the mailgunner code will be tweaked slightly and put up on GitHub after the next post.*

```go
package main

import (
  "bytes"
  "encoding/json"
  "errors"
  "fmt"
  "io/ioutil"
  "net/http"
  "text/template"

  "github.com/shindakun/envy"
  c "github.com/shindakun/mailgunner/client"
)

const apiurl = "https://api.mailgun.net/v3/youremaildomain.com"

type Users []struct {
  Name     string `json:"name"`
  Username string `json:"username"`
  Email    string `json:"email"`
}
```

Now we're down to our first real bit of new code. `checkStatusCode()` is a small utility (or helper) function which we're using to check to see if the `http` response code is `200` or not. The endpoints we're using should only ever respond to our code with a [`200 OK`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200) if not we're going to return an error. You might ask why we're returning an error and not just panicking here? That's because we want the code to panic and exit in the code block it's called from, this way you don't have to trace back. Later we'll also look into gracefully handling errors instead of just panicking. Anyway, it is a good idea to always check response codes - we skipped over it in the previous examples but, I'll try to remember doing it from here on out. Maybe we'll start putting together a "utilities" package for stuff that can be reused.

```go
func checkStatusCode(s int) error {
  if s != 200 {
    err := fmt.Sprintf("unexpected status code: %d", s)
    return errors.New(err)
  }
  return nil
}
```

`sendEmail()` is similar in some respects to the code we wrote to send our test message in the `mailgunner` post. This time, however, we're passing in our `bytes.Buffer` which will hold our completed email template, and the email address. Look closely and you may notice that I'm swapping the "from" and "to" fields in `mgc.FormatEmailRequest()` this is so I can actually send the emails, but send them to a working email - please don't try to email the example ones. They probably are all fake but still spamming isn't polite.

```go
func sendEmail(buf bytes.Buffer, email string) {
  mgKey, err := envy.Get("MGKEY")
  if err != nil {
    panic(err)
  }

  mgc := c.NewMgClient(apiurl, mgKey)

  req, err := mgc.FormatEmailRequest(email, "youremailaddress@",
    "Test email", buf.String())
  if err != nil {
    panic(err)
  }

  res, err := mgc.Client.Do(req)
  if err != nil {
    panic(err)
  }
  defer res.Body.Close()
```

Here we're using our helper to check the returned status code and panic if we're not looking good. Finally, as with every example so far, we're printing our results to standard out.

```go
  if err = checkStatusCode(res.StatusCode); err != nil {
    panic(err)
  }
  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    panic(err)
  }

  fmt.Println(string(body))
}
```

Alright, now lets dive into our `main()`! A lot of this will look familiar if you've read the previous posts. This iteration over the basics is what I'm hoping allows this to stick in my head, and maybe yours too!

```go
func main() {
  APIURL := "https://jsonplaceholder.typicode.com/users"
  req, err := http.NewRequest(http.MethodGet, APIURL, nil)
  if err != nil {
    panic(err)
  }
  client := http.DefaultClient
  resp, err := client.Do(req)
  if err != nil {
    panic(err)
  }
  defer resp.Body.Close()

  if err = checkStatusCode(resp.StatusCode); err != nil {
    panic(err)
  }
  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    panic(err)
  }

  var u Users
  json.Unmarshal(body, &u)
```

Our message is pretty bland, with a full-featured mailing list app you'd make it easy to load custom messages, etc. But, as always, we're just trying stuff out to learn. If we iterate on this enough it could easily become a full app one day. We'll `range` through our users and pass the results of the populated template to `sendEmail()` which will do the actual sending.

```go
  msgText := "Hi {{.Name}}! Or should I call you, {{.Username}}? There is a new post!\n\n"
  t := template.Must(template.New("msg").Parse(msgText))

  for _, v := range u {
    var buf bytes.Buffer

    err := t.Execute(&buf, v)
    if err != nil {
      panic(err)
    }
    sendEmail(buf, v.Email)
  }
}
```

And that's it! Next time around we are going to tweak our `mailgunner` package a little bit and get it posted up on GitHub so we can actually `go get` it!

***

You can find the code for this and most of the other Attempting to Learn Go posts in the repo on GitHub.

{% github shindakun/atlg %}

***

| Enjoy this post? |
|:----:|
| [How about buying me a coffee?](https://ko-fi.com/shindakun) |

***