Worked out the docs for the email sending feature.

master
Zed A. Shaw 2 weeks ago
parent 6872956478
commit c84b29037d
  1. 97
      README.md
  2. 4
      common/email/api.go
  3. 1
      common/email/data.go
  4. 8
      emails/signup.md
  5. 2
      features/init.go
  6. 9
      tools/cmd/qmgr/main.go

@ -474,14 +474,94 @@ When you start with the UI can you can prototype all of the interactions, figure
aim for only what you need. Keep doing this and you'll slowly build a nice data model with less
cruft for the application you're creating.
## Additional Features
### Sending Emails
## Sending Emails
Coming soon...
> __WARNING__: The email sending feature is currently very simple. Don't think you can send 200
> million spam messages with it.
The email system uses a [Redis]() queue to schedule messages, and an email router to actually
deliver them. The idea is that you don't want to wait for email crafting and delivery in your web
application most of the time. Ideally what you want to do is:
1. In an `api.go` you receive a form or action from the user that needs an email. Say a password
reset.
2. You use the `common/email` module to craft a simple message and send it to the queue. Your
message at this stage is usually a very simple `struct` with the information your email router
needs to build the email.
3. In your `api.go` file _immediately return rather than wait for email delivery._
4. Your email router then sits there and processes the email requests. When a new message comes in
it takes the data, queries your database, configures the templates, and finally sends it to the
email server.
Since email is asynchronous there's no point in your web application waiting around for all of #4 to
be done. Just toss out a message on a queue and move on.
### Running the `mailer`
There's a simple router implemented in `tools/cmd/mailer` that you can run to get going. You can
use this to send simple emails but you should probably write a new one that handles your more
sophisticated emails like password resets and receipts.
You can run it from the command line with:
```shell
./bin/mailer
```
It will require that you install `redis` for it to work.
### Testing Your Email Locally
Running an email server locally is kind of a pain, and setting up everything so you can view sent
emails is even harder. That's way the awesome and fabulous [MailHog](https://github.com/mailhog/MailHog) exists.
You can install it easily (it's written in Go) and then run it:
```shell
MailHog
```
By default it opens an SMTP port on `1025` and a web server at 127.0.0.1:8025. If you point your
browser at 127.0.0.:8025 you'll get a fake email inbox. This inbox will show you both the HTML and
TEXT versions of your email, plus other useful things.
### How To Send
### Receiving Payments
Here's an example of sending an email from a form submission in `features/email/api.go`.
```go
package features_email
import (
email "MY/webapp/common/email"
"github.com/gofiber/fiber/v2"
)
func PostApiEmailSend(c *fiber.Ctx) error {
go email.OneShotSend(email.EmailMessage{
To: c.FormValue("To"),
From: c.FormValue("From"),
Subject: c.FormValue("Subject"),
Template: c.FormValue("Template"),
})
return c.Redirect("/email/")
}
func SetupApi(app *fiber.App) {
app.Post("/api/email/send", PostApiEmailSend)
}
```
### Email Templates
The templates use the same default `text/template` engine that the rest of the system uses, but you
should use Markdown to write them. This automatically gives you both a nice text format (Markdown
already is like an email) and an HTML output. Look at `emails/signup.md` for a simple example.
## Receiving Payments
Coming soon...
@ -489,6 +569,15 @@ Coming soon...
Here's some questions I get when people see this.
### What if My Email Templates Need HTML?
You should be able to work with the code in `common/email` to make it do what you want. I don't
think it's specifically looking for any extension, but I haven't tested it. Try just dropping the
`.html` you want into the `emails/` directory and sending it.
You should also know that really complex HTML usually get filtered, so it's best to keep it simple
HTML and Markdown will help you stick to that.
### Isn't Fiber Banned?!
First off, nobody has the right to "ban" a project. If you're hanging out in the Go discord and

@ -98,7 +98,7 @@ func (router *Router) DeliverEmail(msg EmailMessage) error {
}
log.Println("template is", msg.Template)
text, html, err := router.Render(msg.Template, nil)
text, html, err := router.Render(msg.Template, msg)
if err != nil { return err }
email_msg.SetBodyString(mail.TypeTextHTML, html)
@ -150,6 +150,8 @@ func (sender *Sender) QueueEmail(msg EmailMessage) error {
return nil
}
// Intended to be fired off on a goroutine and
// forgotten about.
func OneShotSend(msg EmailMessage) {
ctx := context.Background()

@ -24,6 +24,5 @@ type Router struct {
redis_client *redis.Client
smtp_client *mail.Client
ctx context.Context
}

@ -1,4 +1,10 @@
Welcome
=======
Welcome to my website!
Welcome to my website! Here's what you sent:
* {{ .From }}
* {{ .To }}
* {{ .Data.Name }}
* {{ .Data.Pet }}

@ -6,7 +6,6 @@ import (
"MY/webapp/features/paypal"
"MY/webapp/features/shopping"
"MY/webapp/features/fakepay"
"MY/webapp/features/myfeature"
)
func Setup(app *fiber.App) {
@ -14,5 +13,4 @@ func Setup(app *fiber.App) {
features_paypal.Setup(app)
features_shopping.Setup(app)
features_fakepay.Setup(app)
features_myfeature.Setup(app)
}

@ -7,6 +7,11 @@ import (
"fmt"
)
type Person struct {
Name string
Pet string
}
func main() {
config.Load("config.json")
@ -17,6 +22,10 @@ func main() {
From: "toni.sender@example.com",
Subject: "This is my first mail.",
Template: "signup.md",
Data: Person{
Name: "Zed",
Pet: "None",
},
}
fmt.Println("sending", msg)

Loading…
Cancel
Save