Initial bulk mailer work
This commit is contained in:
parent
8e94f9feb1
commit
9aa4357fdf
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright 2015 ISRG. All rights reserved
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/codegangsta/cli"
|
||||
"gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
"github.com/letsencrypt/boulder/sa"
|
||||
)
|
||||
|
||||
type mailer struct {
|
||||
stats statsd.Statter
|
||||
log *blog.AuditLogger
|
||||
dbMap *gorp.DbMap
|
||||
}
|
||||
|
||||
func (m *mailer) findExpiringCertificates(warningDays []int) error {
|
||||
var err error
|
||||
for _, expiresIn := range warningDays {
|
||||
left := time.Now().Add(time.Hour * 24 * time.Duration(expiresIn))
|
||||
right := left.Add(time.Hour * 24)
|
||||
|
||||
var certs []core.Certificate
|
||||
_, err := m.dbMap.Select(
|
||||
&certs,
|
||||
`SELECT cert.* FROM certificates AS certs JOIN certificateStatus AS cs on cs.serial = cert.serial
|
||||
WHERE cert.expires > :cutoff-a AND cert.Expires < :cutoff-b AND cs.status != "revoked"
|
||||
ORDER BY cert.Issued ASC`,
|
||||
map[string]interface{}{
|
||||
"cutoff-a": left,
|
||||
"cutoff-b": right,
|
||||
},
|
||||
)
|
||||
if err == sql.ErrNoRows {
|
||||
m.log.Info("All up to date. No expiration emails needed.")
|
||||
} else if err != nil {
|
||||
m.log.Err(fmt.Sprintf("Error loading certificates: %s", err))
|
||||
} else {
|
||||
// Do things...
|
||||
// cert expires in expiresIn, send email to registration contacts
|
||||
for _, cert := range certs {
|
||||
reg, err := m.dbMap.Get(&core.Registration{}, cert.RegistrationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.sendWarning(cert, reg, expiresIn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *mailer) sendWarning(cert core.Certificate, reg core.Registration, expiresIn int) {
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := cmd.NewAppShell("expiration-mailer")
|
||||
|
||||
app.App.Flags = append(app.App.Flags, cli.IntFlag{
|
||||
Name: "limit",
|
||||
Value: emailLimit,
|
||||
EnvVar: "EMAIL_LIMIT",
|
||||
Usage: "Maximum number of emails to send per run",
|
||||
})
|
||||
|
||||
app.Config = func(c *cli.Context, config cmd.Config) cmd.Config {
|
||||
config.Mailer.Limit = c.GlobalInt("emailLimit")
|
||||
return config
|
||||
}
|
||||
|
||||
app.Action = func(c cmd.Config) {
|
||||
auditlogger.Info(app.VersionString())
|
||||
|
||||
// Set up logging
|
||||
stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix)
|
||||
cmd.FailOnError(err, "Couldn't connect to statsd")
|
||||
|
||||
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
|
||||
cmd.FailOnError(err, "Could not connect to Syslog")
|
||||
|
||||
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
|
||||
defer auditlogger.AuditPanic()
|
||||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.Mailer.DebugAddr)
|
||||
|
||||
// Configure DB
|
||||
dbMap, err := sa.NewDbMap(c.Mailer.DBDriver, c.Mailer.DBConnect)
|
||||
cmd.FailOnError(err, "Could not connect to database")
|
||||
|
||||
err = findExpiringCertificates()
|
||||
if err != nil {
|
||||
auditlogger.WarningErr(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ func (src *DBSource) Response(req *ocsp.Request) (response []byte, present bool)
|
|||
log.Debug(fmt.Sprintf("Searching for OCSP issued by us for serial %s", serialString))
|
||||
|
||||
var ocspResponse core.OCSPResponse
|
||||
err := src.dbMap.SelectOne(&ocspResponse, "SELECT * from ocspResponses WHERE serial = :serial ORDER BY createdAt DESC LIMIT 1;",
|
||||
err := src.dbMap.SelectOne(&ocspResponse, "SELECT * from ocspResponses WHERE serial = :serial ORDER BY createdAt DESC LIMIT 1;",
|
||||
map[string]interface{}{"serial": serialString})
|
||||
if err != nil {
|
||||
present = false
|
||||
|
|
|
|||
|
|
@ -132,6 +132,12 @@ type Config struct {
|
|||
Port string
|
||||
Username string
|
||||
Password string
|
||||
|
||||
MessageLimit int
|
||||
ExpiryWarnings []int
|
||||
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
OCSPResponder struct {
|
||||
|
|
@ -267,7 +273,7 @@ func AmqpChannel(conf Config) (*amqp.Channel, error) {
|
|||
if conf.AMQP.TLS.CertFile != nil || conf.AMQP.TLS.KeyFile != nil {
|
||||
// But they have to give both.
|
||||
if conf.AMQP.TLS.CertFile == nil || conf.AMQP.TLS.KeyFile == nil {
|
||||
err = fmt.Errorf("AMQPS: You must set both of the configuration values AMQP.TLS.KeyFile and AMQP.TLS.CertFile.")
|
||||
err = fmt.Errorf("AMQPS: You must set both of the configuration values AMQP.TLS.KeyFile and AMQP.TLS.CertFile")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue