Skip to content

Commit acde169

Browse files
committed
provider,resource_smtp_credential: Support configuring SMTP credentials
- https://improvmx.com/api/#smtp-list
1 parent cfc9b8e commit acde169

File tree

4 files changed

+147
-3
lines changed

4 files changed

+147
-3
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ A very nascent Terraform provider for configuring [ImprovMX](https://improvmx.co
1212
- Delete an email forward.
1313
- Import an email forward.
1414
- Update an email forward (ImprovMX allows updating an email forward to send to more than one address, ie `[email protected],[email protected]`).
15+
- Create, update and delete a domain's SMTP credentials.
1516

1617
## Usage
1718

1819
```hcl
1920
terraform {
2021
required_providers {
2122
improvmx = {
22-
source = "issyl0/improvmx"
23+
source = "issyl0/improvmx"
2324
}
2425
}
2526
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# `improvmx_smtp_credential` Resource
2+
3+
A resource to create ImprovMX domain SMTP credentials.
4+
5+
## Example Usage
6+
7+
```hcl
8+
resource "improvmx_email_forward" "example" {
9+
domain = "example.com"
10+
username = "example"
11+
password = var.password
12+
}
13+
```
14+
15+
## Argument Reference
16+
17+
* `domain` - (Required) Name of the domain.
18+
* `username` - (Required) Username of the SMTP sender.
19+
* `password` - (Required) Password for the SMTP sending account.

improvmx/provider.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ type Meta struct {
1515

1616
func Provider() *schema.Provider {
1717
p := &schema.Provider{
18-
Schema: map[string]*schema.Schema{"token": {Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("IMPROVMX_API_TOKEN", nil), Description: "The API token for API operations."}},
19-
ResourcesMap: map[string]*schema.Resource{"improvmx_domain": resourceDomain(), "improvmx_email_forward": resourceEmailForward()},
18+
Schema: map[string]*schema.Schema{"token": {Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("IMPROVMX_API_TOKEN", nil), Description: "The API token for API operations."}},
19+
ResourcesMap: map[string]*schema.Resource{
20+
"improvmx_domain": resourceDomain(),
21+
"improvmx_email_forward": resourceEmailForward(),
22+
"improvmx_smtp_credential": resourceSMTPCredential(),
23+
},
2024
DataSourcesMap: map[string]*schema.Resource{},
2125
ProviderMetaSchema: map[string]*schema.Schema{},
2226
}

improvmx/resource_smtp_credential.go

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package improvmx
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"time"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
)
10+
11+
func resourceSMTPCredential() *schema.Resource {
12+
return &schema.Resource{
13+
Create: resourceSMTPCredentialCreate,
14+
Read: resourceSMTPCredentialRead,
15+
Update: resourceSMTPCredentialUpdate,
16+
Delete: resourceSMTPCredentialDelete,
17+
18+
Schema: map[string]*schema.Schema{
19+
"domain": {
20+
Type: schema.TypeString,
21+
Required: true,
22+
},
23+
"username": {
24+
Type: schema.TypeString,
25+
Required: true,
26+
},
27+
"password": {
28+
Type: schema.TypeString,
29+
Required: true,
30+
Sensitive: true,
31+
},
32+
},
33+
}
34+
}
35+
36+
func resourceSMTPCredentialCreate(d *schema.ResourceData, meta interface{}) error {
37+
m := meta.(*Meta)
38+
39+
for {
40+
resp := m.Client.CreateSMTPCredential(d.Get("domain").(string), d.Get("username").(string), d.Get("password").(string))
41+
42+
log.Printf("[DEBUG] Got status code %v from ImprovMX API on Create for SMTP %s@%s, success: %v, errors: %v.", resp.Code, d.Get("username").(string), d.Get("domain").(string), resp.Success, resp.Errors)
43+
44+
if resp.Code == 429 {
45+
log.Printf("[DEBUG] Sleeping for 10 seconds to allow rate limit to recover.")
46+
time.Sleep(10 * time.Second)
47+
}
48+
49+
if resp.Code == 404 {
50+
log.Printf("[DEBUG] Couldn't find the resource in ImprovMX. Aborting")
51+
return fmt.Errorf("HTTP response code %d, error text: %s", resp.Code, resp.Errors.Domain)
52+
}
53+
54+
if resp.Success {
55+
return resourceSMTPCredentialRead(d, meta)
56+
}
57+
}
58+
}
59+
60+
func resourceSMTPCredentialRead(d *schema.ResourceData, meta interface{}) error {
61+
m := meta.(*Meta)
62+
m.Mutex.Lock()
63+
defer m.Mutex.Unlock()
64+
65+
for {
66+
resp := m.Client.GetSMTPCredential(d.Get("domain").(string))
67+
68+
log.Printf("[DEBUG] Got status code %v from ImprovMX API on Read for SMTP domain %s, success: %v, errors: %v.", resp.Code, d.Get("domain").(string), resp.Success, resp.Errors)
69+
70+
if resp.Code == 429 {
71+
log.Printf("[DEBUG] Sleeping for 10 seconds to allow rate limit to recover.")
72+
time.Sleep(10 * time.Second)
73+
}
74+
75+
if resp.Code == 404 {
76+
log.Printf("[DEBUG] Couldn't find the resource in ImprovMX. Aborting")
77+
return fmt.Errorf("HTTP response code %d, error text: %s", resp.Code, resp.Errors.Domain)
78+
}
79+
80+
if resp.Success {
81+
d.SetId(d.Get("domain").(string))
82+
d.Set("domain", d.Get("domain").(string))
83+
return nil
84+
}
85+
}
86+
}
87+
88+
func resourceSMTPCredentialUpdate(d *schema.ResourceData, meta interface{}) error {
89+
m := meta.(*Meta)
90+
91+
for {
92+
resp := m.Client.UpdateSMTPCredential(d.Get("domain").(string), d.Get("username").(string), d.Get("password").(string))
93+
94+
log.Printf("[DEBUG] Got status code %v from ImprovMX API on Update for SMTP domain %s@%s, success: %v, errors: %v.", resp.Code, d.Get("username").(string), d.Get("domain").(string), resp.Success, resp.Errors)
95+
96+
if resp.Code == 429 {
97+
log.Printf("[DEBUG] Sleeping for 10 seconds to allow rate limit to recover.")
98+
time.Sleep(10 * time.Second)
99+
}
100+
101+
if resp.Code == 404 {
102+
log.Printf("[DEBUG] Couldn't find the resource in ImprovMX. Aborting")
103+
return fmt.Errorf("HTTP response code %d, error text: %s", resp.Code, resp.Errors.Domain)
104+
}
105+
106+
if resp.Success {
107+
return resourceSMTPCredentialRead(d, meta)
108+
}
109+
}
110+
}
111+
112+
func resourceSMTPCredentialDelete(d *schema.ResourceData, meta interface{}) error {
113+
m := meta.(*Meta)
114+
m.Mutex.Lock()
115+
defer m.Mutex.Unlock()
116+
117+
m.Client.DeleteSMTPCredential(d.Get("domain").(string), d.Get("username").(string))
118+
119+
return nil
120+
}

0 commit comments

Comments
 (0)