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