{"id":15178573,"url":"https://github.com/chubbard/groovymail","last_synced_at":"2026-01-28T18:06:44.295Z","repository":{"id":77853258,"uuid":"167724181","full_name":"chubbard/groovymail","owner":"chubbard","description":"GroovyMail aims to replace using JavaMail as the API to send email in Groovy by building a domain specific language (DSL) on top of JavaMail to make sending email simpler.","archived":false,"fork":false,"pushed_at":"2019-04-05T16:39:47.000Z","size":98,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-04T23:09:02.237Z","etag":null,"topics":["email","groovy","groovy-library","mail"],"latest_commit_sha":null,"homepage":"","language":"Groovy","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chubbard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2019-01-26T18:33:05.000Z","updated_at":"2019-04-03T04:47:29.000Z","dependencies_parsed_at":"2023-05-02T07:47:01.221Z","dependency_job_id":null,"html_url":"https://github.com/chubbard/groovymail","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chubbard/groovymail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chubbard%2Fgroovymail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chubbard%2Fgroovymail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chubbard%2Fgroovymail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chubbard%2Fgroovymail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chubbard","download_url":"https://codeload.github.com/chubbard/groovymail/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chubbard%2Fgroovymail/sbom","scorecard":{"id":281859,"data":{"date":"2022-08-15","repo":{"name":"github.com/chubbard/groovymail","commit":"d8f5a677c93ec2a5a48168e9b4071955431cf30f"},"scorecard":{"version":"v4.5.0-17-g7772984","commit":"777298477c07c262a4ec7e95ceee839b7b3b75ae"},"score":5.1,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) out of 13 and 0 issue activity out of 0 found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"no reviews found","details":["Warn: no reviews found for commit: d8f5a677c93ec2a5a48168e9b4071955431cf30f","Warn: no reviews found for commit: b9e1b4465b15149d8c8bade5caa0aea9d1e9f8fa","Warn: no reviews found for commit: a052db155c239a8f582984d956ca6399b067f81c","Warn: no reviews found for commit: 0402477b5687a83db041fa17a2a8988672b1d2ae","Warn: no reviews found for commit: 82281d51408583ac302849aa21220bfbceb213b4","Warn: no reviews found for commit: 64037a39e54868f96395753e684f8de0fca5dfdb","Warn: no reviews found for commit: b9f91cd7b4591541b8d3ff02d5db13201f108158","Warn: no reviews found for commit: 74cc5e9b8de16ad73bbc1dffdfaafe161c601a04","Warn: no reviews found for commit: 4a884781cb6653165f671546cae8cb14948da98f","Warn: no reviews found for commit: 9f550ae22323963129594e812d180ac61fbecbb4","Warn: no reviews found for commit: d1c446778781f998761dbda4d1e2e80f49742a70","Warn: no reviews found for commit: 3cda09302bcaba9b4f77d0dd74c44b5e9d13ed4f","Warn: no reviews found for commit: 56e05f914264e3ee2f883a92ab0be8a88b8663ee"],"documentation":{"short":"Determines if the project requires code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no badge detected","details":null,"documentation":{"short":"Determines if the project has a CII Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#cii-best-practices"}},{"name":"Packaging","score":-1,"reason":"no published package detected","details":["Warn: no GitHub publishing workflow detected"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#packaging"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: : LICENSE:1"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#license"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":10,"reason":"tokens are read-only in GitHub workflows","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":10,"reason":"all dependencies are pinned","details":["Info: GitHub-owned GitHubActions are pinned","Info: Third-party GitHubActions are pinned","Info: Dockerfile dependencies are pinned","Info: no insecure (not pinned by hash) dependency downloads found in Dockerfiles","Info: no insecure (not pinned by hash) dependency downloads found in shell scripts"],"documentation":{"short":"Determines if the project has declared and pinned its dependencies.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#pinned-dependencies"}},{"name":"Vulnerabilities","score":10,"reason":"no vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":["Warn: no GitHub releases found"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#branch-protection"}},{"name":"Fuzzing","score":-1,"reason":"internal error: internal error: Client.Search.Code: Search.Code: GET https://api.github.com/search/code?q=github.com+chubbard+groovymail+repo%3Agoogle%2Foss-fuzz+in%3Afile+filename%3Aproject.yaml: 403 You have exceeded a secondary rate limit. Please wait a few minutes before you try again. []","details":null,"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#fuzzing"}},{"name":"Dependency-Update-Tool","score":0,"reason":"no update tool detected","details":["Warn: dependabot config file not detected in source location.\n\t\t\tWe recommend setting this configuration in code so it can be easily verified by others.","Warn: renovatebot config file not detected in source location.\n\t\t\tWe recommend setting this configuration in code so it can be easily verified by others."],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#dependency-update-tool"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":null,"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/777298477c07c262a4ec7e95ceee839b7b3b75ae/docs/checks.md#security-policy"}}]},"last_synced_at":"2025-08-17T16:05:11.596Z","repository_id":77853258,"created_at":"2025-08-17T16:05:11.596Z","updated_at":"2025-08-17T16:05:11.596Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28848413,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","groovy","groovy-library","mail"],"created_at":"2024-09-27T15:05:33.357Z","updated_at":"2026-01-28T18:06:44.280Z","avatar_url":"https://github.com/chubbard.png","language":"Groovy","readme":"# GroovyMail\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\nGroovyMail aims to replace using JavaMail as the API to send email in Groovy by building a \ndomain specific language (DSL) on top of JavaMail to make sending email simpler.  GroovyMail \ncombines Groovy Templates and MarkupEngine to make sending rich email much easiser that using \nJavaMail alone.\n\n## Installation\n\nFor Gradle:\n\n     compile group: 'com.github.chubbard', name: 'groovymail', version: '0.1.0'\n\nFor Maven:\n\n      \u003cdependency\u003e\n        \u003cgroupId\u003ecom.github.chubbard\u003c/groupId\u003e\n        \u003cartifactId\u003egroovymail\u003c/artifactId\u003e\n        \u003cversion\u003e0.1.0\u003c/version\u003e\n      \u003c/dependency\u003e\n\n## Setup\n\nIn order for GroovyMail to work you need to setup the email configuration.  This is just\nthe properies [JavaMail](https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html) needs.  The simplest way to configure the mailer is to add the a\nproperties file to your classpath named \"emailer.properties\".  Here is an example:\n\n    mail.host=email.mydomain.com\n    mail.port=25\n    mail.transport.protocol=smtp\n    mail.smtp.auth=true\n    mail.smtp.from=noreply@mydomain.com\n    mail.smtp.user=someUser\n    mail.smtp.password=somePassword\n\nOr with SMTPS\n\n    mail.host=email.mydomain.com\n    mail.port=465\n    mail.transport.protocol=smtps\n    mail.smtps.auth=true\n    mail.smtps.from=noreply@mydomain.com\n    mail.smtps.user=someUser\n    mail.smtps.password=somePassword\n\nYou can change the filename used if you want to keep different versions for each environment.\nYou just need to pass the name to the constructor you want to use, and it will look for that\nfile on the classpath.\n\n## How to send email\n\nGroovyMail is based on the `Emailer` class.  Consider the `Emailer` something like a specific email \nserver, and it can be cached global so instantiate an `Emailer` in your program, and use it to send \nemail through that server.  For example:\n\n    Emailer emailer = new Emailer()\n    ...\n    \n    emailer.email(\"person@someDomain.com\", Some subject\")\n        .html(\"classpath:onboard_email.groovy\")\n        .bind(\"name\", \"Dan\")\n        .send() \n        \n    ...\n    \n    emailer.stop()\n\nSo the code above shows how the instantiation of the `Emailer` occurs at some point before you actually\nsend the email.  For example, that might be inside your dependency injection framework when your\ncontainer starts up, or at the beginning of your program, etc.  The `Emailer` instance is long living,\nand the final line is showing how when the emailer instance is being shutdown you need to call stop() \nmethod to clean it up.\n\nThe middle part is how email is actually addressed and sent.  Here is the breakdown:\n\n* **`email`** initiates an email you want to build.  It requires an email address for the to line, and\nthe subject of the Email.\n* **`html`** This method sets the content body of the message to be text/html and specifices the template\nto use to generate that content.  In this case we are loading the template off the classpath.\n* **`bind`** This method is used to pass data to the template during evaulation.  You may call this method\nas many times as you like to add additional data.  It takes a name and the underlying Object.  Templates\nmay refer to this object using the name given.\n* **`send`** This method evaluates all templates, constructs the email, and sends it.  \n\n### Template Example\n\nIn the above example we didn't show what the template looks like.  GroovyMail is based around groovy's\nawesome [MarkupTemplateEngine](http://groovy-lang.org/templating.html) which gives a lot of flexibility \nfor creating content.  Here is an example:\n\n    yieldUnescaped '\u003c!DOCTYPE html\u003e'\n    html(lang:'en') {\n        head {\n            meta( name: \"viewport\", content: \"width=device-width\" )\n            meta( \"http-equiv\": \"Content-Type\", content: \"text/html; charset=UTF-8\")\n        }\n        body {\n            p(\"Hi ${name}\"\n            p(\"\"\"\n                We've noticed you are interested in stuff we are doing, and we \n                love that you want to stay in the know with us.  Welcome aboard!\n            \"\"\")\n            p(\"Sincerely\")\n            p(\"Us\")\n        }\n    }\n\n## Other Examples\n\nHere are a few other examples of the API for common operations:\n\n### Asynchronous Emails\n\nYou can offload the sending of the email to a background thread using `sendAsync`:\n\n    emailer.emal(\"person@someDomain\", \"Welcome\" )\n        .html(\"classpath:welcome.groovy\")\n        .bind(\"name\", person.name )\n        .sendAsync()\n\n### Attach files:\n\n    emailer.email(\"person@someDomain.com\", \"Report\")\n        .html(\"classpath:report.groovy\")\n        .attach( pdfFile )\n        .bind( \"data\", data )\n        .send()\n        \n### bcc, cc, from:\n\n    emailer.email(\"person@someDomain.com\", \"Support Email\")\n        .bcc(\"support@myDomain.com\", \"manager@myDomain.com\")\n        .cc(\"otherPerson@someDomain.com\")        \n        .html(\"classpath:support.groovy\")\n        .bind(\"ticketId\", ticket.id )\n        .send(\"noreply@myDomain.com\")\n        \n### Multiple content:\n\nYou can add multiple formats to your emails like sending plain text and HTML using the following:\n\n    emailer.email(\"person@someDomain.com\", \"Welcome Aboard\")\n        .html(\"classpath:onboard_email_html.groovy\")\n        .text(\"classpath:onboard_email_text.groovy\")\n        .bind(\"user\", user)\n        .send()\n\n## Templates\n\nGroovyMail renders content using [MarkupTemplateEngine](http://groovy-lang.org/templating.html) \nfor an explanation of how content is generated and the features you can use it's suggested you \nvisit those pages.\n                \n### Locating templates\n\nBy default most templates are loaded off the classpath.  But you can also load them from directories\nand external locations to your application.  You can load them from any of these:\n \n* [File](https://docs.oracle.com/javase/8/docs/api/java/io/File.html)\n* [URL](https://docs.oracle.com/javase/8/docs/api/java/net/URL.html)\n* [Reader](https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html)\n\nThe URL is simply a string representing a URL (http:, file:, classpath:, etc).\n\n### Templates, Layouts, Default Look and Feel\n\nA very important part of Groovy's MarkupTemplateEngine is being able to define reusable \n[layouts](http://groovy-lang.org/templating.html#_layouts).  GroovyMail ships with some\ndefault layouts to make it easier to create responsive, pleasant looking emails.\n\n#### html5.groovy\n\nThis is just a bare HTML5 layout.  Here is an example of how to use it:\n\n    layout \"classpath:html5.groovy\", \n        title: \"My Email\", \n        css: \"some_file.css\", \n        bodyContent: contents {\n            p(\"Looks like Snow torrow.\")\n            table {\n                thead {\n                    tr {\n                        th(\"Day of Week\")\n                        th(\"Low\")\n                        th(\"High\")\n                        th(\"Conditions\")\n                    }\n                }\n                tbody {\n                    tr {\n                        td(\"Monday\")\n                        td(\"28F\")\n                        td(\"32F\")\n                        td(\"Snow\")\n                    }\n                    tr {\n                        td(\"Tuesday\")\n                        td(\"22F\")\n                        td(\"31F\")\n                        td(\"Snow\")\n                    }\n                    tr {\n                        td(\"Wednesday\")\n                        td(\"25F\")\n                        td(\"30F\")\n                        td(\"Cloudy\")\n                    }\n                    tr {\n                        td(\"Thursday\")\n                        td(\"24F\")\n                        td(\"33F\")\n                        td(\"Sunny\")\n                    }\n                    tr {\n                        td(\"Friday\")\n                        td(\"23F\")\n                        td(\"31F\")\n                        td(\"Sunny\")\n                    }\n                }\n            }\n        } \n\n#### Simplified\n\nSimplified is a series of templates and styles that helps you create modern style \nemails.\n\n##### simplified-responsive-layout.groovy\n\nThis gives you a single action responsive layout:\n\n    layout \"simplified-responsive-layout.groovy\",\n        title: 'Hello',\n        previewText: 'This is what will be displayed in some email clients as preview text.',\n        beforeActionContent: contents {\n            p(\"Hey there looks like you forgot something.  That's ok use the button below to reset your password.\")\n        },\n        actionText: \"Reset Password\",\n        actionLink: \"http://www.google.com\",\n        afterActionContent: contents {\n            p(\"If you didn't initiate this please alert your administrator or contact us.\")\n        },\n        footer: contents {\n            div {\n                span(class: \"apple-link\") {\n                    yield \"Fruit Company Inc, 100 Infinite Loop, Cupertino CA 94102\"\n                }\n                br()\n                span(\"Don't like these emails?\")\n                a(href: \"http://i.imgur.com/CScmqnj.gif\") {\n                    yield \"Unsubscribe\"\n                }\n            }\n        }\n \n The above shows all the parameters you can pass to the layout.  Here is a breakdown of what those do:\n \n * **`title`**  The title of the email some clients display this\n * **`previewText`** This is the preview text that might be displayed in the list of emails on some clients.\n * **`beforeActionContent`** This is a template to insert before the action button\n * **`actionText`** The text displayed to the user on the action button\n * **`actionLink`** The URL the user will visit if they click on the action button\n * **`afterActionContent`** A template to insert after the action button\n * **`footer`** A template to insert at the bottom of the email after the main area.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchubbard%2Fgroovymail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchubbard%2Fgroovymail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchubbard%2Fgroovymail/lists"}