Rename package, don't serve IMAP

This commit is contained in:
Jarno Rankinen 2024-03-26 21:26:28 +02:00
parent 2db44c9f5d
commit fc644cbebc
17 changed files with 167 additions and 119 deletions

View File

@ -13,8 +13,8 @@ import (
"golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/nacl/secretbox"
"github.com/emersion/hydroxide/config"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/config"
"github.com/0ranki/hydroxide-push/protonmail"
)
func authFilePath() (string, error) {

View File

@ -13,10 +13,10 @@ import (
"strings"
"sync"
"github.com/0ranki/hydroxide-push/protonmail"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/emersion/go-vcard"
"github.com/emersion/go-webdav/carddav"
"github.com/emersion/hydroxide/protonmail"
)
// TODO: use a HTTP error

View File

@ -5,16 +5,15 @@ import (
"crypto/tls"
"flag"
"fmt"
"github.com/emersion/go-imap"
"github.com/0ranki/hydroxide-push/auth"
"github.com/0ranki/hydroxide-push/config"
"github.com/0ranki/hydroxide-push/events"
imapbackend "github.com/0ranki/hydroxide-push/imap"
"github.com/0ranki/hydroxide-push/ntfy"
"github.com/0ranki/hydroxide-push/protonmail"
imapserver "github.com/emersion/go-imap/server"
"github.com/emersion/hydroxide/auth"
"github.com/emersion/hydroxide/config"
"github.com/emersion/hydroxide/events"
imapbackend "github.com/emersion/hydroxide/imap"
"github.com/emersion/hydroxide/protonmail"
"golang.org/x/term"
"log"
"net"
"os"
"time"
)
@ -28,9 +27,7 @@ var (
debug bool
apiEndpoint string
appVersion string
//imapUser *backend.User
ntfyTopic string
cfg ntfy.NtfyConfig
)
func newClient() *protonmail.Client {
@ -60,7 +57,7 @@ func askPass(prompt string) ([]byte, error) {
return b, err
}
func listenAndServeIMAP(addr string, debug bool, authManager *auth.Manager, eventsManager *events.Manager, tlsConfig *tls.Config) error {
func listenEventsAndNotify(addr string, debug bool, authManager *auth.Manager, eventsManager *events.Manager, tlsConfig *tls.Config) error {
be := imapbackend.New(authManager, eventsManager)
s := imapserver.New(be)
s.Addr = addr
@ -69,53 +66,19 @@ func listenAndServeIMAP(addr string, debug bool, authManager *auth.Manager, even
if debug {
s.Debug = os.Stdout
}
if s.TLSConfig != nil {
log.Println("IMAP server listening with TLS on", s.Addr)
return s.ListenAndServeTLS()
ntfy.Login(&cfg, be)
log.Println("Listening for events", s.Addr)
for {
time.Sleep(10 * time.Second)
}
go func() {
time.Sleep(1 * time.Second)
c, _ := net.ResolveIPAddr("ip", "127.0.0.1")
conn := imap.ConnInfo{
RemoteAddr: c,
LocalAddr: c,
TLS: nil,
}
usernames, err := auth.ListUsernames()
if err != nil {
log.Fatal(err)
}
if len(usernames) > 1 {
log.Fatal("only one login supported for now")
}
if len(usernames) == 0 {
executable, _ := os.Executable()
log.Fatal("login first using " + executable + " auth <protonmail username>")
}
// TODO: bridge password
_, err = be.Login(&conn, usernames[0], os.Getenv("HYDROXIDE_BRIDGE_PASS"))
if err != nil {
log.Fatal(err)
}
}()
log.Println("IMAP server listening on", s.Addr)
return s.ListenAndServe()
return nil
}
const usage = `usage: hydroxide [options...] <command>
const usage = `usage: hydroxide-push [options...] <command>
Commands:
auth <username> Login to ProtonMail via hydroxide
carddav Run hydroxide as a CardDAV server
export-secret-keys <username> Export secret keys
imap Run hydroxide as an IMAP server
import-messages <username> [file] Import messages
export-messages [options...] <username> Export messages
sendmail <username> -- <args...> sendmail(1) interface
serve Run all servers
smtp Run hydroxide as an SMTP server
status View hydroxide status
notify Start the notification daemon
Global options:
-debug
@ -124,30 +87,6 @@ Global options:
ProtonMail API endpoint
-app-version <version>
ProtonMail application version
-smtp-host example.com
Allowed SMTP email hostname on which hydroxide listens, defaults to 127.0.0.1
-imap-host example.com
Allowed IMAP email hostname on which hydroxide listens, defaults to 127.0.0.1
-carddav-host example.com
Allowed SMTP email hostname on which hydroxide listens, defaults to 127.0.0.1
-smtp-port example.com
SMTP port on which hydroxide listens, defaults to 1025
-imap-port example.com
IMAP port on which hydroxide listens, defaults to 1143
-carddav-port example.com
CardDAV port on which hydroxide listens, defaults to 8080
-disable-imap
Disable IMAP for hydroxide serve
-disable-smtp
Disable SMTP for hydroxide serve
-disable-carddav
Disable CardDAV for hydroxide serve
-tls-cert /path/to/cert.pem
Path to the certificate to use for incoming connections (Optional)
-tls-key /path/to/key.pem
Path to the certificate key to use for incoming connections (Optional)
-tls-client-ca /path/to/ca.pem
If set, clients must provide a certificate signed by the given CA (Optional)
Environment variables:
HYDROXIDE_BRIDGE_PASS Don't prompt for the bridge password, use this variable instead
@ -157,10 +96,6 @@ func main() {
flag.BoolVar(&debug, "debug", false, "Enable debug logs")
flag.StringVar(&apiEndpoint, "api-endpoint", defaultAPIEndpoint, "ProtonMail API endpoint")
flag.StringVar(&appVersion, "app-version", defaultAppVersion, "ProtonMail app version")
flag.StringVar(&ntfyTopic, "topic", "", "ntfy.sh/NextPush topic to push notifications to")
imapHost := "127.0.0.1" // flag.String("imap-host", "127.0.0.1", "Allowed IMAP email hostname on which hydroxide listens, defaults to 127.0.0.1")
imapPort := "1143" // flag.String("imap-port", "1143", "IMAP port on which hydroxide listens, defaults to 1143")
tlsCert := flag.String("tls-cert", "", "Path to the certificate to use for incoming connections")
tlsCertKey := flag.String("tls-key", "", "Path to the certificate key to use for incoming connections")
@ -294,16 +229,24 @@ func main() {
}
case "setup-ntfy":
case "notify":
if ntfyTopic == "" {
log.Fatal("please set ntfy.sh topic using --topic")
scanner := bufio.NewScanner(os.Stdin)
fmt.Printf("Input push server URL (e.g. 'http://ntfy.sh') : ")
scanner.Scan()
cfg.URL = scanner.Text()
scanner = bufio.NewScanner(os.Stdin)
fmt.Printf("Input push topic (e.g. my-proton-notifications)\nLeave blank to generate a random one: ")
scanner.Scan()
cfg.Topic = scanner.Text()
fmt.Printf("Using URL %s\n", cfg.String())
err = cfg.Save()
if err != nil {
log.Fatal(err)
}
addr := imapHost + ":" + imapPort
log.Println("Notification configuration saved")
case "notify":
authManager := auth.NewManager(newClient)
eventsManager := events.NewManager()
log.Fatal(listenAndServeIMAP(addr, debug, authManager, eventsManager, tlsConfig))
log.Fatal(listenEventsAndNotify("0", debug, authManager, eventsManager, tlsConfig))
default:
fmt.Print(usage)

View File

@ -18,15 +18,15 @@ import (
"github.com/emersion/go-smtp"
"golang.org/x/term"
"github.com/emersion/hydroxide/auth"
"github.com/emersion/hydroxide/carddav"
"github.com/emersion/hydroxide/config"
"github.com/emersion/hydroxide/events"
"github.com/emersion/hydroxide/exports"
imapbackend "github.com/emersion/hydroxide/imap"
"github.com/emersion/hydroxide/imports"
"github.com/emersion/hydroxide/protonmail"
smtpbackend "github.com/emersion/hydroxide/smtp"
"github.com/0ranki/hydroxide-push/auth"
"github.com/0ranki/hydroxide-push/carddav"
"github.com/0ranki/hydroxide-push/config"
"github.com/0ranki/hydroxide-push/events"
"github.com/0ranki/hydroxide-push/exports"
imapbackend "github.com/0ranki/hydroxide-push/imap"
"github.com/0ranki/hydroxide-push/imports"
"github.com/0ranki/hydroxide-push/protonmail"
smtpbackend "github.com/0ranki/hydroxide-push/smtp"
)
const (

View File

@ -5,7 +5,7 @@ import (
"sync"
"time"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/protonmail"
)
const pollInterval = 10 * time.Second

View File

@ -12,7 +12,7 @@ import (
"github.com/emersion/go-message/mail"
"github.com/emersion/go-message/textproto"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/protonmail"
)
func writeMessage(c *protonmail.Client, privateKeys openpgp.KeyRing, w io.Writer, msg *protonmail.Message) error {

3
go.mod
View File

@ -1,4 +1,4 @@
module github.com/emersion/hydroxide
module github.com/0ranki/hydroxide-push
go 1.13
@ -14,6 +14,7 @@ require (
github.com/emersion/go-smtp v0.19.0
github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9
github.com/emersion/go-webdav v0.3.2-0.20220524091811-5d845721d8f7
github.com/emersion/hydroxide v0.2.28
golang.org/x/crypto v0.15.0
golang.org/x/term v0.14.0
)

9
go.sum
View File

@ -1,3 +1,4 @@
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
@ -14,11 +15,14 @@ github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5N
github.com/emersion/go-mbox v1.0.3 h1:Kac75r/EGi6KZAz48HXal9q7EiaXNl+U5HZfyDz0LKM=
github.com/emersion/go-mbox v1.0.3/go.mod h1:Yp9IVuuOYLEuMv4yjgDHvhb5mHOcYH6x92Oas3QqEZI=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
github.com/emersion/go-message v0.16.0/go.mod h1:pDJDgf/xeUIF+eicT6B/hPX/ZbEorKkUMPOxrPVG2eQ=
github.com/emersion/go-message v0.17.0 h1:NIdSKHiVUx4qKqdd0HyJFD41cW8iFguM2XJnRZWQH04=
github.com/emersion/go-message v0.17.0/go.mod h1:/9Bazlb1jwUNB0npYYBsdJ2EMOiiyN3m5UVHbY7GoNw=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY=
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-smtp v0.18.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
github.com/emersion/go-smtp v0.19.0 h1:iVCDtR2/JY3RpKoaZ7u6I/sb52S3EzfNHO1fAWVHgng=
github.com/emersion/go-smtp v0.19.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY=
@ -28,11 +32,14 @@ github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9 h1:ATgqloALX6cHC
github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
github.com/emersion/go-webdav v0.3.2-0.20220524091811-5d845721d8f7 h1:HqrKOBl8HdSnlo8kz72tCU36aK3WwSmpnnz04+dD0oc=
github.com/emersion/go-webdav v0.3.2-0.20220524091811-5d845721d8f7/go.mod h1:uSM1VveeKtogBVWaYccTksToczooJ0rrVGNsgnDsr4Q=
github.com/emersion/hydroxide v0.2.28 h1:4gUyOJkVv4owVa3XHNlS/jEb+++q49O8EQR+kpO/s6w=
github.com/emersion/hydroxide v0.2.28/go.mod h1:wYHmI++eFDFxzWgWRfFFYiFpCfdZcHeLA3X1oGU2JjI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@ -57,6 +64,7 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -65,6 +73,7 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -7,8 +7,8 @@ import (
"github.com/emersion/go-imap"
imapbackend "github.com/emersion/go-imap/backend"
"github.com/emersion/hydroxide/auth"
"github.com/emersion/hydroxide/events"
"github.com/0ranki/hydroxide-push/auth"
"github.com/0ranki/hydroxide-push/events"
)
var errNotYetImplemented = errors.New("not yet implemented")

View File

@ -7,7 +7,7 @@ import (
"github.com/boltdb/bolt"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/protonmail"
)
func serializeUID(uid uint32) []byte {

View File

@ -6,8 +6,8 @@ import (
"github.com/boltdb/bolt"
"github.com/emersion/hydroxide/config"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/config"
"github.com/0ranki/hydroxide-push/protonmail"
)
var ErrNotFound = errors.New("message not found in local database")

View File

@ -10,8 +10,8 @@ import (
"github.com/emersion/go-imap"
imapbackend "github.com/emersion/go-imap/backend"
"github.com/emersion/hydroxide/imap/database"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/imap/database"
"github.com/0ranki/hydroxide-push/protonmail"
)
const delimiter = "/"

View File

@ -15,7 +15,7 @@ import (
"github.com/emersion/go-message"
"github.com/emersion/go-message/mail"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/protonmail"
)
func messageID(msg *protonmail.Message) string {

View File

@ -1,17 +1,17 @@
package imap
import (
"github.com/emersion/hydroxide/ntfy"
"github.com/0ranki/hydroxide-push/ntfy"
"log"
"strings"
"sync"
"github.com/0ranki/hydroxide-push/events"
"github.com/0ranki/hydroxide-push/imap/database"
"github.com/0ranki/hydroxide-push/protonmail"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/emersion/go-imap"
imapbackend "github.com/emersion/go-imap/backend"
"github.com/emersion/hydroxide/events"
"github.com/emersion/hydroxide/imap/database"
"github.com/emersion/hydroxide/protonmail"
)
var systemMailboxes = []struct {
@ -118,7 +118,7 @@ func newUser(be *backend, username string, c *protonmail.Client, privateKeys ope
go uu.receiveEvents(be.updates, ch)
uu.eventsReceiver = be.eventsManager.Register(c, u.Name, ch, done)
log.Printf("User %q logged in via IMAP", u.Name)
log.Printf("Logged in as user %q", u.Name)
return uu, nil
}

View File

@ -8,7 +8,7 @@ import (
"github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/emersion/go-message/mail"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/protonmail"
)
func ImportMessage(c *protonmail.Client, r io.Reader) error {

View File

@ -1,10 +1,46 @@
package ntfy
import (
"bufio"
"encoding/json"
"fmt"
"github.com/0ranki/hydroxide-push/auth"
"github.com/0ranki/hydroxide-push/config"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/backend"
"log"
"net"
"net/http"
"os"
"strings"
)
type NtfyConfig struct {
URL string `json:"url"`
Topic string `json:"topic"`
BridgePw string `json:"bridgePw"`
}
func (cfg *NtfyConfig) String() string {
return fmt.Sprintf("%s/%s", cfg.URL, cfg.Topic)
}
func (cfg *NtfyConfig) Save() error {
b, err := json.Marshal(cfg)
if err != nil {
return err
}
path, err := ntfyConfigFile()
if err != nil {
return err
}
return os.WriteFile(path, b, 0600)
}
func ntfyConfigFile() (string, error) {
return config.Path("notify.json")
}
func Notify() {
req, _ := http.NewRequest("POST", "https://push.oranki.net/testing20240325", strings.NewReader("New message received"))
req.Header.Set("Title", "ProtoMail")
@ -12,3 +48,62 @@ func Notify() {
req.Header.Set("Tags", "envelope")
http.DefaultClient.Do(req)
}
func (cfg *NtfyConfig) Read() error {
f, err := ntfyConfigFile()
if err == nil {
b, err := os.ReadFile(f)
if err == nil {
err = json.Unmarshal(b, &cfg)
}
if err != nil {
return err
}
}
return nil
}
func Login(cfg *NtfyConfig, be backend.Backend) {
//time.Sleep(1 * time.Second)
c, _ := net.ResolveIPAddr("ip", "127.0.0.1")
conn := imap.ConnInfo{
RemoteAddr: c,
LocalAddr: c,
TLS: nil,
}
usernames, err := auth.ListUsernames()
if err != nil {
log.Fatal(err)
}
if len(usernames) > 1 {
log.Fatal("only one login supported for now")
}
err = cfg.Read()
if err != nil {
log.Println(err)
}
if len(usernames) == 0 || cfg.URL == "" || cfg.Topic == "" {
executable, _ := os.Executable()
log.Println("login first using " + executable + " auth <protonmail username>")
log.Fatalln("then setup ntfy using " + executable + "setup-ntfy")
}
cfg.BridgePw = os.Getenv("HYDROXIDE_BRIDGE_PASSWORD")
if cfg.BridgePw == "" {
scanner := bufio.NewScanner(os.Stdin)
fmt.Printf("Bridge password: ")
scanner.Scan()
cfg.BridgePw = scanner.Text()
scanner = bufio.NewScanner(os.Stdin)
fmt.Printf("Save password to config? The password is stored in plain text! (yes/n): ")
scanner.Scan()
if scanner.Text() == "yes" {
if err = cfg.Save(); err != nil {
log.Fatal("failed to save notification config")
}
}
}
_, err = be.Login(&conn, usernames[0], cfg.BridgePw)
if err != nil {
log.Fatal(err)
}
}

View File

@ -13,8 +13,8 @@ import (
"github.com/emersion/go-message/mail"
"github.com/emersion/go-smtp"
"github.com/emersion/hydroxide/auth"
"github.com/emersion/hydroxide/protonmail"
"github.com/0ranki/hydroxide-push/auth"
"github.com/0ranki/hydroxide-push/protonmail"
)
func toPMAddressList(addresses []*mail.Address) []*protonmail.MessageAddress {