{"id":20757184,"url":"https://github.com/vapor-community/mailgun","last_synced_at":"2025-04-13T08:38:40.883Z","repository":{"id":41361827,"uuid":"124623973","full_name":"vapor-community/mailgun","owner":"vapor-community","description":"📧 Service to assist with sending emails from Vapor apps","archived":false,"fork":false,"pushed_at":"2024-05-30T12:57:40.000Z","size":141,"stargazers_count":121,"open_issues_count":11,"forks_count":32,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-04T22:46:50.036Z","etag":null,"topics":["email","mailgun","swift","vapor","vapor-3","vapor-4","vapor-service","vapor-swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vapor-community.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-10T05:05:45.000Z","updated_at":"2025-03-02T21:17:39.000Z","dependencies_parsed_at":"2024-05-12T08:21:53.635Z","dependency_job_id":"9a1e116b-8229-4b39-b88d-babdec003745","html_url":"https://github.com/vapor-community/mailgun","commit_stats":{"total_commits":99,"total_committers":15,"mean_commits":6.6,"dds":0.7272727272727273,"last_synced_commit":"66cde42d230ceba17878f03234d31291bdbdfc7d"},"previous_names":["twof/vapormailgunservice"],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor-community%2Fmailgun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor-community%2Fmailgun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor-community%2Fmailgun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor-community%2Fmailgun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vapor-community","download_url":"https://codeload.github.com/vapor-community/mailgun/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248685148,"owners_count":21145215,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email","mailgun","swift","vapor","vapor-3","vapor-4","vapor-service","vapor-swift"],"created_at":"2024-11-17T09:40:23.630Z","updated_at":"2025-04-13T08:38:40.860Z","avatar_url":"https://github.com/vapor-community.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mailgun\n\n[![Discord](https://img.shields.io/badge/join-discord-745EAF.svg?style=flat)](https://vapor.team)\n[![Platforms](https://img.shields.io/badge/platforms-macOS%2010.15%20|%20Ubuntu%2016.04%20LTS-ff0000.svg?style=flat)](http://cocoapods.org/pods/FASwift)\n[![Swift 5.2](https://img.shields.io/badge/swift-5.2-orange.svg?style=flat)](http://swift.org)\n[![Vapor 4](https://img.shields.io/badge/vapor-4.0-blue.svg?style=flat)](https://vapor.codes)\n\n##\n\n`Mailgun` is a Vapor 4 service for a popular [email sending API](https://www.mailgun.com/)\n\u003e Note: Vapor3 version is available in `vapor3` branch and from `3.0.0` tag\n\n\n## Installation\nMailgun can be installed with Swift Package Manager\n\n```swift\n.package(url: \"https://github.com/vapor-community/mailgun.git\", from: \"5.0.0\")\n\n.target(name: \"App\", dependencies: [\n    .product(name: \"Vapor\", package: \"vapor\"),\n    .product(name: \"Mailgun\", package: \"mailgun\")\n])\n```\n\n## Usage\n\n### Sign up and set up a Mailgun account [here](https://www.mailgun.com/)\nMake sure you get an API key and register a custom domain\n\n### Configure\n\nIn `configure.swift`:\n\n```swift\nimport Mailgun\n\n// Called before your application initializes.\nfunc configure(_ app: Application) throws {\n    /// case 1\n    /// put into your environment variables the following keys:\n    /// MAILGUN_API_KEY=...\n    app.mailgun.configuration = .environment\n\n    /// case 2\n    /// manually\n    app.mailgun.configuration = .init(apiKey: \"\u003capi key\u003e\")\n}\n```\n\n\u003e Note: If your private api key begins with `key-`, be sure to include it\n\n### Declare all your domains\n\n```swift\nextension MailgunDomain {\n    static var myApp1: MailgunDomain { .init(\"mg.myapp1.com\", .us) }\n    static var myApp2: MailgunDomain { .init(\"mg.myapp2.com\", .eu) }\n    static var myApp3: MailgunDomain { .init(\"mg.myapp3.com\", .us) }\n    static var myApp4: MailgunDomain { .init(\"mg.myapp4.com\", .eu) }\n}\n```\n\nSet default domain in `configure.swift`\n\n```swift\napp.mailgun.defaultDomain = .myApp1\n```\n\n### Usage\n\n`Mailgun` is available on both `Application` and `Request`\n\n```swift\n// call it without arguments to use default domain\napp.mailgun().send(...)\nreq.mailgun().send(...)\n\n// or call it with domain\napp.mailgun(.myApp1).send(...)\nreq.mailgun(.myApp1).send(...)\n```\n\n#### In `configure.swift`\n\n```swift\nimport Mailgun\n\n// Called before your application initializes.\nfunc configure(_ app: Application) throws {\n    /// configure mailgun\n\n    /// then you're ready to use it\n    app.mailgun(.myApp1).send(...).whenSuccess { response in\n        print(\"just sent: \\(response)\")\n    }\n}\n```\n\n\u003e 💡 NOTE: All the examples below will be with `Request`, but you could do the same with `Application` as in example above.\n\n#### In `routes.swift`:\n\n##### Without attachments\n\n```swift\nimport Mailgun\n\nfunc routes(_ app: Application) throws {\n    app.post(\"mail\") { req -\u003e EventLoopFuture\u003cClientResponse\u003e in\n        let message = MailgunMessage(\n            from: \"postmaster@example.com\",\n            to: \"example@gmail.com\",\n            subject: \"Newsletter\",\n            text: \"This is a newsletter\",\n            html: \"\u003ch1\u003eThis is a newsletter\u003c/h1\u003e\"\n        )\n        return req.mailgun().send(message)\n    }\n}\n```\n\n##### With attachments\n\n```swift\nimport Mailgun\n\nfunc routes(_ app: Application) throws {\n    app.post(\"mail\") { req -\u003e EventLoopFuture\u003cClientResponse\u003e in\n        let fm = FileManager.default\n        guard let attachmentData = fm.contents(atPath: \"/tmp/test.pdf\") else {\n          throw Abort(.internalServerError)\n        }\n        let bytes: [UInt8] = Array(attachmentData)\n        var bytesBuffer = ByteBufferAllocator().buffer(capacity: bytes.count)\n        bytesBuffer.writeBytes(bytes)\n        let attachment = File.init(data: bytesBuffer, filename: \"test.pdf\")\n        let message = MailgunMessage(\n            from: \"postmaster@example.com\",\n            to: \"example@gmail.com\",\n            subject: \"Newsletter\",\n            text: \"This is a newsletter\",\n            html: \"\u003ch1\u003eThis is a newsletter\u003c/h1\u003e\",\n            attachments: [attachment]\n        )\n        return req.mailgun().send(message)\n    }\n}\n```\n\n##### With template (attachments can be used in same way)\n\n```swift\nimport Mailgun\n\nfunc routes(_ app: Application) throws {\n    app.post(\"mail\") { req -\u003e EventLoopFuture\u003cClientResponse\u003e in\n        let message = MailgunTemplateMessage(\n            from: \"postmaster@example.com\",\n            to: \"example@gmail.com\",\n            subject: \"Newsletter\",\n            template: \"my-template\",\n            templateData: [\"foo\": \"bar\"]\n        )\n        return req.mailgun().send(message)\n    }\n}\n```\n\n##### Setup content through Leaf\n\nUsing Vapor Leaf, you can easily setup your HTML Content.\n\nFirst setup a leaf file in `Resources/Views/Emails/my-email.leaf`\n\n```html\n\u003chtml\u003e\n    \u003cbody\u003e\n        \u003cp\u003eHi #(name)\u003c/p\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nWith this, you can change the `#(name)` with a variable from your Swift code, when sending the mail\n\n```swift\nimport Mailgun\n\nfunc routes(_ app: Application) throws {\n    app.post(\"mail\") { req -\u003e EventLoopFuture\u003cClientResponse\u003e in\n        let content = try req.view().render(\"Emails/my-email\", [\n            \"name\": \"Bob\"\n        ])\n\n        let message = Mailgun.Message(\n            from: \"postmaster@example.com\",\n            to: \"example@gmail.com\",\n            subject: \"Newsletter\",\n            text: \"\",\n            html: content\n        )\n\n        return req.mailgun().send(message)\n    }\n}\n```\n\n##### Setup routes\n\n```swift\npublic func configure(_ app: Application) throws {\n    // sets up a catch_all forward for the route listed\n    let routeSetup = MailgunRouteSetup(forwardURL: \"http://example.com/mailgun/all\", description: \"A route for all emails\")\n    app.mailgun().setup(forwarding: routeSetup).whenSuccess { response in\n        print(response)\n    }\n}\n```\n\n##### Handle routes\n\n```swift\nimport Mailgun\n\nfunc routes(_ app: Application) throws {\n    let mailgunGroup = app.grouped(\"mailgun\")\n    mailgunGroup.post(\"all\") { req -\u003e String in\n        do {\n            let incomingMail = try req.content.decode(MailgunIncomingMessage.self)\n            print(\"incomingMail: (incomingMail)\")\n            return \"Hello\"\n        } catch {\n            throw Abort(.internalServerError, reason: \"Could not decode incoming message\")\n        }\n    }\n}\n```\n\n##### Creating templates\n\n```swift\nimport Mailgun\n\nfunc routes(_ app: Application) throws {\n    let mailgunGroup = app.grouped(\"mailgun\")\n    mailgunGroup.post(\"template\") { req -\u003e EventLoopFuture\u003cClientResponse\u003e in\n        let template = MailgunTemplate(name: \"my-template\", description: \"api created :)\", template: \"\u003ch1\u003eHello {{ name }}\u003c/h1\u003e\")\n        return req.mailgun().createTemplate(template)\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvapor-community%2Fmailgun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvapor-community%2Fmailgun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvapor-community%2Fmailgun/lists"}