git » chasquid » commit 50986a7

Update protobuf library to v2

author Alberto Bertogli
2020-05-16 09:12:51 UTC
committer Alberto Bertogli
2020-05-16 09:12:51 UTC
parent 5ec567b27e55c521baff853b67092bcb5d15b5ba

Update protobuf library to v2

There is a new protobuf library (and corresponding code generator) for
Go: google.golang.org/protobuf.

It is fairly compatible with the previous v1 API
(github.com/golang/protobuf), but there are some changes.

This patch adjusts the code and generated files to the new API.

The on-wire/on-disk format remains unchanged so this should be
transparent to the users.

cmd/chasquid-util/chasquid-util.go +2 -2
cmd/chasquid-util/test.sh +1 -1
go.mod +2 -1
go.sum +19 -2
internal/config/config.go +3 -3
internal/config/config.pb.go +202 -111
internal/config/config.proto +1 -0
internal/domaininfo/domaininfo.go +1 -1
internal/domaininfo/domaininfo.pb.go +181 -76
internal/domaininfo/domaininfo.proto +1 -0
internal/protoio/testpb/dummy.go +1 -1
internal/protoio/testpb/testpb.pb.go +121 -47
internal/protoio/testpb/testpb.proto +1 -0
internal/queue/queue.go +16 -9
internal/queue/queue.pb.go +300 -146
internal/queue/queue.proto +1 -0
internal/userdb/userdb.go +1 -1
internal/userdb/userdb.pb.go +330 -187
internal/userdb/userdb.proto +1 -0

diff --git a/cmd/chasquid-util/chasquid-util.go b/cmd/chasquid-util/chasquid-util.go
index e664b12..e01c50d 100644
--- a/cmd/chasquid-util/chasquid-util.go
+++ b/cmd/chasquid-util/chasquid-util.go
@@ -20,9 +20,9 @@ import (
 	"blitiri.com.ar/go/chasquid/internal/envelope"
 	"blitiri.com.ar/go/chasquid/internal/normalize"
 	"blitiri.com.ar/go/chasquid/internal/userdb"
+	"google.golang.org/protobuf/encoding/prototext"
 
 	"github.com/docopt/docopt-go"
-	"github.com/golang/protobuf/proto"
 	"golang.org/x/crypto/ssh/terminal"
 )
 
@@ -253,7 +253,7 @@ func printConfig() {
 		Fatalf("Error reading config")
 	}
 
-	fmt.Println(proto.MarshalTextString(conf))
+	fmt.Println(prototext.Format(conf))
 }
 
 // chasquid-util domaininfo-remove <domain>
diff --git a/cmd/chasquid-util/test.sh b/cmd/chasquid-util/test.sh
index dc0e2c1..c549b51 100755
--- a/cmd/chasquid-util/test.sh
+++ b/cmd/chasquid-util/test.sh
@@ -74,7 +74,7 @@ if [ "$A" != "(email)  user@somewhere" ]; then
 fi
 
 C=$(r print-config | grep hostname)
-if [ "$C" != "hostname: \"$HOSTNAME\"" ]; then
+if ! ( echo "$C" | grep -E -q "hostname:.*\"$HOSTNAME\"" ); then
 	echo print-config failed
 	echo output: "$C"
 	exit 1
diff --git a/go.mod b/go.mod
index 8637f42..f3ec22e 100644
--- a/go.mod
+++ b/go.mod
@@ -7,9 +7,10 @@ require (
 	blitiri.com.ar/go/spf v0.0.0-20191018194539-a683815bdae8
 	blitiri.com.ar/go/systemd v0.0.0-20171003041308-cdc4fd023aa4
 	github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
-	github.com/golang/protobuf v1.3.5
+	github.com/golang/protobuf v1.4.0
 	golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59
 	golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
 	golang.org/x/text v0.3.2
+	google.golang.org/protobuf v1.23.0
 	gopkg.in/yaml.v2 v2.2.4 // indirect
 )
diff --git a/go.sum b/go.sum
index e483bbf..106ebad 100644
--- a/go.sum
+++ b/go.sum
@@ -6,8 +6,16 @@ blitiri.com.ar/go/systemd v0.0.0-20171003041308-cdc4fd023aa4 h1:ceTBe2TiHNkhA7q/
 blitiri.com.ar/go/systemd v0.0.0-20171003041308-cdc4fd023aa4/go.mod h1:FmDkVlYnOzDHOhtSwtLHh6z9WVVx+aPjrHkPtfA3qhI=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
-github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -24,6 +32,15 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
diff --git a/internal/config/config.go b/internal/config/config.go
index a8e46ce..2b72786 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -2,7 +2,7 @@
 package config
 
 // Generate the config protobuf.
-//go:generate protoc --go_out=. config.proto
+//go:generate protoc --go_out=. --go_opt=paths=source_relative config.proto
 
 import (
 	"io/ioutil"
@@ -10,7 +10,7 @@ import (
 
 	"blitiri.com.ar/go/log"
 
-	"github.com/golang/protobuf/proto"
+	"google.golang.org/protobuf/encoding/prototext"
 )
 
 // Load the config from the given file.
@@ -24,7 +24,7 @@ func Load(path string) (*Config, error) {
 		return nil, err
 	}
 
-	err = proto.UnmarshalText(string(buf), c)
+	err = prototext.Unmarshal(buf, c)
 	if err != nil {
 		log.Errorf("Error parsing config: %v", err)
 		return nil, err
diff --git a/internal/config/config.pb.go b/internal/config/config.pb.go
index beef41d..ffa704d 100644
--- a/internal/config/config.pb.go
+++ b/internal/config/config.pb.go
@@ -1,26 +1,35 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.23.0
+// 	protoc        v3.11.4
 // source: config.proto
 
 package config
 
 import (
-	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
 
 type Config struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
 	// Default hostname to use when saying hello.
 	// This is used:
 	// 1) To say hello to clients, for aesthetic purposes.
@@ -97,174 +106,256 @@ type Config struct {
 	// Dovecot client path. If dovecot_auth is set and this
 	// is not, we will try to autodetect it.
 	// Example: /var/run/dovecot/auth-client
-	DovecotClientPath    string   `protobuf:"bytes,15,opt,name=dovecot_client_path,json=dovecotClientPath,proto3" json:"dovecot_client_path,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
+	DovecotClientPath string `protobuf:"bytes,15,opt,name=dovecot_client_path,json=dovecotClientPath,proto3" json:"dovecot_client_path,omitempty"`
 }
 
-func (m *Config) Reset()         { *m = Config{} }
-func (m *Config) String() string { return proto.CompactTextString(m) }
-func (*Config) ProtoMessage()    {}
-func (*Config) Descriptor() ([]byte, []int) {
-	return fileDescriptor_3eaf2c85e69e9ea4, []int{0}
+func (x *Config) Reset() {
+	*x = Config{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_config_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *Config) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Config.Unmarshal(m, b)
-}
-func (m *Config) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Config.Marshal(b, m, deterministic)
-}
-func (m *Config) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Config.Merge(m, src)
+func (x *Config) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Config) XXX_Size() int {
-	return xxx_messageInfo_Config.Size(m)
-}
-func (m *Config) XXX_DiscardUnknown() {
-	xxx_messageInfo_Config.DiscardUnknown(m)
+
+func (*Config) ProtoMessage() {}
+
+func (x *Config) ProtoReflect() protoreflect.Message {
+	mi := &file_config_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Config proto.InternalMessageInfo
+// Deprecated: Use Config.ProtoReflect.Descriptor instead.
+func (*Config) Descriptor() ([]byte, []int) {
+	return file_config_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *Config) GetHostname() string {
-	if m != nil {
-		return m.Hostname
+func (x *Config) GetHostname() string {
+	if x != nil {
+		return x.Hostname
 	}
 	return ""
 }
 
-func (m *Config) GetMaxDataSizeMb() int64 {
-	if m != nil {
-		return m.MaxDataSizeMb
+func (x *Config) GetMaxDataSizeMb() int64 {
+	if x != nil {
+		return x.MaxDataSizeMb
 	}
 	return 0
 }
 
-func (m *Config) GetSmtpAddress() []string {
-	if m != nil {
-		return m.SmtpAddress
+func (x *Config) GetSmtpAddress() []string {
+	if x != nil {
+		return x.SmtpAddress
 	}
 	return nil
 }
 
-func (m *Config) GetSubmissionAddress() []string {
-	if m != nil {
-		return m.SubmissionAddress
+func (x *Config) GetSubmissionAddress() []string {
+	if x != nil {
+		return x.SubmissionAddress
 	}
 	return nil
 }
 
-func (m *Config) GetSubmissionOverTlsAddress() []string {
-	if m != nil {
-		return m.SubmissionOverTlsAddress
+func (x *Config) GetSubmissionOverTlsAddress() []string {
+	if x != nil {
+		return x.SubmissionOverTlsAddress
 	}
 	return nil
 }
 
-func (m *Config) GetMonitoringAddress() string {
-	if m != nil {
-		return m.MonitoringAddress
+func (x *Config) GetMonitoringAddress() string {
+	if x != nil {
+		return x.MonitoringAddress
 	}
 	return ""
 }
 
-func (m *Config) GetMailDeliveryAgentBin() string {
-	if m != nil {
-		return m.MailDeliveryAgentBin
+func (x *Config) GetMailDeliveryAgentBin() string {
+	if x != nil {
+		return x.MailDeliveryAgentBin
 	}
 	return ""
 }
 
-func (m *Config) GetMailDeliveryAgentArgs() []string {
-	if m != nil {
-		return m.MailDeliveryAgentArgs
+func (x *Config) GetMailDeliveryAgentArgs() []string {
+	if x != nil {
+		return x.MailDeliveryAgentArgs
 	}
 	return nil
 }
 
-func (m *Config) GetDataDir() string {
-	if m != nil {
-		return m.DataDir
+func (x *Config) GetDataDir() string {
+	if x != nil {
+		return x.DataDir
 	}
 	return ""
 }
 
-func (m *Config) GetSuffixSeparators() string {
-	if m != nil {
-		return m.SuffixSeparators
+func (x *Config) GetSuffixSeparators() string {
+	if x != nil {
+		return x.SuffixSeparators
 	}
 	return ""
 }
 
-func (m *Config) GetDropCharacters() string {
-	if m != nil {
-		return m.DropCharacters
+func (x *Config) GetDropCharacters() string {
+	if x != nil {
+		return x.DropCharacters
 	}
 	return ""
 }
 
-func (m *Config) GetMailLogPath() string {
-	if m != nil {
-		return m.MailLogPath
+func (x *Config) GetMailLogPath() string {
+	if x != nil {
+		return x.MailLogPath
 	}
 	return ""
 }
 
-func (m *Config) GetDovecotAuth() bool {
-	if m != nil {
-		return m.DovecotAuth
+func (x *Config) GetDovecotAuth() bool {
+	if x != nil {
+		return x.DovecotAuth
 	}
 	return false
 }
 
-func (m *Config) GetDovecotUserdbPath() string {
-	if m != nil {
-		return m.DovecotUserdbPath
+func (x *Config) GetDovecotUserdbPath() string {
+	if x != nil {
+		return x.DovecotUserdbPath
 	}
 	return ""
 }
 
-func (m *Config) GetDovecotClientPath() string {
-	if m != nil {
-		return m.DovecotClientPath
+func (x *Config) GetDovecotClientPath() string {
+	if x != nil {
+		return x.DovecotClientPath
 	}
 	return ""
 }
 
-func init() {
-	proto.RegisterType((*Config)(nil), "Config")
+var File_config_proto protoreflect.FileDescriptor
+
+var file_config_proto_rawDesc = []byte{
+	0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95,
+	0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73,
+	0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73,
+	0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x74,
+	0x61, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6d, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+	0x0d, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x74, 0x61, 0x53, 0x69, 0x7a, 0x65, 0x4d, 0x62, 0x12, 0x21,
+	0x0a, 0x0c, 0x73, 0x6d, 0x74, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03,
+	0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6d, 0x74, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+	0x73, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x73,
+	0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+	0x12, 0x3d, 0x0a, 0x1b, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6f,
+	0x76, 0x65, 0x72, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18,
+	0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
+	0x6e, 0x4f, 0x76, 0x65, 0x72, 0x54, 0x6c, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12,
+	0x2d, 0x0a, 0x12, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x64,
+	0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6d, 0x6f, 0x6e,
+	0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x35,
+	0x0a, 0x17, 0x6d, 0x61, 0x69, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x5f,
+	0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x14, 0x6d, 0x61, 0x69, 0x6c, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x41, 0x67, 0x65,
+	0x6e, 0x74, 0x42, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x18, 0x6d, 0x61, 0x69, 0x6c, 0x5f, 0x64, 0x65,
+	0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x67,
+	0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x6d, 0x61, 0x69, 0x6c, 0x44, 0x65, 0x6c,
+	0x69, 0x76, 0x65, 0x72, 0x79, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x19,
+	0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x07, 0x64, 0x61, 0x74, 0x61, 0x44, 0x69, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x73, 0x75, 0x66,
+	0x66, 0x69, 0x78, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x0a,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x53, 0x65, 0x70, 0x61,
+	0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x63,
+	0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0e, 0x64, 0x72, 0x6f, 0x70, 0x43, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x12,
+	0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x69, 0x6c, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68,
+	0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x69, 0x6c, 0x4c, 0x6f, 0x67, 0x50,
+	0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x76, 0x65, 0x63, 0x6f, 0x74, 0x5f, 0x61,
+	0x75, 0x74, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x64, 0x6f, 0x76, 0x65, 0x63,
+	0x6f, 0x74, 0x41, 0x75, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x6f, 0x76, 0x65, 0x63, 0x6f,
+	0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0e, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x6f, 0x76, 0x65, 0x63, 0x6f, 0x74, 0x55, 0x73, 0x65, 0x72,
+	0x64, 0x62, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x6f, 0x76, 0x65, 0x63, 0x6f,
+	0x74, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0f, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x6f, 0x76, 0x65, 0x63, 0x6f, 0x74, 0x43, 0x6c, 0x69, 0x65,
+	0x6e, 0x74, 0x50, 0x61, 0x74, 0x68, 0x42, 0x2c, 0x5a, 0x2a, 0x62, 0x6c, 0x69, 0x74, 0x69, 0x72,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x2f, 0x67, 0x6f, 0x2f, 0x63, 0x68, 0x61, 0x73,
+	0x71, 0x75, 0x69, 0x64, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_config_proto_rawDescOnce sync.Once
+	file_config_proto_rawDescData = file_config_proto_rawDesc
+)
+
+func file_config_proto_rawDescGZIP() []byte {
+	file_config_proto_rawDescOnce.Do(func() {
+		file_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_config_proto_rawDescData)
+	})
+	return file_config_proto_rawDescData
 }
 
-func init() { proto.RegisterFile("config.proto", fileDescriptor_3eaf2c85e69e9ea4) }
-
-var fileDescriptor_3eaf2c85e69e9ea4 = []byte{
-	// 409 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0x41, 0x8f, 0x12, 0x31,
-	0x14, 0xc7, 0x83, 0xb8, 0x2c, 0x14, 0xd8, 0x5d, 0xaa, 0xc6, 0xaa, 0x17, 0xdc, 0xcb, 0x92, 0x18,
-	0xf7, 0x62, 0x8c, 0x27, 0x0f, 0x08, 0x47, 0x8d, 0x86, 0xd5, 0x73, 0xf3, 0x66, 0xa6, 0xcc, 0x34,
-	0x99, 0x69, 0x27, 0xef, 0x75, 0x08, 0xf2, 0x3d, 0xfc, 0xbe, 0xa6, 0x0f, 0x18, 0x30, 0xee, 0xb1,
-	0xff, 0xdf, 0xef, 0xdf, 0x76, 0xde, 0x54, 0x8c, 0x52, 0xef, 0xd6, 0x36, 0xbf, 0xaf, 0xd1, 0x07,
-	0x7f, 0xfb, 0xe7, 0x42, 0xf4, 0x16, 0x1c, 0xc8, 0xd7, 0xa2, 0x5f, 0x78, 0x0a, 0x0e, 0x2a, 0xa3,
-	0x3a, 0xd3, 0xce, 0x6c, 0xb0, 0x6a, 0xd7, 0xf2, 0x4e, 0xdc, 0x54, 0xb0, 0xd5, 0x19, 0x04, 0xd0,
-	0x64, 0x77, 0x46, 0x57, 0x89, 0x7a, 0x32, 0xed, 0xcc, 0xba, 0xab, 0x71, 0x05, 0xdb, 0x25, 0x04,
-	0x78, 0xb0, 0x3b, 0xf3, 0x2d, 0x91, 0x6f, 0xc5, 0x88, 0xaa, 0x50, 0x6b, 0xc8, 0x32, 0x34, 0x44,
-	0xaa, 0x3b, 0xed, 0xce, 0x06, 0xab, 0x61, 0xcc, 0xe6, 0xfb, 0x48, 0xbe, 0x17, 0x92, 0x9a, 0xa4,
-	0xb2, 0x44, 0xd6, 0xbb, 0x56, 0x7c, 0xca, 0xe2, 0xe4, 0x44, 0x8e, 0xfa, 0x67, 0xf1, 0xe6, 0x4c,
-	0xf7, 0x1b, 0x83, 0x3a, 0x94, 0xd4, 0xf6, 0x2e, 0xb8, 0xa7, 0x4e, 0xca, 0xf7, 0x8d, 0xc1, 0x9f,
-	0x25, 0x9d, 0x9d, 0x56, 0x79, 0x67, 0x83, 0x47, 0xeb, 0xf2, 0xb6, 0xd5, 0xe3, 0xef, 0x9b, 0x9c,
-	0xc8, 0x51, 0xff, 0x28, 0x5e, 0x56, 0x60, 0x4b, 0x9d, 0x99, 0xd2, 0x6e, 0x0c, 0xfe, 0xd6, 0x90,
-	0x1b, 0x17, 0x74, 0x62, 0x9d, 0xba, 0xe4, 0xce, 0xf3, 0x88, 0x97, 0x07, 0x3a, 0x8f, 0xf0, 0x8b,
-	0x75, 0xf2, 0x93, 0x50, 0x8f, 0xd5, 0x00, 0x73, 0x52, 0x7d, 0xbe, 0xe1, 0x8b, 0xff, 0x7a, 0x73,
-	0xcc, 0x49, 0xbe, 0x12, 0x7d, 0x1e, 0x6a, 0x66, 0x51, 0x0d, 0xf8, 0x80, 0xcb, 0xb8, 0x5e, 0x5a,
-	0x94, 0xef, 0xc4, 0x84, 0x9a, 0xf5, 0xda, 0x6e, 0x35, 0x99, 0x1a, 0x10, 0x82, 0x47, 0x52, 0x82,
-	0x9d, 0x9b, 0x3d, 0x78, 0x68, 0x73, 0x79, 0x27, 0xae, 0x33, 0xf4, 0xb5, 0x4e, 0x0b, 0x40, 0x48,
-	0x83, 0x41, 0x52, 0x43, 0x56, 0xaf, 0x62, 0xbc, 0x68, 0x53, 0x79, 0x2b, 0xc6, 0x7c, 0xd3, 0xd2,
-	0xe7, 0xba, 0x86, 0x50, 0xa8, 0x11, 0x6b, 0xc3, 0x18, 0x7e, 0xf5, 0xf9, 0x0f, 0x08, 0x45, 0xfc,
-	0x89, 0x99, 0xdf, 0x98, 0xd4, 0x07, 0x0d, 0x4d, 0x28, 0xd4, 0x78, 0xda, 0x99, 0xf5, 0x57, 0xc3,
-	0x43, 0x36, 0x6f, 0x42, 0x21, 0xef, 0xc5, 0xb3, 0xa3, 0xd2, 0x90, 0xc1, 0x2c, 0xd9, 0x6f, 0x76,
-	0xb5, 0x9f, 0xeb, 0x01, 0xfd, 0x62, 0xc2, 0x5b, 0x9e, 0xf9, 0x69, 0x69, 0xe3, 0x6c, 0xd8, 0xbf,
-	0xfe, 0xc7, 0x5f, 0x30, 0x89, 0x7e, 0xd2, 0xe3, 0xe7, 0xf9, 0xe1, 0x6f, 0x00, 0x00, 0x00, 0xff,
-	0xff, 0x37, 0xa3, 0x19, 0x18, 0xae, 0x02, 0x00, 0x00,
+var file_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_config_proto_goTypes = []interface{}{
+	(*Config)(nil), // 0: Config
+}
+var file_config_proto_depIdxs = []int32{
+	0, // [0:0] is the sub-list for method output_type
+	0, // [0:0] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_config_proto_init() }
+func file_config_proto_init() {
+	if File_config_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Config); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_config_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_config_proto_goTypes,
+		DependencyIndexes: file_config_proto_depIdxs,
+		MessageInfos:      file_config_proto_msgTypes,
+	}.Build()
+	File_config_proto = out.File
+	file_config_proto_rawDesc = nil
+	file_config_proto_goTypes = nil
+	file_config_proto_depIdxs = nil
 }
diff --git a/internal/config/config.proto b/internal/config/config.proto
index 1d1dea7..9e8c31e 100644
--- a/internal/config/config.proto
+++ b/internal/config/config.proto
@@ -1,5 +1,6 @@
 
 syntax = "proto3";
+option go_package = "blitiri.com.ar/go/chasquid/internal/config";
 
 message Config {
 	// Default hostname to use when saying hello.
diff --git a/internal/domaininfo/domaininfo.go b/internal/domaininfo/domaininfo.go
index 0992e2f..8d4b7d1 100644
--- a/internal/domaininfo/domaininfo.go
+++ b/internal/domaininfo/domaininfo.go
@@ -11,7 +11,7 @@ import (
 )
 
 // Command to generate domaininfo.pb.go.
-//go:generate protoc --go_out=. domaininfo.proto
+//go:generate protoc --go_out=. --go_opt=paths=source_relative domaininfo.proto
 
 // DB represents the persistent domain information database.
 type DB struct {
diff --git a/internal/domaininfo/domaininfo.pb.go b/internal/domaininfo/domaininfo.pb.go
index 8c3cb50..b26a8c6 100644
--- a/internal/domaininfo/domaininfo.pb.go
+++ b/internal/domaininfo/domaininfo.pb.go
@@ -1,24 +1,29 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.23.0
+// 	protoc        v3.11.4
 // source: domaininfo.proto
 
 package domaininfo
 
 import (
-	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
 
 type SecLevel int32
 
@@ -33,104 +38,204 @@ const (
 	SecLevel_TLS_SECURE SecLevel = 3
 )
 
-var SecLevel_name = map[int32]string{
-	0: "PLAIN",
-	1: "TLS_CLIENT",
-	2: "TLS_INSECURE",
-	3: "TLS_SECURE",
-}
+// Enum value maps for SecLevel.
+var (
+	SecLevel_name = map[int32]string{
+		0: "PLAIN",
+		1: "TLS_CLIENT",
+		2: "TLS_INSECURE",
+		3: "TLS_SECURE",
+	}
+	SecLevel_value = map[string]int32{
+		"PLAIN":        0,
+		"TLS_CLIENT":   1,
+		"TLS_INSECURE": 2,
+		"TLS_SECURE":   3,
+	}
+)
 
-var SecLevel_value = map[string]int32{
-	"PLAIN":        0,
-	"TLS_CLIENT":   1,
-	"TLS_INSECURE": 2,
-	"TLS_SECURE":   3,
+func (x SecLevel) Enum() *SecLevel {
+	p := new(SecLevel)
+	*p = x
+	return p
 }
 
 func (x SecLevel) String() string {
-	return proto.EnumName(SecLevel_name, int32(x))
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (SecLevel) Descriptor() protoreflect.EnumDescriptor {
+	return file_domaininfo_proto_enumTypes[0].Descriptor()
+}
+
+func (SecLevel) Type() protoreflect.EnumType {
+	return &file_domaininfo_proto_enumTypes[0]
 }
 
+func (x SecLevel) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use SecLevel.Descriptor instead.
 func (SecLevel) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_622326b6f7a15daa, []int{0}
+	return file_domaininfo_proto_rawDescGZIP(), []int{0}
 }
 
 type Domain struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
 	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
 	// Security level for mail coming from this domain (they send to us).
 	IncomingSecLevel SecLevel `protobuf:"varint,2,opt,name=incoming_sec_level,json=incomingSecLevel,proto3,enum=domaininfo.SecLevel" json:"incoming_sec_level,omitempty"`
 	// Security level for mail going to this domain (we send to them).
-	OutgoingSecLevel     SecLevel `protobuf:"varint,3,opt,name=outgoing_sec_level,json=outgoingSecLevel,proto3,enum=domaininfo.SecLevel" json:"outgoing_sec_level,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
+	OutgoingSecLevel SecLevel `protobuf:"varint,3,opt,name=outgoing_sec_level,json=outgoingSecLevel,proto3,enum=domaininfo.SecLevel" json:"outgoing_sec_level,omitempty"`
 }
 
-func (m *Domain) Reset()         { *m = Domain{} }
-func (m *Domain) String() string { return proto.CompactTextString(m) }
-func (*Domain) ProtoMessage()    {}
-func (*Domain) Descriptor() ([]byte, []int) {
-	return fileDescriptor_622326b6f7a15daa, []int{0}
+func (x *Domain) Reset() {
+	*x = Domain{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_domaininfo_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *Domain) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Domain.Unmarshal(m, b)
-}
-func (m *Domain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Domain.Marshal(b, m, deterministic)
-}
-func (m *Domain) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Domain.Merge(m, src)
-}
-func (m *Domain) XXX_Size() int {
-	return xxx_messageInfo_Domain.Size(m)
+func (x *Domain) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Domain) XXX_DiscardUnknown() {
-	xxx_messageInfo_Domain.DiscardUnknown(m)
+
+func (*Domain) ProtoMessage() {}
+
+func (x *Domain) ProtoReflect() protoreflect.Message {
+	mi := &file_domaininfo_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Domain proto.InternalMessageInfo
+// Deprecated: Use Domain.ProtoReflect.Descriptor instead.
+func (*Domain) Descriptor() ([]byte, []int) {
+	return file_domaininfo_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *Domain) GetName() string {
-	if m != nil {
-		return m.Name
+func (x *Domain) GetName() string {
+	if x != nil {
+		return x.Name
 	}
 	return ""
 }
 
-func (m *Domain) GetIncomingSecLevel() SecLevel {
-	if m != nil {
-		return m.IncomingSecLevel
+func (x *Domain) GetIncomingSecLevel() SecLevel {
+	if x != nil {
+		return x.IncomingSecLevel
 	}
 	return SecLevel_PLAIN
 }
 
-func (m *Domain) GetOutgoingSecLevel() SecLevel {
-	if m != nil {
-		return m.OutgoingSecLevel
+func (x *Domain) GetOutgoingSecLevel() SecLevel {
+	if x != nil {
+		return x.OutgoingSecLevel
 	}
 	return SecLevel_PLAIN
 }
 
-func init() {
-	proto.RegisterEnum("domaininfo.SecLevel", SecLevel_name, SecLevel_value)
-	proto.RegisterType((*Domain)(nil), "domaininfo.Domain")
-}
-
-func init() { proto.RegisterFile("domaininfo.proto", fileDescriptor_622326b6f7a15daa) }
+var File_domaininfo_proto protoreflect.FileDescriptor
+
+var file_domaininfo_proto_rawDesc = []byte{
+	0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x12, 0x0a, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0xa4,
+	0x01, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x42, 0x0a,
+	0x12, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6c, 0x65,
+	0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x64, 0x6f, 0x6d, 0x61,
+	0x69, 0x6e, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x65, 0x63, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52,
+	0x10, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x63, 0x4c, 0x65, 0x76, 0x65,
+	0x6c, 0x12, 0x42, 0x0a, 0x12, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65,
+	0x63, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e,
+	0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x65, 0x63, 0x4c, 0x65,
+	0x76, 0x65, 0x6c, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x63,
+	0x4c, 0x65, 0x76, 0x65, 0x6c, 0x2a, 0x47, 0x0a, 0x08, 0x53, 0x65, 0x63, 0x4c, 0x65, 0x76, 0x65,
+	0x6c, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x4c, 0x41, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a,
+	0x54, 0x4c, 0x53, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c,
+	0x54, 0x4c, 0x53, 0x5f, 0x49, 0x4e, 0x53, 0x45, 0x43, 0x55, 0x52, 0x45, 0x10, 0x02, 0x12, 0x0e,
+	0x0a, 0x0a, 0x54, 0x4c, 0x53, 0x5f, 0x53, 0x45, 0x43, 0x55, 0x52, 0x45, 0x10, 0x03, 0x42, 0x30,
+	0x5a, 0x2e, 0x62, 0x6c, 0x69, 0x74, 0x69, 0x72, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72,
+	0x2f, 0x67, 0x6f, 0x2f, 0x63, 0x68, 0x61, 0x73, 0x71, 0x75, 0x69, 0x64, 0x2f, 0x69, 0x6e, 0x74,
+	0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x66, 0x6f,
+	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_domaininfo_proto_rawDescOnce sync.Once
+	file_domaininfo_proto_rawDescData = file_domaininfo_proto_rawDesc
+)
 
-var fileDescriptor_622326b6f7a15daa = []byte{
-	// 190 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x48, 0xc9, 0xcf, 0x4d,
-	0xcc, 0xcc, 0xcb, 0xcc, 0x4b, 0xcb, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88,
-	0x28, 0x2d, 0x61, 0xe4, 0x62, 0x73, 0x01, 0x73, 0x85, 0x84, 0xb8, 0x58, 0xf2, 0x12, 0x73, 0x53,
-	0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0xc0, 0x6c, 0x21, 0x27, 0x2e, 0xa1, 0xcc, 0xbc, 0xe4,
-	0xfc, 0xdc, 0xcc, 0xbc, 0xf4, 0xf8, 0xe2, 0xd4, 0xe4, 0xf8, 0x9c, 0xd4, 0xb2, 0xd4, 0x1c, 0x09,
-	0x26, 0x05, 0x46, 0x0d, 0x3e, 0x23, 0x11, 0x3d, 0x24, 0x93, 0x83, 0x53, 0x93, 0x7d, 0x40, 0x72,
-	0x41, 0x02, 0x30, 0xf5, 0x30, 0x11, 0x90, 0x19, 0xf9, 0xa5, 0x25, 0xe9, 0xf9, 0xa8, 0x66, 0x30,
-	0xe3, 0x33, 0x03, 0xa6, 0x1e, 0x26, 0xa2, 0xe5, 0xce, 0xc5, 0x01, 0x37, 0x8f, 0x93, 0x8b, 0x35,
-	0xc0, 0xc7, 0xd1, 0xd3, 0x4f, 0x80, 0x41, 0x88, 0x8f, 0x8b, 0x2b, 0xc4, 0x27, 0x38, 0xde, 0xd9,
-	0xc7, 0xd3, 0xd5, 0x2f, 0x44, 0x80, 0x51, 0x48, 0x80, 0x8b, 0x07, 0xc4, 0xf7, 0xf4, 0x0b, 0x76,
-	0x75, 0x0e, 0x0d, 0x72, 0x15, 0x60, 0x82, 0xa9, 0x80, 0xf2, 0x99, 0x93, 0xd8, 0xc0, 0x41, 0x60,
-	0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x2c, 0x78, 0x65, 0x5b, 0x16, 0x01, 0x00, 0x00,
+func file_domaininfo_proto_rawDescGZIP() []byte {
+	file_domaininfo_proto_rawDescOnce.Do(func() {
+		file_domaininfo_proto_rawDescData = protoimpl.X.CompressGZIP(file_domaininfo_proto_rawDescData)
+	})
+	return file_domaininfo_proto_rawDescData
+}
+
+var file_domaininfo_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_domaininfo_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_domaininfo_proto_goTypes = []interface{}{
+	(SecLevel)(0),  // 0: domaininfo.SecLevel
+	(*Domain)(nil), // 1: domaininfo.Domain
+}
+var file_domaininfo_proto_depIdxs = []int32{
+	0, // 0: domaininfo.Domain.incoming_sec_level:type_name -> domaininfo.SecLevel
+	0, // 1: domaininfo.Domain.outgoing_sec_level:type_name -> domaininfo.SecLevel
+	2, // [2:2] is the sub-list for method output_type
+	2, // [2:2] is the sub-list for method input_type
+	2, // [2:2] is the sub-list for extension type_name
+	2, // [2:2] is the sub-list for extension extendee
+	0, // [0:2] is the sub-list for field type_name
+}
+
+func init() { file_domaininfo_proto_init() }
+func file_domaininfo_proto_init() {
+	if File_domaininfo_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_domaininfo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Domain); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_domaininfo_proto_rawDesc,
+			NumEnums:      1,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_domaininfo_proto_goTypes,
+		DependencyIndexes: file_domaininfo_proto_depIdxs,
+		EnumInfos:         file_domaininfo_proto_enumTypes,
+		MessageInfos:      file_domaininfo_proto_msgTypes,
+	}.Build()
+	File_domaininfo_proto = out.File
+	file_domaininfo_proto_rawDesc = nil
+	file_domaininfo_proto_goTypes = nil
+	file_domaininfo_proto_depIdxs = nil
 }
diff --git a/internal/domaininfo/domaininfo.proto b/internal/domaininfo/domaininfo.proto
index a2df39f..1582c6b 100644
--- a/internal/domaininfo/domaininfo.proto
+++ b/internal/domaininfo/domaininfo.proto
@@ -2,6 +2,7 @@
 syntax = "proto3";
 
 package domaininfo;
+option go_package = "blitiri.com.ar/go/chasquid/internal/domaininfo";
 
 enum SecLevel {
 	// Does not do TLS.
diff --git a/internal/protoio/testpb/dummy.go b/internal/protoio/testpb/dummy.go
index f9c04d1..b2495b3 100644
--- a/internal/protoio/testpb/dummy.go
+++ b/internal/protoio/testpb/dummy.go
@@ -1,3 +1,3 @@
 package testpb
 
-//go:generate protoc --go_out=. testpb.proto
+//go:generate protoc --go_out=. --go_opt=paths=source_relative testpb.proto
diff --git a/internal/protoio/testpb/testpb.pb.go b/internal/protoio/testpb/testpb.pb.go
index e29be55..a495225 100644
--- a/internal/protoio/testpb/testpb.pb.go
+++ b/internal/protoio/testpb/testpb.pb.go
@@ -1,75 +1,149 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.23.0
+// 	protoc        v3.11.4
 // source: testpb.proto
 
 package testpb
 
 import (
-	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
 
 type M struct {
-	Content              string   `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *M) Reset()         { *m = M{} }
-func (m *M) String() string { return proto.CompactTextString(m) }
-func (*M) ProtoMessage()    {}
-func (*M) Descriptor() ([]byte, []int) {
-	return fileDescriptor_1b98c0ed33edeb52, []int{0}
+	Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"`
 }
 
-func (m *M) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_M.Unmarshal(m, b)
-}
-func (m *M) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_M.Marshal(b, m, deterministic)
-}
-func (m *M) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_M.Merge(m, src)
+func (x *M) Reset() {
+	*x = M{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_testpb_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *M) XXX_Size() int {
-	return xxx_messageInfo_M.Size(m)
+
+func (x *M) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *M) XXX_DiscardUnknown() {
-	xxx_messageInfo_M.DiscardUnknown(m)
+
+func (*M) ProtoMessage() {}
+
+func (x *M) ProtoReflect() protoreflect.Message {
+	mi := &file_testpb_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_M proto.InternalMessageInfo
+// Deprecated: Use M.ProtoReflect.Descriptor instead.
+func (*M) Descriptor() ([]byte, []int) {
+	return file_testpb_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *M) GetContent() string {
-	if m != nil {
-		return m.Content
+func (x *M) GetContent() string {
+	if x != nil {
+		return x.Content
 	}
 	return ""
 }
 
-func init() {
-	proto.RegisterType((*M)(nil), "testpb.M")
+var File_testpb_proto protoreflect.FileDescriptor
+
+var file_testpb_proto_rawDesc = []byte{
+	0x0a, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06,
+	0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x22, 0x1d, 0x0a, 0x01, 0x4d, 0x12, 0x18, 0x0a, 0x07, 0x63,
+	0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f,
+	0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x34, 0x5a, 0x32, 0x62, 0x6c, 0x69, 0x74, 0x69, 0x72, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x2f, 0x67, 0x6f, 0x2f, 0x63, 0x68, 0x61, 0x73, 0x71,
+	0x75, 0x69, 0x64, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x69, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x33,
+}
+
+var (
+	file_testpb_proto_rawDescOnce sync.Once
+	file_testpb_proto_rawDescData = file_testpb_proto_rawDesc
+)
+
+func file_testpb_proto_rawDescGZIP() []byte {
+	file_testpb_proto_rawDescOnce.Do(func() {
+		file_testpb_proto_rawDescData = protoimpl.X.CompressGZIP(file_testpb_proto_rawDescData)
+	})
+	return file_testpb_proto_rawDescData
 }
 
-func init() { proto.RegisterFile("testpb.proto", fileDescriptor_1b98c0ed33edeb52) }
+var file_testpb_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_testpb_proto_goTypes = []interface{}{
+	(*M)(nil), // 0: testpb.M
+}
+var file_testpb_proto_depIdxs = []int32{
+	0, // [0:0] is the sub-list for method output_type
+	0, // [0:0] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
 
-var fileDescriptor_1b98c0ed33edeb52 = []byte{
-	// 72 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x49, 0x2d, 0x2e,
-	0x29, 0x48, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xf0, 0x94, 0x64, 0xb9, 0x18,
-	0x7d, 0x85, 0x24, 0xb8, 0xd8, 0x93, 0xf3, 0xf3, 0x4a, 0x52, 0xf3, 0x4a, 0x24, 0x18, 0x15, 0x18,
-	0x35, 0x38, 0x83, 0x60, 0xdc, 0x24, 0x36, 0xb0, 0x6a, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff,
-	0xcb, 0x37, 0x9b, 0x8f, 0x3d, 0x00, 0x00, 0x00,
+func init() { file_testpb_proto_init() }
+func file_testpb_proto_init() {
+	if File_testpb_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_testpb_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*M); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_testpb_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_testpb_proto_goTypes,
+		DependencyIndexes: file_testpb_proto_depIdxs,
+		MessageInfos:      file_testpb_proto_msgTypes,
+	}.Build()
+	File_testpb_proto = out.File
+	file_testpb_proto_rawDesc = nil
+	file_testpb_proto_goTypes = nil
+	file_testpb_proto_depIdxs = nil
 }
diff --git a/internal/protoio/testpb/testpb.proto b/internal/protoio/testpb/testpb.proto
index a93ffcb..7424773 100644
--- a/internal/protoio/testpb/testpb.proto
+++ b/internal/protoio/testpb/testpb.proto
@@ -2,6 +2,7 @@
 syntax = "proto3";
 
 package testpb;
+option go_package = "blitiri.com.ar/go/chasquid/internal/protoio/testpb";
 
 message M {
 	string content = 1;
diff --git a/internal/queue/queue.go b/internal/queue/queue.go
index 2d0b6b7..46e5108 100644
--- a/internal/queue/queue.go
+++ b/internal/queue/queue.go
@@ -3,7 +3,7 @@
 package queue
 
 // Command to generate queue.pb.go from queue.proto.
-//go:generate protoc --go_out=. -I=${GOPATH}/src -I. queue.proto
+//go:generate protoc --go_out=. --go_opt=paths=source_relative -I=${GOPATH}/src -I. queue.proto
 
 import (
 	"context"
@@ -29,8 +29,8 @@ import (
 	"blitiri.com.ar/go/chasquid/internal/trace"
 	"blitiri.com.ar/go/log"
 
-	"github.com/golang/protobuf/ptypes"
 	"golang.org/x/net/idna"
+	"google.golang.org/protobuf/types/known/timestamppb"
 )
 
 const (
@@ -276,8 +276,8 @@ func ItemFromFile(fname string) (*Item, error) {
 		return nil, err
 	}
 
-	item.CreatedAt, err = ptypes.Timestamp(item.CreatedAtTs)
-	return item, err
+	item.CreatedAt = timeFromProto(item.CreatedAtTs)
+	return item, nil
 }
 
 // WriteTo saves an item to the given directory.
@@ -286,11 +286,7 @@ func (item *Item) WriteTo(dir string) error {
 	defer item.Unlock()
 	itemsWritten.Add(1)
 
-	var err error
-	item.CreatedAtTs, err = ptypes.TimestampProto(item.CreatedAt)
-	if err != nil {
-		return err
-	}
+	item.CreatedAtTs = timeToProto(item.CreatedAt)
 
 	path := fmt.Sprintf("%s/%s%s", dir, itemFilePrefix, item.ID)
 
@@ -490,3 +486,14 @@ func mustIDNAToASCII(s string) string {
 	}
 	return s
 }
+
+func timeFromProto(ts *timestamppb.Timestamp) time.Time {
+	return time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
+}
+
+func timeToProto(t time.Time) *timestamppb.Timestamp {
+	return &timestamppb.Timestamp{
+		Seconds: t.Unix(),
+		Nanos:   int32(t.Nanosecond()),
+	}
+}
diff --git a/internal/queue/queue.pb.go b/internal/queue/queue.pb.go
index 94bfc29..8904ea7 100644
--- a/internal/queue/queue.pb.go
+++ b/internal/queue/queue.pb.go
@@ -1,25 +1,30 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.23.0
+// 	protoc        v3.11.4
 // source: queue.proto
 
 package queue
 
 import (
-	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
 	timestamp "github.com/golang/protobuf/ptypes/timestamp"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
 
 type Recipient_Type int32
 
@@ -28,22 +33,43 @@ const (
 	Recipient_PIPE  Recipient_Type = 1
 )
 
-var Recipient_Type_name = map[int32]string{
-	0: "EMAIL",
-	1: "PIPE",
-}
+// Enum value maps for Recipient_Type.
+var (
+	Recipient_Type_name = map[int32]string{
+		0: "EMAIL",
+		1: "PIPE",
+	}
+	Recipient_Type_value = map[string]int32{
+		"EMAIL": 0,
+		"PIPE":  1,
+	}
+)
 
-var Recipient_Type_value = map[string]int32{
-	"EMAIL": 0,
-	"PIPE":  1,
+func (x Recipient_Type) Enum() *Recipient_Type {
+	p := new(Recipient_Type)
+	*p = x
+	return p
 }
 
 func (x Recipient_Type) String() string {
-	return proto.EnumName(Recipient_Type_name, int32(x))
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Recipient_Type) Descriptor() protoreflect.EnumDescriptor {
+	return file_queue_proto_enumTypes[0].Descriptor()
+}
+
+func (Recipient_Type) Type() protoreflect.EnumType {
+	return &file_queue_proto_enumTypes[0]
+}
+
+func (x Recipient_Type) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
 }
 
+// Deprecated: Use Recipient_Type.Descriptor instead.
 func (Recipient_Type) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_96e4d7d76a734cd8, []int{1, 0}
+	return file_queue_proto_rawDescGZIP(), []int{1, 0}
 }
 
 type Recipient_Status int32
@@ -54,27 +80,52 @@ const (
 	Recipient_FAILED  Recipient_Status = 2
 )
 
-var Recipient_Status_name = map[int32]string{
-	0: "PENDING",
-	1: "SENT",
-	2: "FAILED",
-}
+// Enum value maps for Recipient_Status.
+var (
+	Recipient_Status_name = map[int32]string{
+		0: "PENDING",
+		1: "SENT",
+		2: "FAILED",
+	}
+	Recipient_Status_value = map[string]int32{
+		"PENDING": 0,
+		"SENT":    1,
+		"FAILED":  2,
+	}
+)
 
-var Recipient_Status_value = map[string]int32{
-	"PENDING": 0,
-	"SENT":    1,
-	"FAILED":  2,
+func (x Recipient_Status) Enum() *Recipient_Status {
+	p := new(Recipient_Status)
+	*p = x
+	return p
 }
 
 func (x Recipient_Status) String() string {
-	return proto.EnumName(Recipient_Status_name, int32(x))
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Recipient_Status) Descriptor() protoreflect.EnumDescriptor {
+	return file_queue_proto_enumTypes[1].Descriptor()
 }
 
+func (Recipient_Status) Type() protoreflect.EnumType {
+	return &file_queue_proto_enumTypes[1]
+}
+
+func (x Recipient_Status) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use Recipient_Status.Descriptor instead.
 func (Recipient_Status) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_96e4d7d76a734cd8, []int{1, 1}
+	return file_queue_proto_rawDescGZIP(), []int{1, 1}
 }
 
 type Message struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
 	// Message ID. Uniquely identifies this message, it is used for
 	// auditing and troubleshooting.
 	ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
@@ -84,80 +135,88 @@ type Message struct {
 	Rcpt []*Recipient `protobuf:"bytes,4,rep,name=rcpt,proto3" json:"rcpt,omitempty"`
 	Data []byte       `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"`
 	// Creation timestamp.
-	CreatedAtTs          *timestamp.Timestamp `protobuf:"bytes,6,opt,name=created_at_ts,json=createdAtTs,proto3" json:"created_at_ts,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
-	XXX_unrecognized     []byte               `json:"-"`
-	XXX_sizecache        int32                `json:"-"`
+	CreatedAtTs *timestamp.Timestamp `protobuf:"bytes,6,opt,name=created_at_ts,json=createdAtTs,proto3" json:"created_at_ts,omitempty"`
 }
 
-func (m *Message) Reset()         { *m = Message{} }
-func (m *Message) String() string { return proto.CompactTextString(m) }
-func (*Message) ProtoMessage()    {}
-func (*Message) Descriptor() ([]byte, []int) {
-	return fileDescriptor_96e4d7d76a734cd8, []int{0}
+func (x *Message) Reset() {
+	*x = Message{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_queue_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *Message) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Message.Unmarshal(m, b)
-}
-func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Message.Marshal(b, m, deterministic)
-}
-func (m *Message) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Message.Merge(m, src)
+func (x *Message) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Message) XXX_Size() int {
-	return xxx_messageInfo_Message.Size(m)
-}
-func (m *Message) XXX_DiscardUnknown() {
-	xxx_messageInfo_Message.DiscardUnknown(m)
+
+func (*Message) ProtoMessage() {}
+
+func (x *Message) ProtoReflect() protoreflect.Message {
+	mi := &file_queue_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Message proto.InternalMessageInfo
+// Deprecated: Use Message.ProtoReflect.Descriptor instead.
+func (*Message) Descriptor() ([]byte, []int) {
+	return file_queue_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *Message) GetID() string {
-	if m != nil {
-		return m.ID
+func (x *Message) GetID() string {
+	if x != nil {
+		return x.ID
 	}
 	return ""
 }
 
-func (m *Message) GetFrom() string {
-	if m != nil {
-		return m.From
+func (x *Message) GetFrom() string {
+	if x != nil {
+		return x.From
 	}
 	return ""
 }
 
-func (m *Message) GetTo() []string {
-	if m != nil {
-		return m.To
+func (x *Message) GetTo() []string {
+	if x != nil {
+		return x.To
 	}
 	return nil
 }
 
-func (m *Message) GetRcpt() []*Recipient {
-	if m != nil {
-		return m.Rcpt
+func (x *Message) GetRcpt() []*Recipient {
+	if x != nil {
+		return x.Rcpt
 	}
 	return nil
 }
 
-func (m *Message) GetData() []byte {
-	if m != nil {
-		return m.Data
+func (x *Message) GetData() []byte {
+	if x != nil {
+		return x.Data
 	}
 	return nil
 }
 
-func (m *Message) GetCreatedAtTs() *timestamp.Timestamp {
-	if m != nil {
-		return m.CreatedAtTs
+func (x *Message) GetCreatedAtTs() *timestamp.Timestamp {
+	if x != nil {
+		return x.CreatedAtTs
 	}
 	return nil
 }
 
 type Recipient struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
 	// Address to send the message to.
 	// This is the final one, after expanding aliases.
 	Address            string           `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
@@ -167,106 +226,201 @@ type Recipient struct {
 	// Address that this recipient was originally intended to.
 	// This is before expanding aliases and only used in very particular
 	// cases.
-	OriginalAddress      string   `protobuf:"bytes,5,opt,name=original_address,json=originalAddress,proto3" json:"original_address,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
+	OriginalAddress string `protobuf:"bytes,5,opt,name=original_address,json=originalAddress,proto3" json:"original_address,omitempty"`
 }
 
-func (m *Recipient) Reset()         { *m = Recipient{} }
-func (m *Recipient) String() string { return proto.CompactTextString(m) }
-func (*Recipient) ProtoMessage()    {}
-func (*Recipient) Descriptor() ([]byte, []int) {
-	return fileDescriptor_96e4d7d76a734cd8, []int{1}
+func (x *Recipient) Reset() {
+	*x = Recipient{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_queue_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *Recipient) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Recipient.Unmarshal(m, b)
+func (x *Recipient) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Recipient) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Recipient.Marshal(b, m, deterministic)
-}
-func (m *Recipient) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Recipient.Merge(m, src)
-}
-func (m *Recipient) XXX_Size() int {
-	return xxx_messageInfo_Recipient.Size(m)
-}
-func (m *Recipient) XXX_DiscardUnknown() {
-	xxx_messageInfo_Recipient.DiscardUnknown(m)
+
+func (*Recipient) ProtoMessage() {}
+
+func (x *Recipient) ProtoReflect() protoreflect.Message {
+	mi := &file_queue_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Recipient proto.InternalMessageInfo
+// Deprecated: Use Recipient.ProtoReflect.Descriptor instead.
+func (*Recipient) Descriptor() ([]byte, []int) {
+	return file_queue_proto_rawDescGZIP(), []int{1}
+}
 
-func (m *Recipient) GetAddress() string {
-	if m != nil {
-		return m.Address
+func (x *Recipient) GetAddress() string {
+	if x != nil {
+		return x.Address
 	}
 	return ""
 }
 
-func (m *Recipient) GetType() Recipient_Type {
-	if m != nil {
-		return m.Type
+func (x *Recipient) GetType() Recipient_Type {
+	if x != nil {
+		return x.Type
 	}
 	return Recipient_EMAIL
 }
 
-func (m *Recipient) GetStatus() Recipient_Status {
-	if m != nil {
-		return m.Status
+func (x *Recipient) GetStatus() Recipient_Status {
+	if x != nil {
+		return x.Status
 	}
 	return Recipient_PENDING
 }
 
-func (m *Recipient) GetLastFailureMessage() string {
-	if m != nil {
-		return m.LastFailureMessage
+func (x *Recipient) GetLastFailureMessage() string {
+	if x != nil {
+		return x.LastFailureMessage
 	}
 	return ""
 }
 
-func (m *Recipient) GetOriginalAddress() string {
-	if m != nil {
-		return m.OriginalAddress
+func (x *Recipient) GetOriginalAddress() string {
+	if x != nil {
+		return x.OriginalAddress
 	}
 	return ""
 }
 
-func init() {
-	proto.RegisterEnum("queue.Recipient_Type", Recipient_Type_name, Recipient_Type_value)
-	proto.RegisterEnum("queue.Recipient_Status", Recipient_Status_name, Recipient_Status_value)
-	proto.RegisterType((*Message)(nil), "queue.Message")
-	proto.RegisterType((*Recipient)(nil), "queue.Recipient")
-}
-
-func init() { proto.RegisterFile("queue.proto", fileDescriptor_96e4d7d76a734cd8) }
-
-var fileDescriptor_96e4d7d76a734cd8 = []byte{
-	// 391 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x90, 0xcf, 0x8a, 0x9c, 0x40,
-	0x10, 0xc6, 0xe3, 0xdf, 0xc9, 0x94, 0xc9, 0x46, 0x9a, 0x84, 0x34, 0x9b, 0x8b, 0x48, 0x0e, 0x2e,
-	0x01, 0x0d, 0x93, 0x63, 0x20, 0x20, 0xe8, 0x06, 0x61, 0x67, 0x18, 0x1c, 0xef, 0xd2, 0x6a, 0x6b,
-	0x04, 0x9d, 0x36, 0x76, 0x7b, 0x98, 0x37, 0xca, 0x1b, 0xe4, 0xf5, 0x82, 0xad, 0x26, 0x90, 0xbd,
-	0x55, 0xd5, 0xf7, 0xeb, 0xea, 0xaf, 0x3e, 0xb0, 0x7e, 0x4e, 0x74, 0xa2, 0xfe, 0x30, 0x32, 0xc1,
-	0x90, 0x21, 0x9b, 0xfb, 0xaf, 0x4d, 0x2b, 0x7e, 0x4c, 0x85, 0x5f, 0xb2, 0x3e, 0x68, 0x58, 0x47,
-	0xae, 0x4d, 0x20, 0xf5, 0x62, 0xaa, 0x83, 0x41, 0xdc, 0x06, 0xca, 0x03, 0xd1, 0xf6, 0x94, 0x0b,
-	0xd2, 0x0f, 0xff, 0xaa, 0x65, 0x87, 0xfb, 0x5b, 0x81, 0xdd, 0x91, 0x72, 0x4e, 0x1a, 0x8a, 0xee,
-	0x40, 0x4d, 0x22, 0xac, 0x38, 0x8a, 0xb7, 0x4f, 0xd5, 0x24, 0x42, 0x08, 0xf4, 0x7a, 0x64, 0x3d,
-	0x56, 0xe5, 0x44, 0xd6, 0x33, 0x93, 0x31, 0xac, 0x39, 0xda, 0xcc, 0x64, 0x0c, 0x7d, 0x04, 0x7d,
-	0x2c, 0x07, 0x81, 0x75, 0x47, 0xf3, 0xac, 0x83, 0xed, 0x2f, 0xfe, 0x52, 0x5a, 0xb6, 0x43, 0x4b,
-	0xaf, 0x22, 0x95, 0xea, 0xbc, 0xa9, 0x22, 0x82, 0x60, 0xc3, 0x51, 0xbc, 0x57, 0xa9, 0xac, 0xd1,
-	0x37, 0x78, 0x5d, 0x8e, 0x94, 0x08, 0x5a, 0xe5, 0x44, 0xe4, 0x82, 0x63, 0xd3, 0x51, 0x3c, 0xeb,
-	0x70, 0xef, 0x37, 0x8c, 0x35, 0xdd, 0x7a, 0x63, 0x31, 0xd5, 0x7e, 0xb6, 0x59, 0x4e, 0xad, 0xf5,
-	0x41, 0x28, 0x32, 0xee, 0xfe, 0x52, 0x61, 0xff, 0xf7, 0x1f, 0x84, 0x61, 0x47, 0xaa, 0x6a, 0xa4,
-	0x9c, 0xaf, 0x07, 0x6c, 0x2d, 0x7a, 0x00, 0x7d, 0x0e, 0x41, 0x5e, 0x71, 0x77, 0x78, 0xf7, 0xbf,
-	0x43, 0x3f, 0xbb, 0x0d, 0x34, 0x95, 0x08, 0x0a, 0xc0, 0xe4, 0x82, 0x88, 0x89, 0x63, 0x4d, 0xc2,
-	0xef, 0x9f, 0xc1, 0x17, 0x29, 0xa7, 0x2b, 0x86, 0x3e, 0xc3, 0xdb, 0x8e, 0x70, 0x91, 0xd7, 0xa4,
-	0xed, 0xa6, 0x91, 0xe6, 0xfd, 0x92, 0x24, 0xd6, 0xa5, 0x05, 0x34, 0x6b, 0x8f, 0x8b, 0xb4, 0x65,
-	0xfc, 0x00, 0x36, 0x1b, 0xdb, 0xa6, 0xbd, 0x92, 0x2e, 0xdf, 0x0c, 0x1b, 0x92, 0x7e, 0xb3, 0xcd,
-	0xc3, 0x65, 0xec, 0x7e, 0x00, 0x7d, 0xf6, 0x86, 0xf6, 0x60, 0xc4, 0xc7, 0x30, 0x79, 0xb2, 0x5f,
-	0xa0, 0x97, 0xa0, 0x9f, 0x93, 0x73, 0x6c, 0x2b, 0xee, 0x27, 0x30, 0x17, 0x2f, 0xc8, 0x82, 0xdd,
-	0x39, 0x3e, 0x45, 0xc9, 0xe9, 0xfb, 0x02, 0x5c, 0xe2, 0x53, 0x66, 0x2b, 0x08, 0xc0, 0x7c, 0x0c,
-	0x93, 0xa7, 0x38, 0xb2, 0xd5, 0xc2, 0x94, 0x59, 0x7e, 0xf9, 0x13, 0x00, 0x00, 0xff, 0xff, 0x9b,
-	0xcb, 0xcf, 0x07, 0x3e, 0x02, 0x00, 0x00,
+var File_queue_proto protoreflect.FileDescriptor
+
+var file_queue_proto_rawDesc = []byte{
+	0x0a, 0x0b, 0x71, 0x75, 0x65, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x71,
+	0x75, 0x65, 0x75, 0x65, 0x1a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
+	0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+	0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+	0x70, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x22, 0xb7, 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a,
+	0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a,
+	0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f,
+	0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x54, 0x6f, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x54,
+	0x6f, 0x12, 0x24, 0x0a, 0x04, 0x72, 0x63, 0x70, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x10, 0x2e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e,
+	0x74, 0x52, 0x04, 0x72, 0x63, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3e, 0x0a, 0x0d, 0x63,
+	0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b,
+	0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x54, 0x73, 0x22, 0xa8, 0x02, 0x0a, 0x09,
+	0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72,
+	0x65, 0x73, 0x73, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0e, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69,
+	0x65, 0x6e, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2f,
+	0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17,
+	0x2e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74,
+	0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
+	0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f,
+	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6c,
+	0x61, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+	0x65, 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x64,
+	0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x72, 0x69,
+	0x67, 0x69, 0x6e, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x1b, 0x0a, 0x04,
+	0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x41, 0x49, 0x4c, 0x10, 0x00, 0x12,
+	0x08, 0x0a, 0x04, 0x50, 0x49, 0x50, 0x45, 0x10, 0x01, 0x22, 0x2b, 0x0a, 0x06, 0x53, 0x74, 0x61,
+	0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x00,
+	0x12, 0x08, 0x0a, 0x04, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41,
+	0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x42, 0x2b, 0x5a, 0x29, 0x62, 0x6c, 0x69, 0x74, 0x69, 0x72,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x2f, 0x67, 0x6f, 0x2f, 0x63, 0x68, 0x61, 0x73,
+	0x71, 0x75, 0x69, 0x64, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x71, 0x75,
+	0x65, 0x75, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_queue_proto_rawDescOnce sync.Once
+	file_queue_proto_rawDescData = file_queue_proto_rawDesc
+)
+
+func file_queue_proto_rawDescGZIP() []byte {
+	file_queue_proto_rawDescOnce.Do(func() {
+		file_queue_proto_rawDescData = protoimpl.X.CompressGZIP(file_queue_proto_rawDescData)
+	})
+	return file_queue_proto_rawDescData
+}
+
+var file_queue_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
+var file_queue_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_queue_proto_goTypes = []interface{}{
+	(Recipient_Type)(0),         // 0: queue.Recipient.Type
+	(Recipient_Status)(0),       // 1: queue.Recipient.Status
+	(*Message)(nil),             // 2: queue.Message
+	(*Recipient)(nil),           // 3: queue.Recipient
+	(*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp
+}
+var file_queue_proto_depIdxs = []int32{
+	3, // 0: queue.Message.rcpt:type_name -> queue.Recipient
+	4, // 1: queue.Message.created_at_ts:type_name -> google.protobuf.Timestamp
+	0, // 2: queue.Recipient.type:type_name -> queue.Recipient.Type
+	1, // 3: queue.Recipient.status:type_name -> queue.Recipient.Status
+	4, // [4:4] is the sub-list for method output_type
+	4, // [4:4] is the sub-list for method input_type
+	4, // [4:4] is the sub-list for extension type_name
+	4, // [4:4] is the sub-list for extension extendee
+	0, // [0:4] is the sub-list for field type_name
+}
+
+func init() { file_queue_proto_init() }
+func file_queue_proto_init() {
+	if File_queue_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_queue_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Message); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_queue_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Recipient); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_queue_proto_rawDesc,
+			NumEnums:      2,
+			NumMessages:   2,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_queue_proto_goTypes,
+		DependencyIndexes: file_queue_proto_depIdxs,
+		EnumInfos:         file_queue_proto_enumTypes,
+		MessageInfos:      file_queue_proto_msgTypes,
+	}.Build()
+	File_queue_proto = out.File
+	file_queue_proto_rawDesc = nil
+	file_queue_proto_goTypes = nil
+	file_queue_proto_depIdxs = nil
 }
diff --git a/internal/queue/queue.proto b/internal/queue/queue.proto
index 80218cf..c1fe2dc 100644
--- a/internal/queue/queue.proto
+++ b/internal/queue/queue.proto
@@ -2,6 +2,7 @@
 syntax = "proto3";
 
 package queue;
+option go_package = "blitiri.com.ar/go/chasquid/internal/queue";
 
 import "github.com/golang/protobuf/ptypes/timestamp/timestamp.proto";
 
diff --git a/internal/userdb/userdb.go b/internal/userdb/userdb.go
index 81b04bc..ba66eaa 100644
--- a/internal/userdb/userdb.go
+++ b/internal/userdb/userdb.go
@@ -30,7 +30,7 @@
 //
 package userdb
 
-//go:generate protoc --go_out=. userdb.proto
+//go:generate protoc --go_out=. --go_opt=paths=source_relative userdb.proto
 
 import (
 	"crypto/rand"
diff --git a/internal/userdb/userdb.pb.go b/internal/userdb/userdb.pb.go
index 859d489..2061629 100644
--- a/internal/userdb/userdb.pb.go
+++ b/internal/userdb/userdb.pb.go
@@ -1,98 +1,140 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.23.0
+// 	protoc        v3.11.4
 // source: userdb.proto
 
 package userdb
 
 import (
-	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
 
 type ProtoDB struct {
-	Users                map[string]*Password `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
-	XXX_unrecognized     []byte               `json:"-"`
-	XXX_sizecache        int32                `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *ProtoDB) Reset()         { *m = ProtoDB{} }
-func (m *ProtoDB) String() string { return proto.CompactTextString(m) }
-func (*ProtoDB) ProtoMessage()    {}
-func (*ProtoDB) Descriptor() ([]byte, []int) {
-	return fileDescriptor_1492f046cfa19579, []int{0}
+	Users map[string]*Password `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
 }
 
-func (m *ProtoDB) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_ProtoDB.Unmarshal(m, b)
-}
-func (m *ProtoDB) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_ProtoDB.Marshal(b, m, deterministic)
-}
-func (m *ProtoDB) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ProtoDB.Merge(m, src)
+func (x *ProtoDB) Reset() {
+	*x = ProtoDB{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_userdb_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *ProtoDB) XXX_Size() int {
-	return xxx_messageInfo_ProtoDB.Size(m)
+
+func (x *ProtoDB) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *ProtoDB) XXX_DiscardUnknown() {
-	xxx_messageInfo_ProtoDB.DiscardUnknown(m)
+
+func (*ProtoDB) ProtoMessage() {}
+
+func (x *ProtoDB) ProtoReflect() protoreflect.Message {
+	mi := &file_userdb_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_ProtoDB proto.InternalMessageInfo
+// Deprecated: Use ProtoDB.ProtoReflect.Descriptor instead.
+func (*ProtoDB) Descriptor() ([]byte, []int) {
+	return file_userdb_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *ProtoDB) GetUsers() map[string]*Password {
-	if m != nil {
-		return m.Users
+func (x *ProtoDB) GetUsers() map[string]*Password {
+	if x != nil {
+		return x.Users
 	}
 	return nil
 }
 
 type Password struct {
-	// Types that are valid to be assigned to Scheme:
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Types that are assignable to Scheme:
 	//	*Password_Scrypt
 	//	*Password_Plain
-	Scheme               isPassword_Scheme `protobuf_oneof:"scheme"`
-	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
-	XXX_unrecognized     []byte            `json:"-"`
-	XXX_sizecache        int32             `json:"-"`
+	Scheme isPassword_Scheme `protobuf_oneof:"scheme"`
 }
 
-func (m *Password) Reset()         { *m = Password{} }
-func (m *Password) String() string { return proto.CompactTextString(m) }
-func (*Password) ProtoMessage()    {}
-func (*Password) Descriptor() ([]byte, []int) {
-	return fileDescriptor_1492f046cfa19579, []int{1}
+func (x *Password) Reset() {
+	*x = Password{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_userdb_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *Password) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Password.Unmarshal(m, b)
+func (x *Password) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Password) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Password.Marshal(b, m, deterministic)
+
+func (*Password) ProtoMessage() {}
+
+func (x *Password) ProtoReflect() protoreflect.Message {
+	mi := &file_userdb_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
-func (m *Password) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Password.Merge(m, src)
+
+// Deprecated: Use Password.ProtoReflect.Descriptor instead.
+func (*Password) Descriptor() ([]byte, []int) {
+	return file_userdb_proto_rawDescGZIP(), []int{1}
 }
-func (m *Password) XXX_Size() int {
-	return xxx_messageInfo_Password.Size(m)
+
+func (m *Password) GetScheme() isPassword_Scheme {
+	if m != nil {
+		return m.Scheme
+	}
+	return nil
 }
-func (m *Password) XXX_DiscardUnknown() {
-	xxx_messageInfo_Password.DiscardUnknown(m)
+
+func (x *Password) GetScrypt() *Scrypt {
+	if x, ok := x.GetScheme().(*Password_Scrypt); ok {
+		return x.Scrypt
+	}
+	return nil
 }
 
-var xxx_messageInfo_Password proto.InternalMessageInfo
+func (x *Password) GetPlain() *Plain {
+	if x, ok := x.GetScheme().(*Password_Plain); ok {
+		return x.Plain
+	}
+	return nil
+}
 
 type isPassword_Scheme interface {
 	isPassword_Scheme()
@@ -110,182 +152,283 @@ func (*Password_Scrypt) isPassword_Scheme() {}
 
 func (*Password_Plain) isPassword_Scheme() {}
 
-func (m *Password) GetScheme() isPassword_Scheme {
-	if m != nil {
-		return m.Scheme
+type Scrypt struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	LogN      uint64 `protobuf:"varint,1,opt,name=logN,proto3" json:"logN,omitempty"`
+	R         int32  `protobuf:"varint,2,opt,name=r,proto3" json:"r,omitempty"`
+	P         int32  `protobuf:"varint,3,opt,name=p,proto3" json:"p,omitempty"`
+	KeyLen    int32  `protobuf:"varint,4,opt,name=keyLen,proto3" json:"keyLen,omitempty"`
+	Salt      []byte `protobuf:"bytes,5,opt,name=salt,proto3" json:"salt,omitempty"`
+	Encrypted []byte `protobuf:"bytes,6,opt,name=encrypted,proto3" json:"encrypted,omitempty"`
+}
+
+func (x *Scrypt) Reset() {
+	*x = Scrypt{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_userdb_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
 	}
-	return nil
 }
 
-func (m *Password) GetScrypt() *Scrypt {
-	if x, ok := m.GetScheme().(*Password_Scrypt); ok {
-		return x.Scrypt
-	}
-	return nil
+func (x *Scrypt) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
 
-func (m *Password) GetPlain() *Plain {
-	if x, ok := m.GetScheme().(*Password_Plain); ok {
-		return x.Plain
-	}
-	return nil
-}
+func (*Scrypt) ProtoMessage() {}
 
-// XXX_OneofWrappers is for the internal use of the proto package.
-func (*Password) XXX_OneofWrappers() []interface{} {
-	return []interface{}{
-		(*Password_Scrypt)(nil),
-		(*Password_Plain)(nil),
+func (x *Scrypt) ProtoReflect() protoreflect.Message {
+	mi := &file_userdb_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
 	}
+	return mi.MessageOf(x)
 }
 
-type Scrypt struct {
-	LogN                 uint64   `protobuf:"varint,1,opt,name=logN,proto3" json:"logN,omitempty"`
-	R                    int32    `protobuf:"varint,2,opt,name=r,proto3" json:"r,omitempty"`
-	P                    int32    `protobuf:"varint,3,opt,name=p,proto3" json:"p,omitempty"`
-	KeyLen               int32    `protobuf:"varint,4,opt,name=keyLen,proto3" json:"keyLen,omitempty"`
-	Salt                 []byte   `protobuf:"bytes,5,opt,name=salt,proto3" json:"salt,omitempty"`
-	Encrypted            []byte   `protobuf:"bytes,6,opt,name=encrypted,proto3" json:"encrypted,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *Scrypt) Reset()         { *m = Scrypt{} }
-func (m *Scrypt) String() string { return proto.CompactTextString(m) }
-func (*Scrypt) ProtoMessage()    {}
+// Deprecated: Use Scrypt.ProtoReflect.Descriptor instead.
 func (*Scrypt) Descriptor() ([]byte, []int) {
-	return fileDescriptor_1492f046cfa19579, []int{2}
+	return file_userdb_proto_rawDescGZIP(), []int{2}
 }
 
-func (m *Scrypt) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Scrypt.Unmarshal(m, b)
-}
-func (m *Scrypt) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Scrypt.Marshal(b, m, deterministic)
-}
-func (m *Scrypt) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Scrypt.Merge(m, src)
-}
-func (m *Scrypt) XXX_Size() int {
-	return xxx_messageInfo_Scrypt.Size(m)
-}
-func (m *Scrypt) XXX_DiscardUnknown() {
-	xxx_messageInfo_Scrypt.DiscardUnknown(m)
-}
-
-var xxx_messageInfo_Scrypt proto.InternalMessageInfo
-
-func (m *Scrypt) GetLogN() uint64 {
-	if m != nil {
-		return m.LogN
+func (x *Scrypt) GetLogN() uint64 {
+	if x != nil {
+		return x.LogN
 	}
 	return 0
 }
 
-func (m *Scrypt) GetR() int32 {
-	if m != nil {
-		return m.R
+func (x *Scrypt) GetR() int32 {
+	if x != nil {
+		return x.R
 	}
 	return 0
 }
 
-func (m *Scrypt) GetP() int32 {
-	if m != nil {
-		return m.P
+func (x *Scrypt) GetP() int32 {
+	if x != nil {
+		return x.P
 	}
 	return 0
 }
 
-func (m *Scrypt) GetKeyLen() int32 {
-	if m != nil {
-		return m.KeyLen
+func (x *Scrypt) GetKeyLen() int32 {
+	if x != nil {
+		return x.KeyLen
 	}
 	return 0
 }
 
-func (m *Scrypt) GetSalt() []byte {
-	if m != nil {
-		return m.Salt
+func (x *Scrypt) GetSalt() []byte {
+	if x != nil {
+		return x.Salt
 	}
 	return nil
 }
 
-func (m *Scrypt) GetEncrypted() []byte {
-	if m != nil {
-		return m.Encrypted
+func (x *Scrypt) GetEncrypted() []byte {
+	if x != nil {
+		return x.Encrypted
 	}
 	return nil
 }
 
 type Plain struct {
-	Password             []byte   `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *Plain) Reset()         { *m = Plain{} }
-func (m *Plain) String() string { return proto.CompactTextString(m) }
-func (*Plain) ProtoMessage()    {}
-func (*Plain) Descriptor() ([]byte, []int) {
-	return fileDescriptor_1492f046cfa19579, []int{3}
+	Password []byte `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"`
 }
 
-func (m *Plain) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Plain.Unmarshal(m, b)
-}
-func (m *Plain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Plain.Marshal(b, m, deterministic)
-}
-func (m *Plain) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Plain.Merge(m, src)
+func (x *Plain) Reset() {
+	*x = Plain{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_userdb_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *Plain) XXX_Size() int {
-	return xxx_messageInfo_Plain.Size(m)
+
+func (x *Plain) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Plain) XXX_DiscardUnknown() {
-	xxx_messageInfo_Plain.DiscardUnknown(m)
+
+func (*Plain) ProtoMessage() {}
+
+func (x *Plain) ProtoReflect() protoreflect.Message {
+	mi := &file_userdb_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Plain proto.InternalMessageInfo
+// Deprecated: Use Plain.ProtoReflect.Descriptor instead.
+func (*Plain) Descriptor() ([]byte, []int) {
+	return file_userdb_proto_rawDescGZIP(), []int{3}
+}
 
-func (m *Plain) GetPassword() []byte {
-	if m != nil {
-		return m.Password
+func (x *Plain) GetPassword() []byte {
+	if x != nil {
+		return x.Password
 	}
 	return nil
 }
 
-func init() {
-	proto.RegisterType((*ProtoDB)(nil), "userdb.ProtoDB")
-	proto.RegisterMapType((map[string]*Password)(nil), "userdb.ProtoDB.UsersEntry")
-	proto.RegisterType((*Password)(nil), "userdb.Password")
-	proto.RegisterType((*Scrypt)(nil), "userdb.Scrypt")
-	proto.RegisterType((*Plain)(nil), "userdb.Plain")
-}
-
-func init() { proto.RegisterFile("userdb.proto", fileDescriptor_1492f046cfa19579) }
-
-var fileDescriptor_1492f046cfa19579 = []byte{
-	// 292 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x41, 0x4b, 0xc3, 0x40,
-	0x10, 0x85, 0xbb, 0x6d, 0x77, 0x6d, 0xa7, 0x51, 0xca, 0x1c, 0x64, 0x29, 0x1e, 0x42, 0x44, 0xc9,
-	0x29, 0x48, 0xbd, 0x88, 0xc7, 0xa2, 0x50, 0x44, 0x44, 0x56, 0xfc, 0x01, 0xa9, 0x59, 0x54, 0x1a,
-	0x93, 0x65, 0x37, 0x55, 0x72, 0xf5, 0xe2, 0xdf, 0x96, 0x9d, 0x6c, 0xd3, 0xdb, 0xbc, 0xef, 0xcd,
-	0xbc, 0x99, 0x65, 0x21, 0xda, 0x39, 0x6d, 0x8b, 0x4d, 0x66, 0x6c, 0xdd, 0xd4, 0x28, 0x3a, 0x95,
-	0xfc, 0x31, 0x38, 0x7a, 0xf6, 0xe4, 0x6e, 0x85, 0x57, 0xc0, 0x3d, 0x75, 0x92, 0xc5, 0xa3, 0x74,
-	0xb6, 0x5c, 0x64, 0x61, 0x22, 0xf8, 0xd9, 0xab, 0x37, 0xef, 0xab, 0xc6, 0xb6, 0xaa, 0x6b, 0x5c,
-	0x3c, 0x00, 0x1c, 0x20, 0xce, 0x61, 0xb4, 0xd5, 0xad, 0x64, 0x31, 0x4b, 0xa7, 0xca, 0x97, 0x78,
-	0x09, 0xfc, 0x3b, 0x2f, 0x77, 0x5a, 0x0e, 0x63, 0x96, 0xce, 0x96, 0xf3, 0x3e, 0x31, 0x77, 0xee,
-	0xa7, 0xb6, 0x85, 0xea, 0xec, 0xdb, 0xe1, 0x0d, 0x4b, 0x34, 0x4c, 0xf6, 0x18, 0x53, 0x10, 0xee,
-	0xcd, 0xb6, 0xa6, 0x09, 0x83, 0x27, 0xfb, 0xc1, 0x17, 0xa2, 0xeb, 0x81, 0x0a, 0x3e, 0x5e, 0x00,
-	0x37, 0x65, 0xfe, 0x59, 0xc9, 0x11, 0x35, 0x1e, 0xf7, 0x1b, 0x3c, 0x5c, 0x0f, 0x54, 0xe7, 0xae,
-	0x26, 0x3e, 0xf0, 0x43, 0x7f, 0xe9, 0xe4, 0x97, 0x81, 0xe8, 0x52, 0x10, 0x61, 0x5c, 0xd6, 0xef,
-	0x4f, 0x74, 0xf0, 0x58, 0x51, 0x8d, 0x11, 0x30, 0x4b, 0x4b, 0xb9, 0x62, 0xd6, 0x2b, 0x43, 0xc9,
-	0x5c, 0x31, 0x83, 0xa7, 0x20, 0xb6, 0xba, 0x7d, 0xd4, 0x95, 0x1c, 0x13, 0x0a, 0xca, 0xe7, 0xb8,
-	0xbc, 0x6c, 0x24, 0x8f, 0x59, 0x1a, 0x29, 0xaa, 0xf1, 0x0c, 0xa6, 0xba, 0xa2, 0x35, 0xba, 0x90,
-	0x82, 0x8c, 0x03, 0x48, 0xce, 0x81, 0xd3, 0x81, 0xb8, 0x80, 0x89, 0x09, 0x8f, 0xa6, 0x33, 0x22,
-	0xd5, 0xeb, 0x8d, 0xa0, 0x9f, 0xba, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xe4, 0x93, 0xae, 0x19,
-	0xb9, 0x01, 0x00, 0x00,
+var File_userdb_proto protoreflect.FileDescriptor
+
+var file_userdb_proto_rawDesc = []byte{
+	0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x64, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06,
+	0x75, 0x73, 0x65, 0x72, 0x64, 0x62, 0x22, 0x87, 0x01, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+	0x44, 0x42, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x1a, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x64, 0x62, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+	0x44, 0x42, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x75,
+	0x73, 0x65, 0x72, 0x73, 0x1a, 0x4a, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74,
+	0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x64, 0x62, 0x2e, 0x50, 0x61, 0x73,
+	0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
+	0x22, 0x65, 0x0a, 0x08, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x28, 0x0a, 0x06,
+	0x73, 0x63, 0x72, 0x79, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x75,
+	0x73, 0x65, 0x72, 0x64, 0x62, 0x2e, 0x53, 0x63, 0x72, 0x79, 0x70, 0x74, 0x48, 0x00, 0x52, 0x06,
+	0x73, 0x63, 0x72, 0x79, 0x70, 0x74, 0x12, 0x25, 0x0a, 0x05, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x64, 0x62, 0x2e, 0x50,
+	0x6c, 0x61, 0x69, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x42, 0x08, 0x0a,
+	0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x06, 0x53, 0x63, 0x72, 0x79,
+	0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
+	0x52, 0x04, 0x6c, 0x6f, 0x67, 0x4e, 0x12, 0x0c, 0x0a, 0x01, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x01, 0x72, 0x12, 0x0c, 0x0a, 0x01, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x01, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x4c, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01,
+	0x28, 0x05, 0x52, 0x06, 0x6b, 0x65, 0x79, 0x4c, 0x65, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x61,
+	0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x61, 0x6c, 0x74, 0x12, 0x1c,
+	0x0a, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
+	0x0c, 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x22, 0x23, 0x0a, 0x05,
+	0x50, 0x6c, 0x61, 0x69, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
+	0x64, 0x42, 0x2c, 0x5a, 0x2a, 0x62, 0x6c, 0x69, 0x74, 0x69, 0x72, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x2e, 0x61, 0x72, 0x2f, 0x67, 0x6f, 0x2f, 0x63, 0x68, 0x61, 0x73, 0x71, 0x75, 0x69, 0x64, 0x2f,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x64, 0x62, 0x62,
+	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_userdb_proto_rawDescOnce sync.Once
+	file_userdb_proto_rawDescData = file_userdb_proto_rawDesc
+)
+
+func file_userdb_proto_rawDescGZIP() []byte {
+	file_userdb_proto_rawDescOnce.Do(func() {
+		file_userdb_proto_rawDescData = protoimpl.X.CompressGZIP(file_userdb_proto_rawDescData)
+	})
+	return file_userdb_proto_rawDescData
+}
+
+var file_userdb_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
+var file_userdb_proto_goTypes = []interface{}{
+	(*ProtoDB)(nil),  // 0: userdb.ProtoDB
+	(*Password)(nil), // 1: userdb.Password
+	(*Scrypt)(nil),   // 2: userdb.Scrypt
+	(*Plain)(nil),    // 3: userdb.Plain
+	nil,              // 4: userdb.ProtoDB.UsersEntry
+}
+var file_userdb_proto_depIdxs = []int32{
+	4, // 0: userdb.ProtoDB.users:type_name -> userdb.ProtoDB.UsersEntry
+	2, // 1: userdb.Password.scrypt:type_name -> userdb.Scrypt
+	3, // 2: userdb.Password.plain:type_name -> userdb.Plain
+	1, // 3: userdb.ProtoDB.UsersEntry.value:type_name -> userdb.Password
+	4, // [4:4] is the sub-list for method output_type
+	4, // [4:4] is the sub-list for method input_type
+	4, // [4:4] is the sub-list for extension type_name
+	4, // [4:4] is the sub-list for extension extendee
+	0, // [0:4] is the sub-list for field type_name
+}
+
+func init() { file_userdb_proto_init() }
+func file_userdb_proto_init() {
+	if File_userdb_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_userdb_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ProtoDB); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_userdb_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Password); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_userdb_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Scrypt); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_userdb_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Plain); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	file_userdb_proto_msgTypes[1].OneofWrappers = []interface{}{
+		(*Password_Scrypt)(nil),
+		(*Password_Plain)(nil),
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_userdb_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   5,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_userdb_proto_goTypes,
+		DependencyIndexes: file_userdb_proto_depIdxs,
+		MessageInfos:      file_userdb_proto_msgTypes,
+	}.Build()
+	File_userdb_proto = out.File
+	file_userdb_proto_rawDesc = nil
+	file_userdb_proto_goTypes = nil
+	file_userdb_proto_depIdxs = nil
 }
diff --git a/internal/userdb/userdb.proto b/internal/userdb/userdb.proto
index ca663e3..b2a536c 100644
--- a/internal/userdb/userdb.proto
+++ b/internal/userdb/userdb.proto
@@ -2,6 +2,7 @@
 syntax = "proto3";
 
 package userdb;
+option go_package = "blitiri.com.ar/go/chasquid/internal/userdb";
 
 message ProtoDB {
 	map<string, Password> users = 1;