Skip to content

Commit 78a756c

Browse files
authored
Merge pull request #37 from MihaelIsaev/master
Upgrade to Vapor4
2 parents 9c41e74 + d57d422 commit 78a756c

21 files changed

Lines changed: 650 additions & 462 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
/Packages
44
/*.xcodeproj
55
Package.resolved
6+
.swiftpm

Package.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
// swift-tools-version:4.0
1+
// swift-tools-version:5.1
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription
55

66
let package = Package(
77
name: "Mailgun",
8+
platforms: [
9+
.macOS(.v10_14)
10+
],
811
products: [
912
// Products define the executables and libraries produced by a package, and make them visible to other packages.
1013
.library(
1114
name: "Mailgun",
1215
targets: ["Mailgun"]),
1316
],
1417
dependencies: [
15-
.package(url: "https://github.com/vapor/vapor.git", from: "3.3.0")
18+
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0-beta.3")
1619
],
1720
targets: [
1821
// Targets are the basic building blocks of a package. A target can define a module or a test suite.

README.md

Lines changed: 166 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
# Vapor Mailgun Service
22

3-
[![Slack](https://img.shields.io/badge/join-slack-745EAF.svg?style=flat)](https://vapor.team)
4-
[![Platforms](https://img.shields.io/badge/platforms-macOS%2010.13%20|%20Ubuntu%2016.04%20LTS-ff0000.svg?style=flat)](http://cocoapods.org/pods/FASwift)
5-
[![Swift 4.1](https://img.shields.io/badge/swift-4.1-orange.svg?style=flat)](http://swift.org)
6-
[![Vapor 3](https://img.shields.io/badge/vapor-3.0-blue.svg?style=flat)](https://vapor.codes)
3+
[![Discord](https://img.shields.io/badge/join-discord-745EAF.svg?style=flat)](https://vapor.team)
4+
[![Platforms](https://img.shields.io/badge/platforms-macOS%2010.14%20|%20Ubuntu%2016.04%20LTS-ff0000.svg?style=flat)](http://cocoapods.org/pods/FASwift)
5+
[![Swift 5.1](https://img.shields.io/badge/swift-5.1-orange.svg?style=flat)](http://swift.org)
6+
[![Vapor 4](https://img.shields.io/badge/vapor-4.0-blue.svg?style=flat)](https://vapor.codes)
77

88
##
99

10-
`Mailgun` is a Vapor 3 service for a popular [email sending API](https://www.mailgun.com/)
10+
`Mailgun` is a Vapor 4 service for a popular [email sending API](https://www.mailgun.com/)
11+
> Note: Vapor3 version is available in `vapor3` branch and from `3.0.0` tag
1112
1213

1314
## Installation
1415
Vapor Mailgun Service can be installed with Swift Package Manager
1516

1617
```swift
17-
.package(url: "https://github.com/twof/VaporMailgunService.git", from: "1.5.0")
18+
.package(url: "https://github.com/twof/VaporMailgunService.git", from: "4.0.0")
19+
20+
//and in targets add
21+
//"Mailgun"
1822
```
1923

2024
## Usage
@@ -27,74 +31,141 @@ Make sure you get an API key and register a custom domain
2731
In `configure.swift`:
2832

2933
```swift
30-
let mailgun = Mailgun(apiKey: "<api key>", domain: "mg.example.com", region: .eu)
31-
services.register(mailgun, as: Mailgun.self)
34+
import Mailgun
35+
36+
// Called before your application initializes.
37+
func configure(_ app: Application) throws {
38+
/// case 1
39+
/// put into your environment variables the following keys:
40+
/// MAILGUN_API_KEY=...
41+
app.mailgun.configuration = .environment
42+
43+
/// case 2
44+
/// manually
45+
app.mailgun.configuration = .init(apiKey: "<api key>")
46+
}
3247
```
3348

3449
> Note: If your private api key begins with `key-`, be sure to include it
3550
36-
### Use
51+
### Declare all your domains
52+
53+
```swift
54+
extension MailgunDomain {
55+
static var myApp1: MailgunDomain { .init("mg.myapp1.com", .us) }
56+
static var myApp2: MailgunDomain { .init("mg.myapp2.com", .eu) }
57+
static var myApp3: MailgunDomain { .init("mg.myapp3.com", .us) }
58+
static var myApp4: MailgunDomain { .init("mg.myapp4.com", .eu) }
59+
}
60+
```
61+
62+
Set default domain in `configure.swift`
63+
64+
```swift
65+
app.mailgun.defaultDomain = .myApp1
66+
```
67+
68+
### Usage
69+
70+
`Mailgun` is available on both `Application` and `Request`
71+
72+
```swift
73+
// call it without arguments to use default domain
74+
app.mailgun().send(...)
75+
req.mailgun().send(...)
3776

38-
In `routes.swift`:
77+
// or call it with domain
78+
app.mailgun(.myApp1).send(...)
79+
req.mailgun(.myApp1).send(...)
80+
```
3981

40-
#### Without attachments
82+
#### In `configure.swift`
4183

4284
```swift
43-
router.post("mail") { (req) -> Future<Response> in
44-
let message = Mailgun.Message(
45-
from: "postmaster@example.com",
46-
to: "example@gmail.com",
47-
subject: "Newsletter",
48-
text: "This is a newsletter",
49-
html: "<h1>This is a newsletter</h1>"
50-
)
51-
52-
let mailgun = try req.make(Mailgun.self)
53-
return try mailgun.send(message, on: req)
85+
import Mailgun
86+
87+
// Called before your application initializes.
88+
func configure(_ app: Application) throws {
89+
/// configure mailgun
90+
91+
/// then you're ready to use it
92+
app.mailgun(.myApp1).send(...).whenSuccess { response in
93+
print("just sent: \(response)")
94+
}
95+
}
96+
```
97+
98+
> 💡 NOTE: All the examples below will be with `Request`, but you could do the same with `Application` as in example above.
99+
100+
#### In `routes.swift`:
101+
102+
##### Without attachments
103+
104+
```swift
105+
import Mailgun
106+
107+
func routes(_ app: Application) throws {
108+
app.post("mail") { req -> EventLoopFuture<ClientResponse> in
109+
let message = MailgunMessage(
110+
from: "postmaster@example.com",
111+
to: "example@gmail.com",
112+
subject: "Newsletter",
113+
text: "This is a newsletter",
114+
html: "<h1>This is a newsletter</h1>"
115+
)
116+
return req.mailgun().send(message)
117+
}
54118
}
55119
```
56120

57-
#### With attachments
121+
##### With attachments
58122

59123
```swift
60-
router.post("mail") { (req) -> Future<Response> in
61-
let fm = FileManager.default
62-
guard let attachmentData = fm.contents(atPath: "/tmp/test.pdf") else {
63-
throw Abort(.internalServerError)
124+
import Mailgun
125+
126+
func routes(_ app: Application) throws {
127+
app.post("mail") { req -> EventLoopFuture<ClientResponse> in
128+
let fm = FileManager.default
129+
guard let attachmentData = fm.contents(atPath: "/tmp/test.pdf") else {
130+
throw Abort(.internalServerError)
131+
}
132+
let bytes: [UInt8] = Array(attachmentData)
133+
var bytesBuffer = ByteBufferAllocator().buffer(capacity: bytes.count)
134+
bytesBuffer.writeBytes(bytes)
135+
let attachment = File.init(data: bytesBuffer, filename: "test.pdf")
136+
let message = MailgunMessage(
137+
from: "postmaster@example.com",
138+
to: "example@gmail.com",
139+
subject: "Newsletter",
140+
text: "This is a newsletter",
141+
html: "<h1>This is a newsletter</h1>",
142+
attachments: [attachment]
143+
)
144+
return req.mailgun().send(message)
64145
}
65-
let attachment = File(data: attachmentData, filename: "test.pdf")
66-
let message = Mailgun.Message(
67-
from: "postmaster@example.com",
68-
to: "example@gmail.com",
69-
subject: "Newsletter",
70-
text: "This is a newsletter",
71-
html: "<h1>This is a newsletter</h1>",
72-
attachments: [attachment]
73-
)
74-
75-
let mailgun = try req.make(Mailgun.self)
76-
return try mailgun.send(message, on: req)
77146
}
78147
```
79148

80-
#### With template (attachments can be used in same way)
149+
##### With template (attachments can be used in same way)
81150

82151
```swift
83-
router.post("mail") { (req) -> Future<Response> in
84-
let message = Mailgun.TemplateMessage(
85-
from: "postmaster@example.com",
86-
to: "example@gmail.com",
87-
subject: "Newsletter",
88-
template: "my-template",
89-
templateData: ["foo": "bar"]
90-
)
91-
92-
let mailgun = try req.make(Mailgun.self)
93-
return try mailgun.send(message, on: req)
152+
import Mailgun
153+
154+
func routes(_ app: Application) throws {
155+
app.post("mail") { req -> EventLoopFuture<ClientResponse> in
156+
let message = MailgunTemplateMessage(
157+
from: "postmaster@example.com",
158+
to: "example@gmail.com",
159+
subject: "Newsletter",
160+
template: "my-template",
161+
templateData: ["foo": "bar"]
162+
)
163+
return req.mailgun().send(message)
164+
}
94165
}
95166
```
96167

97-
#### Setup content through Leaf
168+
##### Setup content through Leaf
98169

99170
Using Vapor Leaf, you can easily setup your HTML Content.
100171

@@ -111,58 +182,68 @@ First setup a leaf file in `Resources/Views/Emails/my-email.leaf`
111182
With this, you can change the `#(name)` with a variable from your Swift code, when sending the mail
112183

113184
```swift
114-
router.post("mail") { (req) -> Future<Response> in
115-
let content = try req.view().render("Emails/my-email", [
116-
"name": "Bob"
117-
])
118-
119-
let message = Mailgun.Message(
120-
from: "postmaster@example.com",
121-
to: "example@gmail.com",
122-
subject: "Newsletter",
123-
text: "",
124-
html: content
125-
)
126-
127-
let mailgun = try req.make(Mailgun.self)
128-
return try mailgun.send(message, on: req)
185+
import Mailgun
186+
187+
func routes(_ app: Application) throws {
188+
app.post("mail") { req -> EventLoopFuture<ClientResponse> in
189+
let content = try req.view().render("Emails/my-email", [
190+
"name": "Bob"
191+
])
192+
193+
let message = Mailgun.Message(
194+
from: "postmaster@example.com",
195+
to: "example@gmail.com",
196+
subject: "Newsletter",
197+
text: "",
198+
html: content
199+
)
200+
201+
return req.mailgun().send(message)
202+
}
129203
}
130204
```
131205

132-
#### Setup routes
206+
##### Setup routes
133207

134208
```swift
135-
public func boot(_ app: Application) throws {
209+
public func configure(_ app: Application) throws {
136210
// sets up a catch_all forward for the route listed
137-
let routeSetup = RouteSetup(forwardURL: "http://example.com/mailgun/all", description: "A route for all emails")
138-
let mailgunClient = try app.make(Mailgun.self)
139-
try mailgunClient.setup(forwarding: routeSetup, with: app).map { (resp) in
140-
print(resp)
211+
let routeSetup = MailgunRouteSetup(forwardURL: "http://example.com/mailgun/all", description: "A route for all emails")
212+
app.mailgun().setup(forwarding: routeSetup).whenSuccess { response in
213+
print(response)
141214
}
142215
}
143216
```
144217

145-
#### Handle routes
218+
##### Handle routes
146219

147220
```swift
148-
mailgunGroup.post("all") { (req) -> Future<String> in
149-
do {
150-
return try req.content.decode(IncomingMailgun.self).map { (incomingMail) in
221+
import Mailgun
222+
223+
func routes(_ app: Application) throws {
224+
let mailgunGroup = app.grouped("mailgun")
225+
mailgunGroup.post("all") { req -> String in
226+
do {
227+
let incomingMail = try req.content.decode(MailgunIncomingMessage.self)
228+
print("incomingMail: (incomingMail)")
151229
return "Hello"
230+
} catch {
231+
throw Abort(.internalServerError, reason: "Could not decode incoming message")
152232
}
153-
} catch {
154-
throw Abort(HTTPStatus.internalServerError, reason: "Could not decode incoming message")
155233
}
156234
}
157235
```
158236

159-
#### Creating templates
237+
##### Creating templates
160238

161239
```swift
162-
router.post("template") { (req) -> Future<Response> in
163-
let template = Mailgun.Template(name: "my-template", description: "api created :)", template: "<h1>Hello {{ name }}</h1>")
164-
165-
let mailgun = try req.make(Mailgun.self)
166-
return try mailgun.createTemplate(template, on: req)
240+
import Mailgun
241+
242+
func routes(_ app: Application) throws {
243+
let mailgunGroup = app.grouped("mailgun")
244+
mailgunGroup.post("template") { req -> EventLoopFuture<ClientResponse> in
245+
let template = MailgunTemplate(name: "my-template", description: "api created :)", template: "<h1>Hello {{ name }}</h1>")
246+
return req.mailgun().createTemplate(template)
247+
}
167248
}
168249
```

0 commit comments

Comments
 (0)