Documentation
¶
Overview ¶
Package maillist sends bulk e-mail to lists of addresses using the Sendgrid API.
All functionality is implemented as methods on a session object, which should be closed when finished with it.
The script 'init-db.sh' should be run to initialize the database for this package.
Usage ¶
Open a new session.
config := maillist.Config{
DatabaseAddress: "username:password@unix(/run/mysqld/mysqld.sock)/attendly_email_service"
JustPrint: true,
Logger: os.Stdout,
UnsubscribeURL: "https://localhost/unsubscribe",
SendGridUsername: "sendgrid@example.com"
SendGridPassword: "asdf1234"
SendGridAPIKey: "SG.0x145597e70x13313b210x49fd869f"
}
s, _ := maillist.OpenSession(&config)
defer s.Close()
Create or retrieve an Account.
a := maillist.Account{
FirstName: "Joe",
LastName: "Bloggs",
Email: "sendgrid@example.com",
}
s.InsertAccount(&a)
Create or retrive a List (which contains subscribers).
l := maillist.List{
AccountID: a.ID,
Name: "My Awesome Mailing List",
}
s.InsertList(&l)
Optionally add more subscribers to the list.
sub := maillist.Subscriber{
AccountID: a.ID,
FirstName: "Tommy",
LastName: "Barker",
Email: "tom@example.com",
}
s.InsertSubscriber(&sub)
s.AddSubscriberToList(l.ID, sub.ID)
Create and schedule a campaign for that list.
c := maillist.Campaign{
AccountID: a.ID,
Subject: "Awesome Event 2016",
Body: "Hi {{.FirstName}} {{.LastName}},\nThis is a test of attendly email list service",
Scheduled: time.Now().Unix(),
}
s.InsertCampaign(&c, []int64{l.ID}, nil)
This package will ensure the emails are sent out when the scheduled time is reached as long as at least one session remains open.
Example ¶
Example session of sending a single test email. Configuration here is read from the environment.
package main
import (
"os"
"time"
"github.com/Attendly/maillist"
_ "github.com/go-sql-driver/mysql"
)
func main() {
config := maillist.Config{
DatabaseAddress: os.Getenv("MAILLIST_DATABASE"),
JustPrint: true,
UnsubscribeURL: "https://myeventarc.localhost/unsubscribe",
SendGridUsername: os.Getenv("SENDGRID_USERNAME"),
SendGridPassword: os.Getenv("SENDGRID_PASSWORD"),
SendGridAPIKey: os.Getenv("SENDGRID_APIKEY"),
}
s, _ := maillist.OpenSession(&config)
defer s.Close()
a := maillist.Account{
ApplicationID: 0xdeadbeef,
FirstName: "Joe",
LastName: "Bloggs",
Email: "sendgrid@example.com",
}
s.InsertAccount(&a)
defer s.DeleteAccount(a.ID)
l := maillist.List{
AccountID: a.ID,
Name: "My Awesome Mailing List",
}
s.InsertList(&l)
sub := maillist.Subscriber{
AccountID: a.ID,
FirstName: "Tommy",
LastName: "Barker",
Email: "tom@example.com",
}
s.InsertSubscriber(&sub)
defer s.DeleteSubscriber(sub.ID)
s.AddSubscriberToList(l.ID, sub.ID)
c := maillist.Campaign{
AccountID: a.ID,
Subject: "Awesome Event 2016",
Body: "Hi {{.FirstName}} {{.LastName}},\nThis is a test of attendly email list service",
Address: "123 fake st",
Scheduled: time.Now().Unix(),
}
s.InsertCampaign(&c, []int64{l.ID}, nil)
time.Sleep(5 * time.Second)
}
Output: Email to send To: tom@example.com (Tommy Barker) From: sendgrid@example.com (Joe Bloggs) Subject: Awesome Event 2016 Body: Hi Tommy Barker, This is a test of attendly email list service
Index ¶
- Variables
- type Account
- type Campaign
- type Config
- type List
- type ListSubscriber
- type Logger
- type Message
- type Session
- func (s *Session) AddSubscriberToList(listID, subscriberID int64) error
- func (s *Session) CancelCampaign(campaignID int64) error
- func (c *Session) Close() error
- func (s *Session) DeleteAccount(accountID int64) error
- func (s *Session) DeleteList(listID int64) error
- func (s *Session) DeleteSubscriber(id int64) error
- func (s *Session) GetAccount(accountID int64) (*Account, error)
- func (s *Session) GetAccountByApplicationID(applicationID int64) (*Account, error)
- func (s *Session) GetAccountByEmail(email string) (*Account, error)
- func (s *Session) GetCampaign(campaignID int64) (*Campaign, error)
- func (s *Session) GetCampaignsInAccount(accountID int64) ([]*Campaign, error)
- func (s *Session) GetList(listID int64) (*List, error)
- func (s *Session) GetLists(accountID int64) ([]*List, error)
- func (s *Session) GetSubscriber(subscriberID int64) (*Subscriber, error)
- func (s *Session) GetSubscriberByEmail(email string, accountID int64) (*Subscriber, error)
- func (s *Session) GetSubscriberByToken(token string) (*Subscriber, error)
- func (s *Session) GetSubscribers(listID int64) ([]*Subscriber, error)
- func (s *Session) HasReportedSpam(email string) (bool, error)
- func (s *Session) InsertAccount(a *Account) error
- func (s *Session) InsertCampaign(c *Campaign, listIDs []int64, eventIDs []int64) error
- func (s *Session) InsertList(l *List) error
- func (s *Session) InsertMessage(m *Message) error
- func (s *Session) InsertSubscriber(sub *Subscriber) error
- func (s *Session) RemoveSubscriberFromList(listID, subscriberID int64) error
- func (s *Session) Unsubscribe(sub *Subscriber) error
- func (s *Session) UnsubscribeToken(sub *Subscriber) (string, error)
- func (s *Session) UpdateAccount(a *Account) error
- func (s *Session) UpdateList(l *List) error
- type Subscriber
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNotFound = &errNotFound{}
ErrNotFound returned when an entity is not present in the database
Functions ¶
This section is empty.
Types ¶
type Account ¶
type Account struct {
ID int64 `db:"id"`
ApplicationID int64 `db:"application_id" validate:"required"`
FirstName string `db:"first_name" validate:"required"`
LastName string `db:"last_name" validate:"required"`
Email string `db:"email" validate:"required"`
Status string `db:"status" validate:"eq=active|eq=deleted"`
CreateTime int64 `db:"create_time" validate:"required"`
}
Account is equivalent to a user. All lists, messages, and subscribers must have an associated account
type Campaign ¶
type Campaign struct {
ID int64 `db:"id"`
AccountID int64 `db:"account_id" validate:"required"`
Subject string `db:"subject" validate:"required"`
Body string `db:"body" validate:"required"`
Address string `db:"address" validate:"required"`
Status string `db:"status" validate:"eq=scheduled|eq=pending|eq=sent|eq=cancelled|eq=failed|eq=draft"`
ListIDs string `db:"list_ids" validate:"-"`
EventIDs string `db:"event_ids" validate:"-"`
Scheduled int64 `db:"scheduled" validate:"required"`
CreateTime int64 `db:"create_time" validate:"required"`
}
Campaign is a message template sent at a particular time to one or more mailing lists
type Config ¶
type Config struct {
DatabaseAddress string
JustPrint bool
Logger Logger
GetAttendeesCallback getAttendeeFunc
UnsubscribeURL string
SendGridAPIKey string
SendGridUsername string
SendGridPassword string
}
Config stores application defined options
type List ¶
type List struct {
ID int64 `db:"id"`
AccountID int64 `db:"account_id" validate:"required"`
Name string `db:"name" validate:"required"`
Status string `db:"status" validate:"eq=active|eq=deleted"`
CreateTime int64 `db:"create_time" validate:"required"`
}
List represents a user defined mailing list, these are seperate from event-associated lists
type ListSubscriber ¶
type ListSubscriber struct {
ListID int64 `db:"list_id" validate:"required"`
SubscriberID int64 `db:"subscriber_id" validate:"required"`
CreateTime int64 `db:"create_time" validate:"required"`
}
ListSubscriber represents a joining table for list and subscribers
type Logger ¶
type Logger interface {
Error(a ...interface{})
Info(a ...interface{})
}
Logger interface
type Message ¶
type Message struct {
SubscriberID int64 `db:"subscriber_id" validate:"required"`
CampaignID int64 `db:"campaign_id" validate:"required"`
Status string `db:"status" validate:"eq=pending|eq=sent|eq=failed|eq=cancelled"`
CreateTime int64 `db:"create_time" validate:"required"`
}
Message is a single email. It keeps track of whether the message has been sent or not.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is an opaque type holding database connections and other implementation details
func OpenSession ¶
OpenSession initialises a connection with the mailing list system. A call to Session.Close() should follow to ensure a clean exit.
func (*Session) AddSubscriberToList ¶
AddSubscriberToList adds a subscriber to a mailing list. Internally it is added to the list_subscriber joining table
func (*Session) CancelCampaign ¶
CancelCampaign will cancel the given campaign from sending
func (*Session) DeleteAccount ¶
DeleteAccount removes an account
func (*Session) DeleteList ¶
DeleteList removes a mailing list from the database (actually just marks it as `deleted` so we can a log of it)
func (*Session) DeleteSubscriber ¶
DeleteSubscriber from the db
func (*Session) GetAccount ¶
GetAccount retrieves an account with a given ID. Returns nil,nil if that ID does not exist (or has been deleted)
func (*Session) GetAccountByApplicationID ¶
GetAccountByApplicationID retrieves an account with a given application ID. Returns nil,nil if that ID does not exist (or has been deleted)
func (*Session) GetAccountByEmail ¶
GetAccountByEmail retrieves an account with a given email address. Returns nil,nil if that email address does not exist (or has been deleted)
func (*Session) GetCampaign ¶
GetCampaign retrieves a campaign with a given ID
func (*Session) GetCampaignsInAccount ¶
GetCampaignsInAccount returns the campaigns for the given account
func (*Session) GetSubscriber ¶
func (s *Session) GetSubscriber(subscriberID int64) (*Subscriber, error)
GetSubscriber retrieves a subscriber with a given ID. Returns nil,nil if no such subscriber exists
func (*Session) GetSubscriberByEmail ¶
func (s *Session) GetSubscriberByEmail(email string, accountID int64) (*Subscriber, error)
GetSubscriberByEmail retrieves a subscriber with a given email address. Returns nil,nil if no such subscriber exists
func (*Session) GetSubscriberByToken ¶
func (s *Session) GetSubscriberByToken(token string) (*Subscriber, error)
GetSubscriberByToken retrieves the subscriber associated with a token. Returns an error if the token doesn't match any in the database
func (*Session) GetSubscribers ¶
func (s *Session) GetSubscribers(listID int64) ([]*Subscriber, error)
GetSubscribers retrieves all the subscribers in a mailing list
func (*Session) HasReportedSpam ¶
HasReportedSpam checks whether an email address has made a spam report against us. Mail should not be sent to such an address.
func (*Session) InsertAccount ¶
InsertAccount adds the database to the account. The ID field will be updated. It is an error to have duplicate email addresses for the account table
func (*Session) InsertCampaign ¶
InsertCampaign adds the campaign to the scheduler to be sent to all its subscribers
func (*Session) InsertList ¶
InsertList adds a new mailing list to the database.
func (*Session) InsertMessage ¶
InsertMessage inserts a message into the database. It's ID field will be updated.
func (*Session) InsertSubscriber ¶
func (s *Session) InsertSubscriber(sub *Subscriber) error
InsertSubscriber into the db
func (*Session) RemoveSubscriberFromList ¶
RemoveSubscriberFromList removes a subscriber from a list. Note this is distinct from unsubscribing which is done on an account basis
func (*Session) Unsubscribe ¶
func (s *Session) Unsubscribe(sub *Subscriber) error
Unsubscribe marks a subscriber as not wanting to recieve any more marketting emails
func (*Session) UnsubscribeToken ¶
func (s *Session) UnsubscribeToken(sub *Subscriber) (string, error)
UnsubscribeToken gets a crypographically secure token which represents a subscriber. Using such a token means that only the recepiant of an email can unsubscribe from that mailing list.
func (*Session) UpdateAccount ¶
UpdateAccount updates an account (identified by it's ID)
func (*Session) UpdateList ¶
UpdateList updates a mailing list in the database, identified by it's ID
type Subscriber ¶
type Subscriber struct {
ID int64 `db:"id"`
AccountID int64 `db:"account_id" validate:"required"`
FirstName string `db:"first_name" validate:"required"`
LastName string `db:"last_name" validate:"required"`
Email string `db:"email" validate:"required,email"`
Status string `db:"status" validate:"eq=active|eq=deleted|eq=unsubscribed"`
CreateTime int64 `db:"create_time" validate:"required"`
}
Subscriber stores a single email address and some associated parameters. Each subscriber must have an associated account, and a given email address will have one subscriber for each account