-
Notifications
You must be signed in to change notification settings - Fork 3
/
client.go
128 lines (105 loc) · 3.08 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package server
import (
"crypto/tls"
"crypto/x509"
"fmt"
"github.com/arnisoph/postisto/pkg/log"
imapClientPkg "github.com/emersion/go-imap/client"
"github.com/pkg/errors"
"io/ioutil"
"os"
)
type Connection struct {
Server string `yaml:"server"`
Port int `yaml:"port"`
Username string `yaml:"username"`
Password string `yaml:"password"`
IMAPS bool `yaml:"imaps"`
Starttls *bool `yaml:"starttls"`
TLSVerify *bool `yaml:"tlsverify"`
TLSCACertFile string `yaml:"cacertfile"`
imapClient *imapClientPkg.Client
}
// Manually connect to the IMAP server. Usually the session to the IMAP server is re-established automatically if we're disconnected or logged out.
func (conn *Connection) Connect() error {
var imapClient *imapClientPkg.Client
var err error
log.Debugw("Connecting to IMAP server now", "username", conn.Username, "server", conn.Server)
// validate config
if err := conn.validate(); err != nil {
return err
}
// When not using IMAPS, enable STARTTLS by default
if !conn.IMAPS && conn.Starttls == nil {
var b bool
conn.Starttls = &b
*conn.Starttls = true
}
certPool := x509.NewCertPool()
if conn.TLSCACertFile != "" {
pemBytes, err := ioutil.ReadFile(conn.TLSCACertFile)
if err != nil {
log.Errorw("Failed to load CA cert file", err, "TLSCACertFile", conn.TLSCACertFile)
return err
}
certPool.AppendCertsFromPEM(pemBytes)
} else {
certPool = nil
}
tlsConfig := &tls.Config{
ServerName: conn.Server,
InsecureSkipVerify: !*conn.TLSVerify,
MinVersion: tls.VersionTLS12,
RootCAs: certPool,
}
if conn.IMAPS {
if imapClient, err = imapClientPkg.DialTLS(fmt.Sprintf("%v:%v", conn.Server, conn.Port), tlsConfig); err != nil {
log.Errorw("Failed to connect to server", err, "server", conn.Server)
return err
}
} else {
if imapClient, err = imapClientPkg.Dial(fmt.Sprintf("%v:%v", conn.Server, conn.Port)); err != nil {
log.Errorw("Failed to connect to server", err, "server", conn.Server)
return err
}
if *conn.Starttls {
if err = imapClient.StartTLS(tlsConfig); err != nil {
log.Errorw("Failed to initiate TLS session after connecting to server (STARTTLS)", err, "server", conn.Server)
return err
}
}
}
if log.GetLogLevel() == "trace" {
imapClient.SetDebug(os.Stderr)
}
if err = imapClient.Login(conn.Username, conn.Password); err != nil {
log.Errorw("Failed to login to server", err, "server", conn.Server, "username", conn.Username)
return err
}
conn.imapClient = imapClient
return err
}
func (conn *Connection) Disconnect() error {
if conn.imapClient == nil {
// no connection
return nil
}
return conn.imapClient.Logout()
}
func (conn *Connection) validate() error {
if conn.Server == "" {
return errors.Errorf("server not set in account config")
}
if conn.Port == 0 {
return errors.Errorf("port is not set in account config")
}
if conn.Username == "" {
return errors.Errorf("username not set in account config")
}
if conn.TLSVerify == nil {
var b bool
conn.TLSVerify = &b
*conn.TLSVerify = true
}
return nil
}