+23
.github/workflows/test.yml
+23
.github/workflows/test.yml
···
1
+
name: test
2
+
3
+
on:
4
+
push:
5
+
branches:
6
+
- master
7
+
- main
8
+
pull_request:
9
+
10
+
jobs:
11
+
test:
12
+
runs-on: ubuntu-latest
13
+
steps:
14
+
- uses: actions/checkout@v4
15
+
- uses: erlef/setup-beam@v1
16
+
with:
17
+
otp-version: "26.0.2"
18
+
gleam-version: "1.3.2"
19
+
rebar3-version: "3"
20
+
# elixir-version: "1.15.4"
21
+
- run: gleam deps download
22
+
- run: gleam test
23
+
- run: gleam format --check src test
+36
README.md
+36
README.md
···
1
+
# resend
2
+
3
+
[](https://hex.pm/packages/resend)
4
+
[](https://hexdocs.pm/resend/)
5
+
6
+
```sh
7
+
gleam add resend@1
8
+
```
9
+
10
+
```gleam
11
+
import resend
12
+
import resend/emails.{create_email, send_email, with_html}
13
+
14
+
pub fn main() {
15
+
let client =
16
+
resend.Resend(api_key: "// Replace this with your resend api key")
17
+
18
+
create_email(
19
+
client:,
20
+
from: "from@example.com",
21
+
to: ["to@example.com"],
22
+
subject: ":)",
23
+
)
24
+
|> with_html("<p>Email sent</p>")
25
+
|> send_email()
26
+
}
27
+
```
28
+
29
+
Further documentation can be found at <https://hexdocs.pm/resend>.
30
+
31
+
## Development
32
+
33
+
```sh
34
+
gleam run # Run the project
35
+
gleam test # Run the tests
36
+
```
+13
gleam.toml
+13
gleam.toml
···
1
+
name = "resend"
2
+
version = "1.0.0"
3
+
licences = ["MIT"]
4
+
repository = { type = "github", user = "dinkelspiel", repo = "resend" }
5
+
6
+
[dependencies]
7
+
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
8
+
gleam_http = ">= 3.6.0 and < 4.0.0"
9
+
gleam_hackney = ">= 1.2.0 and < 2.0.0"
10
+
gleam_json = ">= 1.0.1 and < 2.0.0"
11
+
12
+
[dev-dependencies]
13
+
gleeunit = ">= 1.0.0 and < 2.0.0"
+26
manifest.toml
+26
manifest.toml
···
1
+
# This file was generated by Gleam
2
+
# You typically do not need to edit this file
3
+
4
+
packages = [
5
+
{ name = "certifi", version = "2.12.0", build_tools = ["rebar3"], requirements = [], otp_app = "certifi", source = "hex", outer_checksum = "EE68D85DF22E554040CDB4BE100F33873AC6051387BAF6A8F6CE82272340FF1C" },
6
+
{ name = "gleam_hackney", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_stdlib", "hackney"], otp_app = "gleam_hackney", source = "hex", outer_checksum = "066B1A55D37DBD61CC72A1C4EDE43C6015B1797FAF3818C16FE476534C7B6505" },
7
+
{ name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" },
8
+
{ name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" },
9
+
{ name = "gleam_stdlib", version = "0.39.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "2D7DE885A6EA7F1D5015D1698920C9BAF7241102836CE0C3837A4F160128A9C4" },
10
+
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
11
+
{ name = "hackney", version = "1.20.1", build_tools = ["rebar3"], requirements = ["certifi", "idna", "metrics", "mimerl", "parse_trans", "ssl_verify_fun", "unicode_util_compat"], otp_app = "hackney", source = "hex", outer_checksum = "FE9094E5F1A2A2C0A7D10918FEE36BFEC0EC2A979994CFF8CFE8058CD9AF38E3" },
12
+
{ name = "idna", version = "6.1.1", build_tools = ["rebar3"], requirements = ["unicode_util_compat"], otp_app = "idna", source = "hex", outer_checksum = "92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA" },
13
+
{ name = "metrics", version = "1.0.1", build_tools = ["rebar3"], requirements = [], otp_app = "metrics", source = "hex", outer_checksum = "69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16" },
14
+
{ name = "mimerl", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "mimerl", source = "hex", outer_checksum = "A1E15A50D1887217DE95F0B9B0793E32853F7C258A5CD227650889B38839FE9D" },
15
+
{ name = "parse_trans", version = "3.4.1", build_tools = ["rebar3"], requirements = [], otp_app = "parse_trans", source = "hex", outer_checksum = "620A406CE75DADA827B82E453C19CF06776BE266F5A67CFF34E1EF2CBB60E49A" },
16
+
{ name = "ssl_verify_fun", version = "1.1.7", build_tools = ["mix", "rebar3", "make"], requirements = [], otp_app = "ssl_verify_fun", source = "hex", outer_checksum = "FE4C190E8F37401D30167C8C405EDA19469F34577987C76DDE613E838BBC67F8" },
17
+
{ name = "thoas", version = "1.2.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "E38697EDFFD6E91BD12CEA41B155115282630075C2A727E7A6B2947F5408B86A" },
18
+
{ name = "unicode_util_compat", version = "0.7.0", build_tools = ["rebar3"], requirements = [], otp_app = "unicode_util_compat", source = "hex", outer_checksum = "25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521" },
19
+
]
20
+
21
+
[requirements]
22
+
gleam_hackney = { version = ">= 1.2.0 and < 2.0.0" }
23
+
gleam_http = { version = ">= 3.6.0 and < 4.0.0" }
24
+
gleam_json = { version = ">= 1.0.1 and < 2.0.0" }
25
+
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
26
+
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+138
src/resend/emails.gleam
+138
src/resend/emails.gleam
···
1
+
import gleam/dynamic
2
+
import gleam/hackney
3
+
import gleam/http.{Post}
4
+
import gleam/http/request
5
+
import gleam/json
6
+
import gleam/list
7
+
import gleam/option.{type Option, None, Some}
8
+
import gleam/result.{try}
9
+
import resend.{type Resend}
10
+
11
+
pub type ResendEmail {
12
+
ResendEmail(
13
+
client: Resend,
14
+
from: String,
15
+
to: List(String),
16
+
subject: String,
17
+
bcc: Option(List(String)),
18
+
cc: Option(List(String)),
19
+
reply_to: Option(List(String)),
20
+
html: Option(String),
21
+
text: Option(String),
22
+
)
23
+
}
24
+
25
+
pub fn with_bcc(resend: ResendEmail, bcc: List(String)) {
26
+
ResendEmail(..resend, bcc: Some(bcc))
27
+
}
28
+
29
+
pub fn with_cc(resend: ResendEmail, cc: List(String)) {
30
+
ResendEmail(..resend, cc: Some(cc))
31
+
}
32
+
33
+
pub fn with_reply_to(resend: ResendEmail, reply_to: List(String)) {
34
+
ResendEmail(..resend, reply_to: Some(reply_to))
35
+
}
36
+
37
+
pub fn with_html(resend: ResendEmail, html: String) {
38
+
ResendEmail(..resend, html: Some(html))
39
+
}
40
+
41
+
pub fn with_text(resend: ResendEmail, text: String) {
42
+
ResendEmail(..resend, text: Some(text))
43
+
}
44
+
45
+
pub fn create_email(
46
+
client client: Resend,
47
+
from from: String,
48
+
to to: List(String),
49
+
subject subject: String,
50
+
) {
51
+
ResendEmail(
52
+
client:,
53
+
from:,
54
+
to:,
55
+
subject:,
56
+
bcc: None,
57
+
cc: None,
58
+
reply_to: None,
59
+
html: None,
60
+
text: None,
61
+
)
62
+
}
63
+
64
+
pub type SendEmailError {
65
+
RequestError
66
+
BadRequestError
67
+
ParseResponseBodyError
68
+
}
69
+
70
+
pub type SuccessResponse {
71
+
SuccessResponse(id: String)
72
+
}
73
+
74
+
pub fn send_email(email: ResendEmail) {
75
+
let assert Ok(request) = request.to("https://api.resend.com/emails")
76
+
77
+
let body =
78
+
json.object(
79
+
list.concat([
80
+
[
81
+
#("from", json.string(email.from)),
82
+
#("to", json.array(email.to, fn(a) { json.string(a) })),
83
+
#("subject", json.string(email.from)),
84
+
],
85
+
case email.bcc {
86
+
Some(bcc) -> [#("bcc", json.array(bcc, fn(a) { json.string(a) }))]
87
+
None -> []
88
+
},
89
+
case email.cc {
90
+
Some(cc) -> [#("cc", json.array(cc, fn(a) { json.string(a) }))]
91
+
None -> []
92
+
},
93
+
case email.reply_to {
94
+
Some(reply_to) -> [
95
+
#("reply_to", json.array(reply_to, fn(a) { json.string(a) })),
96
+
]
97
+
None -> []
98
+
},
99
+
case email.html {
100
+
Some(html) -> [#("html", json.string(html))]
101
+
None -> []
102
+
},
103
+
case email.text {
104
+
Some(text) -> [#("text", json.string(text))]
105
+
None -> []
106
+
},
107
+
]),
108
+
)
109
+
110
+
use response <- try(
111
+
request
112
+
|> request.prepend_header("accept", "application/vnd.hmrc.1.0+json")
113
+
|> request.prepend_header("Content-Type", "application/json")
114
+
|> request.prepend_header(
115
+
"Authorization",
116
+
"Bearer " <> email.client.api_key,
117
+
)
118
+
|> request.set_method(Post)
119
+
|> request.set_body(
120
+
body
121
+
|> json.to_string,
122
+
)
123
+
|> hackney.send
124
+
|> result.replace_error(RequestError),
125
+
)
126
+
127
+
let body_decoder =
128
+
dynamic.decode1(SuccessResponse, dynamic.field("id", dynamic.string))
129
+
130
+
case response.status {
131
+
200 ->
132
+
case json.decode(response.body, body_decoder) {
133
+
Ok(body) -> Ok(body)
134
+
Error(_) -> Error(ParseResponseBodyError)
135
+
}
136
+
_ -> Error(BadRequestError)
137
+
}
138
+
}
+22
test/resend_test.gleam
+22
test/resend_test.gleam
···
1
+
import gleeunit
2
+
import gleeunit/should
3
+
import resend
4
+
import resend/emails.{create_email, send_email, with_html}
5
+
6
+
pub fn main() {
7
+
gleeunit.main()
8
+
}
9
+
10
+
pub fn resend_test() {
11
+
let client =
12
+
resend.Resend(api_key: "// Replace this with your resend api key")
13
+
14
+
create_email(
15
+
client:,
16
+
from: "from@example.com",
17
+
to: ["to@example.com"],
18
+
subject: ":)",
19
+
)
20
+
|> with_html("<p>Successful response</p>")
21
+
|> send_email()
22
+
}