Skip to content

Commit

Permalink
Merge pull request #37 from MihaelIsaev/master
Browse files Browse the repository at this point in the history
Upgrade to Vapor4
  • Loading branch information
twof committed Jan 21, 2020
2 parents 9c41e74 + d57d422 commit 78a756c
Show file tree
Hide file tree
Showing 21 changed files with 650 additions and 462 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,3 +3,4 @@
/Packages
/*.xcodeproj
Package.resolved
.swiftpm
7 changes: 5 additions & 2 deletions Package.swift
@@ -1,18 +1,21 @@
// swift-tools-version:4.0
// swift-tools-version:5.1
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Mailgun",
platforms: [
.macOS(.v10_14)
],
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "Mailgun",
targets: ["Mailgun"]),
],
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", from: "3.3.0")
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0-beta.3")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand Down
251 changes: 166 additions & 85 deletions README.md
@@ -1,20 +1,24 @@
# Vapor Mailgun Service

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

##

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

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

```swift
.package(url: "https://github.com/twof/VaporMailgunService.git", from: "1.5.0")
.package(url: "https://github.com/twof/VaporMailgunService.git", from: "4.0.0")

//and in targets add
//"Mailgun"
```

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

```swift
let mailgun = Mailgun(apiKey: "<api key>", domain: "mg.example.com", region: .eu)
services.register(mailgun, as: Mailgun.self)
import Mailgun

// Called before your application initializes.
func configure(_ app: Application) throws {
/// case 1
/// put into your environment variables the following keys:
/// MAILGUN_API_KEY=...
app.mailgun.configuration = .environment

/// case 2
/// manually
app.mailgun.configuration = .init(apiKey: "<api key>")
}
```

> Note: If your private api key begins with `key-`, be sure to include it
### Use
### Declare all your domains

```swift
extension MailgunDomain {
static var myApp1: MailgunDomain { .init("mg.myapp1.com", .us) }
static var myApp2: MailgunDomain { .init("mg.myapp2.com", .eu) }
static var myApp3: MailgunDomain { .init("mg.myapp3.com", .us) }
static var myApp4: MailgunDomain { .init("mg.myapp4.com", .eu) }
}
```

Set default domain in `configure.swift`

```swift
app.mailgun.defaultDomain = .myApp1
```

### Usage

`Mailgun` is available on both `Application` and `Request`

```swift
// call it without arguments to use default domain
app.mailgun().send(...)
req.mailgun().send(...)

In `routes.swift`:
// or call it with domain
app.mailgun(.myApp1).send(...)
req.mailgun(.myApp1).send(...)
```

#### Without attachments
#### In `configure.swift`

```swift
router.post("mail") { (req) -> Future<Response> in
let message = Mailgun.Message(
from: "postmaster@example.com",
to: "example@gmail.com",
subject: "Newsletter",
text: "This is a newsletter",
html: "<h1>This is a newsletter</h1>"
)

let mailgun = try req.make(Mailgun.self)
return try mailgun.send(message, on: req)
import Mailgun

// Called before your application initializes.
func configure(_ app: Application) throws {
/// configure mailgun

/// then you're ready to use it
app.mailgun(.myApp1).send(...).whenSuccess { response in
print("just sent: \(response)")
}
}
```

> 馃挕 NOTE: All the examples below will be with `Request`, but you could do the same with `Application` as in example above.
#### In `routes.swift`:

##### Without attachments

```swift
import Mailgun

func routes(_ app: Application) throws {
app.post("mail") { req -> EventLoopFuture<ClientResponse> in
let message = MailgunMessage(
from: "postmaster@example.com",
to: "example@gmail.com",
subject: "Newsletter",
text: "This is a newsletter",
html: "<h1>This is a newsletter</h1>"
)
return req.mailgun().send(message)
}
}
```

#### With attachments
##### With attachments

```swift
router.post("mail") { (req) -> Future<Response> in
let fm = FileManager.default
guard let attachmentData = fm.contents(atPath: "/tmp/test.pdf") else {
throw Abort(.internalServerError)
import Mailgun

func routes(_ app: Application) throws {
app.post("mail") { req -> EventLoopFuture<ClientResponse> in
let fm = FileManager.default
guard let attachmentData = fm.contents(atPath: "/tmp/test.pdf") else {
throw Abort(.internalServerError)
}
let bytes: [UInt8] = Array(attachmentData)
var bytesBuffer = ByteBufferAllocator().buffer(capacity: bytes.count)
bytesBuffer.writeBytes(bytes)
let attachment = File.init(data: bytesBuffer, filename: "test.pdf")
let message = MailgunMessage(
from: "postmaster@example.com",
to: "example@gmail.com",
subject: "Newsletter",
text: "This is a newsletter",
html: "<h1>This is a newsletter</h1>",
attachments: [attachment]
)
return req.mailgun().send(message)
}
let attachment = File(data: attachmentData, filename: "test.pdf")
let message = Mailgun.Message(
from: "postmaster@example.com",
to: "example@gmail.com",
subject: "Newsletter",
text: "This is a newsletter",
html: "<h1>This is a newsletter</h1>",
attachments: [attachment]
)

let mailgun = try req.make(Mailgun.self)
return try mailgun.send(message, on: req)
}
```

#### With template (attachments can be used in same way)
##### With template (attachments can be used in same way)

```swift
router.post("mail") { (req) -> Future<Response> in
let message = Mailgun.TemplateMessage(
from: "postmaster@example.com",
to: "example@gmail.com",
subject: "Newsletter",
template: "my-template",
templateData: ["foo": "bar"]
)

let mailgun = try req.make(Mailgun.self)
return try mailgun.send(message, on: req)
import Mailgun

func routes(_ app: Application) throws {
app.post("mail") { req -> EventLoopFuture<ClientResponse> in
let message = MailgunTemplateMessage(
from: "postmaster@example.com",
to: "example@gmail.com",
subject: "Newsletter",
template: "my-template",
templateData: ["foo": "bar"]
)
return req.mailgun().send(message)
}
}
```

#### Setup content through Leaf
##### Setup content through Leaf

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

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

```swift
router.post("mail") { (req) -> Future<Response> in
let content = try req.view().render("Emails/my-email", [
"name": "Bob"
])

let message = Mailgun.Message(
from: "postmaster@example.com",
to: "example@gmail.com",
subject: "Newsletter",
text: "",
html: content
)

let mailgun = try req.make(Mailgun.self)
return try mailgun.send(message, on: req)
import Mailgun

func routes(_ app: Application) throws {
app.post("mail") { req -> EventLoopFuture<ClientResponse> in
let content = try req.view().render("Emails/my-email", [
"name": "Bob"
])

let message = Mailgun.Message(
from: "postmaster@example.com",
to: "example@gmail.com",
subject: "Newsletter",
text: "",
html: content
)

return req.mailgun().send(message)
}
}
```

#### Setup routes
##### Setup routes

```swift
public func boot(_ app: Application) throws {
public func configure(_ app: Application) throws {
// sets up a catch_all forward for the route listed
let routeSetup = RouteSetup(forwardURL: "http://example.com/mailgun/all", description: "A route for all emails")
let mailgunClient = try app.make(Mailgun.self)
try mailgunClient.setup(forwarding: routeSetup, with: app).map { (resp) in
print(resp)
let routeSetup = MailgunRouteSetup(forwardURL: "http://example.com/mailgun/all", description: "A route for all emails")
app.mailgun().setup(forwarding: routeSetup).whenSuccess { response in
print(response)
}
}
```

#### Handle routes
##### Handle routes

```swift
mailgunGroup.post("all") { (req) -> Future<String> in
do {
return try req.content.decode(IncomingMailgun.self).map { (incomingMail) in
import Mailgun

func routes(_ app: Application) throws {
let mailgunGroup = app.grouped("mailgun")
mailgunGroup.post("all") { req -> String in
do {
let incomingMail = try req.content.decode(MailgunIncomingMessage.self)
print("incomingMail: (incomingMail)")
return "Hello"
} catch {
throw Abort(.internalServerError, reason: "Could not decode incoming message")
}
} catch {
throw Abort(HTTPStatus.internalServerError, reason: "Could not decode incoming message")
}
}
```

#### Creating templates
##### Creating templates

```swift
router.post("template") { (req) -> Future<Response> in
let template = Mailgun.Template(name: "my-template", description: "api created :)", template: "<h1>Hello {{ name }}</h1>")

let mailgun = try req.make(Mailgun.self)
return try mailgun.createTemplate(template, on: req)
import Mailgun

func routes(_ app: Application) throws {
let mailgunGroup = app.grouped("mailgun")
mailgunGroup.post("template") { req -> EventLoopFuture<ClientResponse> in
let template = MailgunTemplate(name: "my-template", description: "api created :)", template: "<h1>Hello {{ name }}</h1>")
return req.mailgun().createTemplate(template)
}
}
```

0 comments on commit 78a756c

Please sign in to comment.