-
Notifications
You must be signed in to change notification settings - Fork 0
/
email.go
201 lines (159 loc) · 5.81 KB
/
email.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
package directadmin
import (
"errors"
"fmt"
"net/http"
"net/url"
"github.com/spf13/cast"
)
type EmailAccount struct {
DiskQuota int `json:"diskQuota" yaml:"diskQuota"`
DiskUsage int `json:"diskUsage" yaml:"diskUsage"`
Domain string `json:"domain" yaml:"domain"`
Password string `json:"password" yaml:"password"`
SendQuota int `json:"sendQuota" yaml:"sendQuota"`
SendUsage int `json:"sendUsage" yaml:"sendUsage"`
Suspended bool `json:"suspended" yaml:"suspended"`
Username string `json:"username" yaml:"username"`
}
func (c *UserContext) CreateEmailAccount(emailAccount EmailAccount) error {
var response apiGenericResponse
body := url.Values{}
body.Set("domain", emailAccount.Domain)
body.Set("user", emailAccount.Username)
body.Set("passwd", emailAccount.Password)
body.Set("passwd2", emailAccount.Password)
body.Set("quota", cast.ToString(emailAccount.DiskQuota))
body.Set("limit", cast.ToString(emailAccount.SendQuota))
if _, err := c.makeRequestOld(http.MethodPost, "API_POP?action=create", body, &response); err != nil {
return err
}
if response.Success != "Email account created" {
return fmt.Errorf("failed to create email account: %v", response.Result)
}
return nil
}
func (c *UserContext) DeleteEmailAccount(domain string, name string) error {
var response apiGenericResponse
body := url.Values{}
body.Set("domain", domain)
body.Set("user", name)
if _, err := c.makeRequestOld(http.MethodPost, "API_POP?action=delete", body, &response); err != nil {
return err
}
if response.Success != "E-Mail Accounts Deleted" {
return fmt.Errorf("failed to delete email account: %v", response.Result)
}
return nil
}
// GetEmailAccounts (user) returns an array of email accounts belonging to the provided domain
func (c *UserContext) GetEmailAccounts(domain string) ([]EmailAccount, error) {
var emailAccounts []EmailAccount
rawEmailAccounts := struct {
EmailAccounts map[string]struct {
Sent any `json:"sent"`
Suspended string `json:"suspended"`
Usage struct {
DiskQuota string `json:"quota"`
DiskUsage string `json:"usage"`
} `json:"usage"`
Username string `json:"account"`
} `json:"emails"`
}{}
if _, err := c.makeRequestOld(http.MethodGet, "EMAIL_POP?bytes=yes&domain="+domain, nil, &rawEmailAccounts); err != nil {
return nil, err
}
for id, emailAccount := range rawEmailAccounts.EmailAccounts {
if id != "info" {
email := EmailAccount{
DiskQuota: cast.ToInt(emailAccount.Usage.DiskQuota),
DiskUsage: cast.ToInt(emailAccount.Usage.DiskUsage),
Domain: domain,
Suspended: parseOnOff(emailAccount.Suspended),
Username: emailAccount.Username,
}
// this is necessary because DA either returns a string, or a map with the disk usage in a "usage" field depending on which usage endpoint we hit
switch emailAccount.Sent.(type) {
case map[string]any:
emailAccountSent := emailAccount.Sent.(map[string]any)
email.SendQuota = cast.ToInt(emailAccountSent["send_limit"])
email.SendUsage = cast.ToInt(emailAccountSent["sent"])
}
emailAccounts = append(emailAccounts, email)
}
}
if len(emailAccounts) == 0 {
return nil, errors.New("no email accounts were found")
}
return emailAccounts, nil
}
func (c *UserContext) ToggleDKIM(domain string, status bool) error {
var response apiGenericResponse
body := url.Values{}
body.Set("action", "set_dkim")
body.Set("domain", domain)
if status {
body.Set("enable", "yes")
} else {
body.Set("disable", "yes")
}
if _, err := c.makeRequestOld(http.MethodPost, "API_EMAIL_POP", body, &response); err != nil {
return err
}
if response.Success != "Success" {
return fmt.Errorf("failed to toggle DKIM state: %v", response.Result)
}
return nil
}
func (c *UserContext) UpdateEmailAccount(emailAccount EmailAccount) error {
var response apiGenericResponse
body := url.Values{}
body.Set("domain", emailAccount.Domain)
body.Set("user", emailAccount.Username)
body.Set("passwd", emailAccount.Password)
body.Set("passwd2", emailAccount.Password)
body.Set("quota", cast.ToString(emailAccount.DiskQuota))
body.Set("limit", cast.ToString(emailAccount.SendQuota))
if _, err := c.makeRequestOld(http.MethodPost, "API_POP?action=modify", body, &response); err != nil {
return err
}
if response.Success != "Account password changed" {
return fmt.Errorf("failed to update email account: %v", response.Result)
}
return nil
}
// UseInternalMailHandler tells the server to use the local mail handler for the given domain. If this is enabled, other
// domains on the server that email this domain will use the server's local mail handler to deliver the email, rather
// than looking up the domain's MX records. This is fine if your email is being hosted on the same server, but not
// otherwise.
func (c *UserContext) UseInternalMailHandler(domain string, enable bool) error {
var response apiGenericResponse
body := url.Values{}
body.Set("domain", domain)
if enable {
body.Set("internal", "yes")
} else {
body.Set("internal", "no")
}
if _, err := c.makeRequestOld(http.MethodPost, "API_DNS_MX?action=internal", body, &response); err != nil {
return err
}
if response.Success != "Option Saved" {
return fmt.Errorf("failed to set internal mail handler for %v: %v", domain, response.Result)
}
return nil
}
// VerifyEmailAccount (user) accepts the full email address as well as the password for the account. If the credentials aren't correct, an error will be returned.
func (c *UserContext) VerifyEmailAccount(address string, password string) error {
var response apiGenericResponse
body := url.Values{}
body.Set("email", address)
body.Set("passwd", password)
if _, err := c.makeRequestOld(http.MethodPost, "API_EMAIL_AUTH", body, &response); err != nil {
return err
}
if response.Success != "Password Correct" {
return errors.New("credentials incorrect")
}
return nil
}