Skip to content

Instantly share code, notes, and snippets.

@immannino
Last active February 26, 2023 09:05
Show Gist options
  • Save immannino/d02bdb4cc7118cbe6778a1e1df356979 to your computer and use it in GitHub Desktop.
Save immannino/d02bdb4cc7118cbe6778a1e1df356979 to your computer and use it in GitHub Desktop.
// a small exmaple cli application for sending emails
//
// Expects a .env with the following configuration:
//
// EMAIL_ADDRESS=<from address>
// EMAIL_PASSWORD=<app password>
// EMAIL_HOST=smtp.gmail.com
// EMAIL_PORT=587
// RECIPIENT=<optional>
// SITEMAP=<optional>
package main
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/smtp"
"os"
"github.com/disgoorg/log"
"github.com/joho/godotenv"
"github.com/jordan-wright/email"
"github.com/spf13/cobra"
"github.com/yterajima/go-sitemap"
)
var (
sitemapUrl = ""
recipient = ""
rootCmd = &cobra.Command{
Use: "email",
Short: "send an email with go",
Run: sendSitemap,
}
)
func main() {
err := godotenv.Load(".env")
if err != nil {
log.Fatal(err)
}
rootCmd.Flags().StringVarP(&sitemapUrl, "sitemap", "s", "", "The sitemap to crawl")
rootCmd.Flags().StringVarP(&recipient, "recipient", "r", "", "The email recipient")
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func sendSitemap(cmd *cobra.Command, args []string) {
if sitemapUrl == "" {
sitemapUrl = os.Getenv("SITEMAP")
}
if sitemapUrl == "" {
log.Fatalf("no sitemap provided, exiting.")
}
if recipient == "" {
recipient = os.Getenv("RECIPIENT")
}
if recipient == "" {
log.Fatalf("no email recipient provided.\n%s", cmd.Usage())
}
sm, err := fetchSitemap(sitemapUrl)
if err != nil {
log.Fatal(err)
}
for _, v := range sm.URL {
err = sendEmail(v.Loc)
if err != nil {
log.Errorf("error sending email for url %s - %v", v.Loc, err)
}
}
}
func sendEmail(url string) error {
contents, err := fetchHTML(url)
if err != nil {
return err
}
tmp, err := ioutil.TempFile("./", "attachment.*.html")
if err != nil {
return err
}
_, err = tmp.Write([]byte(contents))
if err != nil {
log.Fatal(err)
}
defer tmp.Close()
defer os.RemoveAll(tmp.Name())
if err := sendWithAttachment(recipient, url+".html", contents, tmp.Name()); err != nil {
return err
}
log.Infof("successfully sent %s to %s", url, recipient)
return nil
}
func sendWithAttachment(to, subject, body, attachmentFile string) error {
e := email.NewEmail()
e.From = fmt.Sprintf("<%s>", os.Getenv("EMAIL_ADDRESS"))
e.To = []string{os.Getenv("RECIPIENT")}
e.Subject = subject
e.HTML = []byte(body)
_, err := e.AttachFile(attachmentFile)
if err != nil {
return err
}
return e.Send(fmt.Sprintf("%s:%s", os.Getenv("EMAIL_HOST"), os.Getenv("EMAIL_PORT")), smtp.PlainAuth("", os.Getenv("EMAIL_ADDRESS"), os.Getenv("EMAIL_PASSWORD"), os.Getenv("EMAIL_HOST")))
}
func fetchHTML(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", err
}
if resp.StatusCode > http.StatusUnsupportedMediaType {
return "", errors.New("non successful response from server")
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
func fetchSitemap(url string) (*sitemap.Sitemap, error) {
sm, err := sitemap.Get(url, nil)
if err != nil {
return nil, err
}
return &sm, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment