Hermes is an open-source E-Mail tracking solution that is written in Go. It tracks emails using a tracking pixel.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.4 KiB

4 years ago
4 years ago
4 years ago
  1. package controllers
  2. import (
  3. "bytes"
  4. "crypto/sha256"
  5. "fmt"
  6. "github.com/revel/revel"
  7. "image"
  8. "image/jpeg"
  9. "io/ioutil"
  10. "net/http"
  11. "net/url"
  12. "os"
  13. "strconv"
  14. "strings"
  15. )
  16. var pix = image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{1, 1}})
  17. var img image.Image = pix
  18. var buffer = new(bytes.Buffer)
  19. var foo = jpeg.Encode(buffer, img, nil)
  20. var content_length = strconv.Itoa(len(buffer.Bytes()))
  21. type Pixel string
  22. func (p Pixel) Apply(req *revel.Request, resp *revel.Response) {
  23. resp.Out.Header().Add("Content-Type", "image/jpeg")
  24. resp.Out.Header().Add("Content-Length", content_length)
  25. resp.GetWriter().Write(buffer.Bytes())
  26. }
  27. type Hermes struct {
  28. *revel.Controller
  29. }
  30. func (c Hermes) Index() revel.Result {
  31. return c.Render()
  32. }
  33. func send_notification(title, recipient, token string) {
  34. http.PostForm("https://gotify.yigitcolakoglu.com/message?token="+token,
  35. url.Values{"title": {"E-mail Seen"}, "message": {fmt.Sprintf("To: %s \n Title: %s", recipient, title)}, "priority": {"5"}})
  36. }
  37. func (h Hermes) Read(title, recipient, user, provided_hash string) revel.Result {
  38. ip := strings.Split(h.Request.RemoteAddr, ":")[0]
  39. raw_userdata, _ := ioutil.ReadFile("storage/userdata")
  40. userdata := strings.Split(string(raw_userdata), "\n")
  41. key := ""
  42. gotify_token := ""
  43. for i := 0; i < len(userdata); i++ {
  44. if strings.Split(userdata[i], " ")[0] == user {
  45. key = strings.Split(userdata[i], " ")[1]
  46. gotify_token = strings.Split(userdata[i], " ")[2]
  47. }
  48. }
  49. if key == "" {
  50. return Pixel("No dice")
  51. }
  52. identity := title + recipient + user + key
  53. fmt.Printf(identity)
  54. hash_string := fmt.Sprintf("%x", sha256.Sum256([]byte(identity)))
  55. if hash_string != provided_hash {
  56. fmt.Printf("Hashes don't match!\n")
  57. return Pixel("You think you can fool me?")
  58. }
  59. if _, err := os.Stat("storage/ipdata/" + hash_string); os.IsNotExist(err) {
  60. os.Create("storage/ipdata/" + hash_string)
  61. }
  62. raw_ipdata, _ := ioutil.ReadFile("storage/ipdata/" + hash_string)
  63. ipdata := strings.Split(string(raw_ipdata), "\n")
  64. for i := 0; i < len(ipdata)-1; i++ {
  65. if ipdata[i] == ip {
  66. fmt.Printf("IP collision detected!\n")
  67. return Pixel("I see what you are trying to do!")
  68. }
  69. }
  70. f, _ := os.OpenFile("storage/ipdata/"+hash_string, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
  71. f.WriteString(fmt.Sprintf("%s\n", ip))
  72. f.Close()
  73. send_notification(title, recipient, gotify_token)
  74. return Pixel("Success")
  75. }